Announcement

Collapse
No announcement yet.

%VK_OEM_PLUS vs %VK_ADD

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • %VK_OEM_PLUS vs %VK_ADD

    In one of my superclass routines I want to do the normal thing with the + and - that are top of the keyboard but another thing with the %VK_ADD and %VK_SUBTRACT. I'd like the + and - to be accepted and displayed by the textbox when typed using the top row of the keyboard and I want the + and - from the keypad to be used to trigger the finishing of the field and moving to the next. In our programs a lot of number entry makes it useful to hit the + key to enter the number as is and the - key to take the number entered and turn it negative.

    The top row + produces 16,187 keydown,43 char and 187,16 keyup.
    The numberpad + produces 107 keydown,43 char and 107 up.

    In the example below you can toggle insert and overwrite mode. Pressing the + key while in the middle of a word will truncate the rest of the field and go to the next field.

    Up/Down arrows work as do the normal editing options.
    +/- both work the same for text fields but in number fields the - will turn the value negative.

    I also am trying some code that I converted from a subclassed decimal routine I found in Poffs to work as a superclass. (Still working on this).

    Again I want the +- from the top row to work but the keypad +- to do their separate job.

    Code:
       #COMPILE EXE
       #REGISTER NONE
       #DIM ALL
       #INCLUDE "WIN32API.INC" 
       FUNCTION Validate(hdialog AS LONG,hctrlid AS LONG,sTxt AS STRING) AS LONG
         FUNCTION = 1 ' true allows navigation to next fields
       END FUNCTION
       GLOBAL FieldLen() AS LONG, FieldDec() AS LONG, VDSet() AS STRING,VR() AS STRING, VSET AS STRING,Keystrokes AS STRING
       GLOBAL V_INSOVR AS INTEGER 'INSERT/OVERWRITE FLAG
       FUNCTION CreateSuperClass(OldClassName AS STRING, NewClassName AS STRING, lpfnNewWndProc AS LONG, cbWndExtra AS LONG) AS LONG
          LOCAL wc AS WNDCLASSEX
          wc.cbSize = SIZEOF(wc)
          IF GetClassInfoEx(BYVAL 0&, BYVAL STRPTR(OldClassName), wc) THEN
             CallWindowProc lpfnNewWndProc, 0, 0, wc.lpfnWndProc, wc.cbWndExtra
             wc.hInstance = GetModuleHandle(BYVAL 0&)
             wc.lpszClassName = STRPTR(NewClassName)
             wc.lpfnWndProc = lpfnNewWndProc
             wc.cbWndExtra = wc.cbWndExtra + cbWndExtra
             FUNCTION = RegisterClassEx(wc)
          END IF
       END FUNCTION
       CALLBACK FUNCTION NEditProc
          STATIC OldProc AS LONG, OffsetWndExtra AS LONG
          LOCAL FieldLen AS LONG,V_NKEYPOS AS LONG,sTXT AS STRING,Txt AS ASCIIZ * %MAX_PATH 
          IF CBHNDL = 0 THEN OldProc = CBWPARAM: OffsetWndExtra = CBLPARAM: EXIT FUNCTION
          SELECT CASE CBMSG
             ' control navigation macro
         CASE %WM_GETDLGCODE
            FUNCTION = %DLGC_WANTALLKEYS: EXIT FUNCTION
         CASE %WM_KEYDOWN
           SELECT CASE CBWPARAM
             CASE %VK_UP
               CONTROL GET TEXT GetParent(CBHNDL),getdlgctrlid(CBHNDL) to sTXT$
               IF Validate(GetParent(CBHNDL),getdlgctrlid(CBHNDL),sTXT$) THEN
                 SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, -1)
                 EXIT FUNCTION
               END IF
             CASE %VK_TAB
               IF GetAsyncKeyState(%VK_SHIFT) THEN
                 SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, -1)
               ELSE
                 SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
               END IF
               EXIT FUNCTION
             CASE %VK_DOWN,%VK_RETURN
               SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
               EXIT FUNCTION
             CASE %VK_F 'find routine
               IF GetAsyncKeyState(%VK_CONTROL) THEN
                 CONTROL SET TEXT GetParent(CBHNDL),getdlgctrlid(CBHNDL),"Ctrl+F"
                 EXIT FUNCTION
               END IF
             CASE %VK_INSERT
               IF NOT V_INSOVR THEN
                 V_INSOVR = -1
               SetWindowText GetParent(CBHNDL),"OVR"   
               ELSEIF V_INSOVR THEN
                 V_INSOVR = 0
               SetWindowText GetParent(CBHNDL),"INS"   
               END IF
             CASE %VK_ADD
               SendMessage CBHNDL, %EM_GETSEL, 0, 0 TO V_NKEYPOS&     'Used to detect when field is filled           
               V_NKEYPOS& = LOWRD(V_NKEYPOS&)
               CONTROL GET TEXT GetParent(CBHNDL),GetDlgCtrlid(CBHNDL) TO sTxt
               sTxt = LEFT$(sTxt,V_NKEYPOS&)
               CONTROL SET TEXT GetParent(CBHNDL),GetDlgCtrlid(CBHNDL),sTxt
               SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
             CASE %VK_SUBTRACT  
               SendMessage CBHNDL, %EM_GETSEL, 0, 0 TO V_NKEYPOS&     'Used to detect when field is filled           
               V_NKEYPOS& = LOWRD(V_NKEYPOS&)
               CONTROL GET TEXT GetParent(CBHNDL),GetDlgCtrlid(CBHNDL) TO sTxt
               sTxt = LEFT$(sTxt,V_NKEYPOS&)
               IF VAL(sTxt) > 0 THEN
                 sTXT = "-" + TRIM$(sTxt)
               END IF
               CONTROL SET TEXT GetParent(CBHNDL),GetDlgCtrlid(CBHNDL),sTxt
               SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
           END SELECT
         CASE %WM_KEYUP
           CONTROL SEND GetParent(CBHNDL),getdlgctrlid(CBHNDL), %EM_GETSEL, 0, 0 TO V_NKEYPOS&     'Used to detect when field is filled           
           IF LOWRD(V_NKEYPOS&) = FieldLen(getdlgctrlid(CBHNDL)) THEN
             SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
             EXIT FUNCTION
           END IF
             CASE %WM_SETFOCUS
               SendMessage CBHNDL, %EM_SETSEL, 0, -1
             CASE %WM_CHAR
               IF INSTR("+-",CHR$(CBWPARAM)) > 0 THEN EXIT FUNCTION
               IF V_INSOVR THEN
                 SendMessage CBHNDL, %EM_GETSEL, 0, 0 TO V_NKEYPOS&     'Used to detect when field is filled           
                 V_NKEYPOS& = LOWRD(V_NKEYPOS&)
                 SendMessage CBHNDL, %EM_SETSEL,V_NKEYPOS&,V_NKEYPOS& + 1  'Selects current character
                 SendMessage CBHNDL, %WM_CLEAR,0,0                       'If nothing to clear doesn't act
               END IF
          END SELECT
          FUNCTION = CallWindowProc(OldProc, CBHNDL, CBMSG, CBWPARAM, CBLPARAM)
       END FUNCTION
       CALLBACK FUNCTION NMoneyProc
          STATIC OldProc AS LONG, OffsetWndExtra AS LONG
          LOCAL FieldLen AS LONG,V_NKEYPOS AS LONG,sTXT AS STRING
          DIM  Dpnt  AS LOCAL LONG
          DIM  hWnd   AS LOCAL DWORD
          DIM  Mlen  AS LOCAL LONG
          DIM  Tlen  AS LOCAL LONG
          DIM  Txt   AS LOCAL ASCIIZ * %MAX_PATH
          DIM  Value AS LOCAL DOUBLE
          IF CBHNDL = 0 THEN OldProc = CBWPARAM: OffsetWndExtra = CBLPARAM: EXIT FUNCTION
          SELECT CASE CBMSG
             ' control navigation macro
         CASE %WM_GETDLGCODE
            FUNCTION = %DLGC_WANTALLKEYS: EXIT FUNCTION
         CASE %WM_KEYDOWN
           SELECT CASE CBWPARAM
             CASE %VK_UP
               CONTROL GET TEXT GetParent(CBHNDL),getdlgctrlid(CBHNDL) to sTXT$
               IF Validate(GetParent(CBHNDL),getdlgctrlid(CBHNDL),sTXT$) THEN
                 SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, -1)
                 EXIT FUNCTION
               END IF
             CASE %VK_TAB
               IF GetAsyncKeyState(%VK_SHIFT) THEN
                 SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, -1)
               ELSE
                 SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
               END IF
               EXIT FUNCTION
             CASE %VK_DOWN,%VK_RETURN
               SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
               EXIT FUNCTION
             CASE %VK_F 'find routine
               IF GetAsyncKeyState(%VK_CONTROL) THEN
                 CONTROL SET TEXT GetParent(CBHNDL),getdlgctrlid(CBHNDL),"Ctrl+F"
                 EXIT FUNCTION
               END IF
             CASE %VK_INSERT
               IF NOT V_INSOVR THEN
                 V_INSOVR = -1
               SetWindowText GetParent(CBHNDL),"OVR"   
               ELSEIF V_INSOVR THEN
                 V_INSOVR = 0
               SetWindowText GetParent(CBHNDL),"INS"   
               END IF
             CASE %VK_ADD
               SendMessage CBHNDL, %EM_GETSEL, 0, 0 TO V_NKEYPOS&     'Used to detect when field is filled           
               V_NKEYPOS& = LOWRD(V_NKEYPOS&)
               CONTROL GET TEXT GetParent(CBHNDL),GetDlgCtrlid(CBHNDL) TO sTxt
               sTxt = LEFT$(sTxt,V_NKEYPOS&)
               CONTROL SET TEXT GetParent(CBHNDL),GetDlgCtrlid(CBHNDL),sTxt
               SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
             CASE %VK_SUBTRACT  
               SendMessage CBHNDL, %EM_GETSEL, 0, 0 TO V_NKEYPOS&     'Used to detect when field is filled           
               V_NKEYPOS& = LOWRD(V_NKEYPOS&)
               CONTROL GET TEXT GetParent(CBHNDL),GetDlgCtrlid(CBHNDL) TO sTxt
               sTxt = LEFT$(sTxt,V_NKEYPOS&)
               IF VAL(sTxt) > 0 THEN
                 sTXT = "-" + TRIM$(sTxt)
               END IF
               CONTROL SET TEXT GetParent(CBHNDL),GetDlgCtrlid(CBHNDL),sTxt
               SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
           END SELECT
         CASE %WM_KEYUP
           CONTROL SEND GetParent(CBHNDL),getdlgctrlid(CBHNDL), %EM_GETSEL, 0, 0 TO V_NKEYPOS&     'Used to detect when field is filled           
           IF LOWRD(V_NKEYPOS&) = FieldLen(getdlgctrlid(CBHNDL)) THEN
             SetFocus GetNextDlgTabItem(GetParent(CBHNDL), CBHNDL, 0)
             EXIT FUNCTION
           END IF
             CASE %WM_PASTE                              
                'more handling for error
                EXIT FUNCTION                                       
             CASE %WM_CHAR      
               IF CBWPARAM < 32 THEN EXIT SELECT                   ' BkSpc, Tab, etc pass these on
               IF CBWPARAM > 57 THEN EXIT FUNCTION                 ' > "9" not legal
               IF CBWPARAM = 47 THEN EXIT FUNCTION                 ' "/" not legal
               IF CBWPARAM < 46 THEN EXIT FUNCTION                 ' < "." not legal
               Tlen = GetWindowTextLength(CBHNDL)                  ' current text length 
               IF Tlen = 0 THEN EXIT SELECT                        ' anything goes here!
               GetWindowText CBHNDL, Txt, %MAX_PATH                ' get current text
               Dpnt = INSTR(Txt,".")                               ' find "."
               IF CBWPARAM = 46 THEN                               ' "." was input
                 IF Dpnt > 0 THEN EXIT FUNCTION                  ' can't have 2
               ELSEIF Dpnt > 0 THEN                              ' already working on decimal value
                 IF Dpnt + FieldDec(getdlgctrlid(CBHNDL)) = Tlen THEN EXIT FUNCTION           ' can't have more than 2 places past decimal
               ELSE                                              ' digits 0 -> 9
                 Mlen = FieldLen(getdlgctrlid(CBHNDL)) ' max length
                 IF Tlen = Mlen - FieldDec(getdlgctrlid(CBHNDL)) - 1 THEN EXIT FUNCTION             ' can't have more whole numbers than this
               END IF                                              '
             CASE %WM_SETFOCUS
               GetWindowText CBHNDL, Txt, %MAX_PATH
               Txt = REMOVE$(Txt,",")
               SetWindowText CBHNDL, Txt
               SendMessage CBHNDL, %EM_SETSEL, 0, -1
             CASE %WM_KILLFOCUS
               GetWindowText CBHNDL, Txt, %MAX_PATH
               Value = Val(Txt)
               Txt   = FORMAT$(Value, "0,." + STRING$(FieldDec(getdlgctrlid(CBHNDL)),"0"))
               SetWindowText CBHNDL, Txt   
          END SELECT
          FUNCTION = CallWindowProc(OldProc, CBHNDL, CBMSG, CBWPARAM, CBLPARAM)
       END FUNCTION
    
       FUNCTION PBMAIN
          IF ISFALSE(CreateSuperClass("EDIT", "NEdit", CODEPTR(NEditProc), 4)) THEN EXIT FUNCTION
          IF ISFALSE(CreateSuperClass("EDIT", "NMoney", CODEPTR(NMoneyProc), 4)) THEN EXIT FUNCTION
          DIM FieldLen(1000:2000),FieldDec(1000:2000),VDSet(1000:2000) 
    
          LOCAL hDlg AS LONG, i AS LONG
          DIALOG NEW 0, "Test", , , 200, 300, %WS_CAPTION OR %WS_SYSMENU OR %WS_MAXIMIZEBOX TO hDlg
    
    
          CONTROL ADD "Static",hDlg, 2003,"String",10,35,40,14,%SS_LEFT OR %WS_VISIBLE OR %WS_CHILD OR %SS_NOTIFY,%WS_EX_LEFT
          CONTROL ADD "NEdit", hDlg, 1003, "", 50, 35, 100, 14, _
             %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP, %WS_EX_CLIENTEDGE
    
             CONTROL SEND hDlg,1003,%EM_LIMITTEXT,20,0: FieldLen(1003) = 20 
    
          CONTROL ADD "Static",hDlg, 2004,"String",10,50,40,14,%SS_LEFT OR %WS_VISIBLE OR %WS_CHILD OR %SS_NOTIFY,%WS_EX_LEFT
          CONTROL ADD "NEdit",  hDlg, 1004, "", 50, 50, 100, 14, _
             %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP, %WS_EX_CLIENTEDGE
    
             CONTROL SEND hDlg,1004,%EM_LIMITTEXT,20,0: FieldLen(1004) = 20
             
          CONTROL ADD "Static",hDlg, 2005,"Money",10,65,40,14,%SS_LEFT OR %WS_VISIBLE OR %WS_CHILD,%WS_EX_LEFT
          CONTROL ADD "NMoney", hDlg,1005, "", 50, 65, 48, 14, _
            %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %ES_RIGHT, %WS_EX_CLIENTEDGE   
    
             CONTROL SEND hDlg,1005,%EM_LIMITTEXT,10,0: FieldLen(1005) = 10: FieldDec(1005) = 4
                      
    
          DIALOG SHOW MODAL hDlg
       END FUNCTION
    Bob Mechler
    Last edited by BOB MECHLER; 24 Jun 2008, 03:08 PM. Reason: Incomplete code posting

  • #2
    The following I found to distinguish between the -+ on the top row and the number pad.
    Code:
             CASE %WM_CHAR
               KeyState = GetAsyncKeyState(%VK_OEM_MINUS) OR GetAsyncKeyState(%VK_OEM_PLUS)
               IF INSTR("+-",CHR$(CBWPARAM)) > 0 AND KeyState <> &H8001 THEN EXIT FUNCTION

    Comment

    Working...
    X