Announcement

Collapse
No announcement yet.

Listview Question

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

  • Listview Question

    Hi All,

    How can I stop a listview from receiving commands from the keyboard when its in focus.

    I'm trying to generate a dialog with a listview and a static label box, using a keyboard hook routine I want to be able to intercept the keypresses + update the text in the static label box and then depending on whats in this box show the closest match in the list view.

    So far I've got the dialog created with all of the controls and I have the keyboard hook routine working. Only problem is that when I start to type the listview selected row changes depending on the last key pressed.

  • #2
    >How can I stop a listview from receiving commands from the keyboard when its in focus

    ???

    The whole idea of keyboard focus is to get those notification messages. If you don't want 'em, ignore 'em. Or, don't let the listview get the keyboard focus. (On WM_NOTIFY/NM_SETFOCUS, just set the focus elsewhere).

    I have the keyboard hook routine working....Only problem is that when I start to type the listview selected row changes depending on the last key pressed.
    I might suggest that perhaps your hook routine is not working as well as you might like it.

    Into what control are these keypresses being entered? You should not need a keyboard hook to update a static control and select a different row of the listview control based on user-entered keys; even the lowly edit control will send a notification message every time a character is changed and you can "do stuff" at that time.
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      The idea is that the listview stays focussed.

      The control that is displaying the "typed string" is just a static label. I test for backspace in the keyboard hook and delete characters etc.

      The keyhook also tests for up and down arrow and the moves the selected row in the listview to suit.

      As each character is typed the static label is updated and a quick search of the contents of the listview is performed and the best match is then automatically selected.

      Comment


      • #4
        If the listview stays focused, it gets all keyboard input, which means you get notifucation messages.

        If you're not interested in them, ignore them or subclass the control to eat 'em. (No I will not show you how, because A) there are examples elsewhere and B) I'm almost ashamed of myself for suggesting something this silly).

        Why not let the user type into an edit control? That handles delete keys, it shows what has been typed, and if the user tries to set the focus to the listview control, you can just redirect focus to that edit control.

        Seems to me you are doing something not just the hard way, but the REALLY hard way.

        You can do everything you want to do without a kyeboard hook. If you want to pick up up and down arrow from the edit control you'll have to subclass it, but as I said there are examples of this here.
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          There are two ways to approach this:

          You could trap keyboard messages destined for the listview control in the message loop and reroute them to another control or the dialog itself. You have to change the Msg structure so it has a different window handle for the message than the listview.

          Second, you could subclass the listview control and then process the WM_GETDLGCODE message and return the value:

          %DLGC_STATIC

          The Dialog will send this message to the control which has the focus, to determine whether it wants the keyboard input or not and what specific keys are needed. By returning DLGC_STATIC the listview should be able to tell the dialog it does not want any keys. I haven't tried this, but in theory it should work.
          Chris Boss
          Computer Workshop
          Developer of "EZGUI"
          http://cwsof.com
          http://twitter.com/EZGUIProGuy

          Comment


          • #6
            Thanks everyone for the posts. I'm unsure how to implement your suggestions,

            I have put together a complete executable example of what I have so far.

            Code:
            ' SED_PBWIN
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            %SelectListEntryListBox = 974		' ----------- SELECT LIST ENTRY EQUATES ----------
            %SelectListEntrySearchTextBox = 975
            %SelectListEntryCancelButton = 976
            %SelectListEntryOKButton = 977		' ----------- END OF SELECT LIST ENTRY EQUATES ----------
            %MOD_ALT = &H00000001		' Keyboard Hook
            %MOD_CONTROL = &H00000002		' Keyboard Hook
            %MOD_SHIFT = &H00000004		' Keyboard Hook
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            #COMPILE EXE
            #DIM ALL
            #DEBUG ERROR ON
            #TOOLS ON
            #INCLUDE "WIN32API.INC"
            #INCLUDE "COMMCTRL.INC"
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            DECLARE FUNCTION Show_Get_List_Selection_Dialog( BYVAL hParent AS DWORD, DialogTitle AS STRING, CursorLine AS LONG, BYVAL DiagWidth AS LONG _
              , BYVAL DiagHeight AS LONG, GetListSelectArray_GL( ) AS STRING, BYVAL IncLineNums AS LONG, BYVAL AllowMulSel AS LONG ) AS LONG
            DECLARE CALLBACK FUNCTION Get_List_Selection_Proc( )
            DECLARE FUNCTION Get_ListBox_Rows_Selected( BYVAL Winhandle AS DWORD, BYVAL ListBoxID AS LONG ) AS STRING
            DECLARE FUNCTION Convert_Keyboard_Hook_Code( BYVAL CBLPARAM_PARSED AS DWORD, BYVAL CBWPARAM_PARSED AS DWORD, BYVAL Return_Alt_Shift_Etc AS LONG ) AS STRING
            DECLARE SUB Add_Columns_To_List_View( BYVAL WinHandle AS DWORD, BYVAL ListViewID AS LONG, BYVAL ListBoxHeaders AS STRING )
            DECLARE SUB Populate_List_View( BYVAL WinHandle AS DWORD, ListViewID AS LONG, ListViewDataArray( ) AS STRING, BYVAL ListViewArrayQty AS QUAD, BYVAL ListViewColQty AS LONG, BYVAL CursorLine AS LONG )
            DECLARE FUNCTION KeyBoardProc( BYVAL iCode AS INTEGER, BYVAL wParam AS DWORD, BYVAL lParam AS LONG ) AS DWORD
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            GLOBAL CallBack_SR_String1_GL AS STRING
            GLOBAL TempListArray_Row_Qty_GL AS LONG
            GLOBAL TempListArray_Col_Qty_GL AS LONG
            GLOBAL TempListArray_GL( ) AS STRING
            GLOBAL GetListSelectArray_GL( ) AS STRING
            GLOBAL Current_Keyboard_Hook_DlgHan_GL AS DWORD
            GLOBAL ghKeyb AS DWORD		' global handles for keyboard hook
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            FUNCTION PBMAIN
              '
              LOCAL TL1 AS LONG
              '
              ghKeyb = SETWINDOWSHOOKEX( %WH_KEYBOARD, CODEPTR( KeyBoardProc ), 0, GETCURRENTTHREADID )		' Keyboard Hook
              '
              REDIM TempHeldDispArray( 1 TO 10, 1 TO 3 ) AS STRING
              '
              FOR TL1 = 1 TO 10
                '
                TempHeldDispArray( TL1, 1 ) = FORMAT$( RND( 1, 100 ))
                TempHeldDispArray( TL1, 2 ) = PARSE$( "Anita Smith/Andrew/Alex/Amanda/Adrian/Ciaran/Christopher Smith/Christopher Brown/Andrew Green/Anita Brown", "/", TL1 ) + STR$( RND( 1, 10 ))
                TempHeldDispArray( TL1, 3 ) = FORMAT$( RND( 1, 100 ))
                '
              NEXT TL1
              '
              CALL Show_Get_List_Selection_Dialog( 0, "Test List" + $CR + "Created,Company / Surname,Value*," + $CR + $CR + "1,2,3", 1, 465, 310, TempHeldDispArray( ), %FALSE, %FALSE )
              '
              IF CallBack_SR_String1_GL = "" THEN
                MSGBOX "Canelled Select"
              ELSE
                MSGBOX "Selected Line " + CallBack_SR_String1_GL
              END IF
              '
              UNHOOKWINDOWSHOOKEX ghKeyb
              '
            END FUNCTION
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            FUNCTION Show_Get_List_Selection_Dialog( BYVAL hParent AS DWORD, DialogTitle AS STRING, CursorLine AS LONG, BYVAL DiagWidth AS LONG, BYVAL DiagHeight AS LONG, GetListSelectArray_GL( ) AS STRING, BYVAL IncLineNums AS LONG, BYVAL AllowMulSel AS LONG ) AS LONG
              '
              ON ERROR GOTO Show_Get_List_Selection_Dialog_Error_Handler
              '
              ' first entry is the default list view cursor
              LOCAL hDlg AS DWORD
              LOCAL TL1 AS LONG
              LOCAL TL2 AS LONG
              LOCAL TS1 AS STRING
              '
              ' Parse$( DialogTitle, $CR, 1) = Dialog Title
              ' Parse$( DialogTitle, $CR, 2) = List Of Column Headers
              ' Parse$( DialogTitle, $CR, 3) = Overiding Font Handle
              ' Parse$( DialogTitle, $CR, 4) = Columns To Perform Quick Lookup On [ 1,4,5,7 ] : If None Then Then Use All
              '
              CallBack_SR_String1_GL = PARSE$( DialogTitle, $CR, 4 )
              '
              TempListArray_Row_Qty_GL = UBOUND( GetListSelectArray_GL( ), 1 )
              TempListArray_Col_Qty_GL = UBOUND( GetListSelectArray_GL( ), 2 ) + 2
              '
              REDIM TempListArray_GL( 1 TO TempListArray_Row_Qty_GL, 1 TO TempListArray_Col_Qty_GL ) AS GLOBAL STRING
              '
              FOR TL1 = 1 TO TempListArray_Row_Qty_GL
                '
                IF IncLineNums = %TRUE THEN
                  TempListArray_GL( TL1, 1 ) = FORMAT$( TL1 )
                END IF
                '
                FOR TL2 = 1 TO UBOUND( GetListSelectArray_GL( ), 2 )
                  '
                  TempListArray_GL( TL1, TL2 - ( IncLineNums = %TRUE )) = GetListSelectArray_GL( TL1, TL2 )
                  '
                NEXT TL2
                '
              NEXT TL1
              '
              DIALOG NEW hParent, PARSE$( DialogTitle, $CR, 1 ),,, DiagWidth, DiagHeight, _
                %WS_POPUP OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                %WS_VISIBLE OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
                %WS_EX_WINDOWEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
                %WS_EX_RIGHTSCROLLBAR, TO hDlg
              '
              CONTROL ADD "SysListView32", hDlg, %SelectListEntryListBox, "SysListView32_1", 10, 10, DiagWidth - 20, DiagHeight - 40, _
                %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %WS_TABSTOP OR %LVS_REPORT OR - %LVS_SINGLESEL * ( AllowMulSel = %FALSE ) OR _
                %LVS_SHOWSELALWAYS, %WS_EX_LEFT OR %WS_EX_RIGHTSCROLLBAR
              TS1 = PARSE$( DialogTitle, $CR, 3 )
              IF TS1 <> "" THEN
                CONTROL SEND hDlg, %SelectListEntryListBox, %WM_SETFONT, VAL( TS1 ), 0
              END IF
              CALL Add_Columns_To_List_View( hDlg, %SelectListEntryListBox, PARSE$( DialogTitle, $CR, 2 ))
              '
              CONTROL ADD TEXTBOX, hDlg, %SelectListEntrySearchTextBox, "", 10, DiagHeight - 25, DiagWidth - 160, 12, _
                %WS_CHILD OR %WS_VISIBLE OR %ES_LEFT OR %ES_READONLY OR %WS_GROUP OR %WS_TABSTOP, %WS_EX_CLIENTEDGE OR _
                %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
              '
              CONTROL ADD BUTTON, hDlg, %SelectListEntryCancelButton, "Cancel", DiagWidth - 140, DiagHeight - 25, 60, 20
              CONTROL ADD BUTTON, hDlg, %SelectListEntryOKButton, "Select", DiagWidth - 70, DiagHeight - 25, 60, 20, %BS_DEFPUSHBUTTON
              CALL Populate_List_View( hDlg, - %SelectListEntryListBox, TempListArray_GL( ), TempListArray_Row_Qty_GL, UBOUND( GetListSelectArray_GL( ), 2 ) - ( IncLineNums = %TRUE ), CursorLine )
              '
              DIALOG SHOW MODAL hDlg, CALL Get_List_Selection_Proc
              '
              EXIT FUNCTION
              '
            Show_Get_List_Selection_Dialog_Error_Handler :
              '
              MSGBOX "Show_Get_List_Selection_Dialog Error" + STR$( ERR ), %MB_ICONERROR OR %MB_TASKMODAL, "Epos"
              '
            END FUNCTION
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            CALLBACK FUNCTION Get_List_Selection_Proc( )
              '
              ON ERROR GOTO Get_List_Selection_Proc_Error_Handler
              '
              LOCAL TL1 AS LONG
              LOCAL TL2 AS LONG
              LOCAL TL3 AS LONG
              LOCAL TS1 AS STRING
              LOCAL TS2 AS STRING
              LOCAL TS3 AS STRING
              LOCAL MS AS STRING
              LOCAL SM AS STRING
              LOCAL SearchWordsQty AS LONG
              '
              SELECT CASE AS LONG CBMSG
                  '
                CASE %WM_INITDIALOG
                  '
                  DIM ListPos_ST AS STATIC LONG
                  DIM XCursor_ST AS STATIC LONG
                  DIM CursorFlag_ST AS STATIC LONG
                  DIM IDT_TIMER_ST AS STATIC LONG
                  DIM InpString AS STATIC STRING
                  '
                  InpString = ""
                  '
                  IDT_TIMER_ST = %WM_USER + 2500
                  SETTIMER CBHNDL, IDT_TIMER_ST, 500, BYVAL %NULL
                  '
                  Current_Keyboard_Hook_DlgHan_GL = CBHNDL
                  '
                  ListPos_ST = VAL( Get_ListBox_Rows_Selected( CBHNDL, %SelectListEntryListBox ))
                  '
                CASE %WM_NOTIFY
                  '
                  '
                CASE %WM_DESTROY
                  '
                  KILLTIMER CBHNDL, IDT_TIMER_ST
                  '
                CASE %WM_TIMER
                  '
                  CursorFlag_ST = CursorFlag_ST XOR 1
                  '
                  IF CursorFlag_ST = 0 THEN
                    CONTROL SET TEXT CBHNDL, %SelectListEntrySearchTextBox, InpString
                  ELSE
                    IF XCursor_ST = LEN( InpString ) THEN
                      TS1 = InpString + "_"
                    ELSE
                      TS1 = InpString
                      MID$( TS1, XCursor_ST + 1, 1 ) = "_"
                    END IF
                    CONTROL SET TEXT CBHNDL, %SelectListEntrySearchTextBox, TS1
                  END IF
                  '
                CASE %WM_NCACTIVATE
                  '
                CASE %WM_SYSCOMMAND
                  '
                  SELECT CASE CBWPARAM AND &hFFF0
                    CASE %SC_CLOSE
                      CallBack_SR_String1_GL = ""
                      DIALOG END CBHNDL
                  END SELECT
                  '
                CASE %WM_HELP
                  '
                  MSGBOX "Help"
                  '
                CASE %WM_USER + 101
                  '
                  TS3 = InpString
                  '
                  TS2 = Convert_Keyboard_Hook_Code( CBLPARAM, CBWPARAM, %FALSE )
                  '
                  IF LEN( TS2 ) = 1 THEN
                    InpString = InpString + TS2
                    IF RIGHT$( TS1, 2 ) = "  " THEN
                      InpString = LEFT$( InpString, - 1 )
                    END IF
                    XCursor_ST = LEN( InpString )
                  ELSEIF TS2 = "BackSpace" THEN
                    InpString = LEFT$( InpString, LEN( InpString ) - 1 )
                    XCursor_ST = LEN( InpString )
                  ELSEIF TS2 = "Up Arrow" THEN
                    DECR ListPos_ST
                    IF ListPos_ST = 0 THEN
                      ListPos_ST = 1
                    END IF
                  ELSEIF TS2 = "Down Arrow" THEN
                    INCR ListPos_ST
                    IF ListPos_ST > TempListArray_Row_Qty_GL THEN
                      ListPos_ST = TempListArray_Row_Qty_GL
                    END IF
                  ELSEIF TS2 = "Left Arrow" AND InpString <> "" AND 1 = 2 THEN
                    DECR XCursor_ST
                    IF XCursor_ST < 0 THEN
                      XCursor_ST = 0
                    END IF
                  ELSEIF TS2 = "Right Arrow" AND InpString <> "" AND 1 = 2 THEN
                    INCR XCursor_ST
                    IF XCursor_ST > LEN( InpString ) THEN
                      XCursor_ST = LEN( InpString )
                    END IF
                  END IF
                  '
                  InpString = LTRIM$( InpString )
                  '
                  IF InpString <> "" AND InpString <> TS3 THEN
                    '
                    SM = UCASE$( TRIM$( InpString ))
                    '
                    SearchWordsQTY = PARSECOUNT( SM, $SPC )
                    '
                    FOR TL1 = 1 TO TempListArray_Row_Qty_GL
                      '
                      MS = ""
                      '
                      FOR TL2 = 1 TO TempListArray_Col_Qty_GL
                        '
                        IF CallBack_SR_String1_GL = "" OR INSTR( CallBack_SR_String1_GL + ",", FORMAT$( TL2 ) + "," ) <> 0 THEN
                          '
                          MS = MS + UCASE$( TempListArray_GL( TL1, TL2 )) + $SPC
                          '
                        END IF
                        '
                      NEXT TL2
                      '
                      FOR TL3 = 1 TO SearchWordsQTY
                        '
                        IF INSTR( MS, PARSE$( SM, $SPC, TL3 )) = 0 THEN
                          EXIT FOR
                        END IF
                        '
                      NEXT TL3
                      '
                      IF TL3 = SearchWordsQTY + 1 THEN
                        EXIT FOR
                      END IF
                      '
                    NEXT TL1
                    '
                    IF TL1 <> TempListArray_Row_Qty_GL + 1 THEN
                      ListPos_ST = TL1
                    END IF
                    '
                  END IF
                  '
                  CONTROL SET TEXT CBHNDL, %SelectListEntrySearchTextBox, InpString
                  '
                  DIALOG POST CBHNDL, %WM_USER + 102, 1, 1
                  '
                CASE %WM_USER + 102
                  '
                  CONTROL HANDLE CBHNDL, %SelectListEntryListBox TO TL1
                  Listview_SetItemState( TL1, ListPos_ST - 1, %LVIS_SELECTED OR %LVIS_FOCUSED, %LVIS_SELECTED OR %LVIS_FOCUSED )
                  CONTROL SET FOCUS CBHNDL, %SelectListEntryListBox
                  '
                CASE %WM_COMMAND
                  '
                  IF CBCTLMSG = %BN_CLICKED THEN
                    '
                    SELECT CASE CBCTL
                        '
                      CASE %SelectListEntryOKButton
                        '
                        TL1 = VAL( Get_ListBox_Rows_Selected( CBHNDL, %SelectListEntryListBox ))
                        CallBack_SR_String1_GL = FORMAT$( TL1 )
                        DIALOG END CBHNDL
                        '
                      CASE %SelectListEntryCancelButton, %IDCANCEL
                        '
                        CallBack_SR_String1_GL = ""
                        DIALOG END CBHNDL
                        '
                    END SELECT
                    '
                  END IF
                  '
              END SELECT
              '
              EXIT FUNCTION
              '
            Get_List_Selection_Proc_Error_Handler :
              '
              MSGBOX "Get_List_Selection_Proc Error" + STR$( ERR ), %MB_ICONERROR OR %MB_TASKMODAL, "Epos"
              '
            END FUNCTION
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            FUNCTION Get_ListBox_Rows_Selected( BYVAL Winhandle AS DWORD, BYVAL ListBoxID AS LONG ) AS STRING
              '
              ON ERROR GOTO Get_ListBox_Rows_Selected_Error_Handler
              '
              LOCAL ListViewHandle AS DWORD
              DIM tLV_Item AS LOCAL LV_ITEM
              LOCAL ListViewRow AS LONG
              LOCAL hLV_Item AS DWORD
              LOCAL Selected AS STRING		' ",1,5,8,9" etc
              '
              ListViewHandle = GETDLGITEM( WinHandle, ListBoxID )
              '
              ListViewRow = SENDMESSAGE( ListViewHandle, %LVM_GETITEMCOUNT, 0, 0 )
              tLV_Item.isubitem = 0
              tLV_Item.mask = %LVIF_STATE
              tLV_Item.statemask = %LVIS_SELECTED
              hLV_Item = VARPTR( tLV_Item )
              '
              WHILE ListViewRow > 0
                DECR ListViewRow
                tLV_Item.iitem = ListViewRow
                IF SENDMESSAGE( ListViewHandle, %LVM_GETITEM, 0, BYVAL hLV_Item ) = 0 THEN
                  ITERATE
                END IF
                IF tLV_Item.State = %LVIS_SELECTED THEN
                  Selected = "," + FORMAT$( ListViewRow + 1 ) + Selected
                END IF
              WEND
              '
              FUNCTION = MID$( Selected, 2 )
              '
              EXIT FUNCTION
              '
            Get_ListBox_Rows_Selected_Error_Handler :
              '
              MSGBOX "Get_ListBox_Rows_Selected Error" + STR$( ERR ), %MB_ICONERROR OR %MB_TASKMODAL, "Epos"
              '
            END FUNCTION
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            FUNCTION Convert_Keyboard_Hook_Code( BYVAL CBLPARAM_PARSED AS DWORD, BYVAL CBWPARAM_PARSED AS DWORD, BYVAL Return_Alt_Shift_Etc AS LONG ) AS STRING
              '
              LOCAL TS1 AS STRING
              '
              ' check shift mode info by processing lParam
              '
              IF Return_Alt_Shift_Etc = %TRUE THEN
                '
                IF ( CBLPARAM_PARSED AND %MOD_ALT ) THEN
                  TS1 = "Alt+"
                END IF
                '
                IF ( CBLPARAM_PARSED AND %MOD_CONTROL ) THEN
                  TS1 = TS1 + "Ctrl+"
                END IF
                '
                IF ( CBLPARAM_PARSED AND %MOD_SHIFT ) THEN
                  TS1 = TS1 + "Shift+"
                END IF
                '
              END IF
              '
              ' now check which key (virt. key code or ASCII code) has been pressed
              '
              SELECT CASE AS LONG CBWPARAM_PARSED
                  '
                CASE 8
                  '
                  TS1 = TS1 + "BackSpace"
                  '
                CASE 9
                  '
                  TS1 = TS1 + "Tab"
                  '
                CASE %VK_PGUP
                  '
                  TS1 = TS1 + "PgUp"
                  '
                CASE %VK_PGDN
                  '
                  TS1 = TS1 + "PgDn"
                  '
                CASE %VK_END
                  '
                  TS1 = TS1 + "End"
                  '
                CASE %VK_HOME
                  '
                  TS1 = TS1 + "Home"
                  '
                CASE %VK_LEFT
                  '
                  TS1 = TS1 + "Left Arrow"
                  '
                CASE %VK_UP
                  '
                  TS1 = TS1 + "Up Arrow"
                  '
                CASE %VK_RIGHT
                  '
                  TS1 = TS1 + "Right Arrow"
                  '
                CASE %VK_DOWN
                  '
                  TS1 = TS1 + "Down Arrow"
                  '
                CASE %VK_INSERT
                  '
                  TS1 = TS1 + "Ins"
                  '
                CASE %VK_DELETE
                  '
                  TS1 = TS1 + "Del"
                  '
                CASE %VK_F1
                  '
                  SELECT CASE AS LONG CBLPARAM_PARSED
                      '
                    CASE 0, _		' no shift keys pressed
                        %MOD_CONTROL, _		' Ctrl pressed
                        %MOD_SHIFT, _		' Shift pressed
                        %MOD_CONTROL + %MOD_SHIFT, _		' Ctrl + Shift pressed
                        %MOD_ALT + %MOD_CONTROL + %MOD_SHIFT		' Alt + Ctrl + Shift pressed
                      ' NOTE: F1, Ctrl/F1, Shift/F1, Ctrl/Shift/F1 and Alt/Ctrl/Shift/F1 fire the %WM_HELP message
                      ' so let %WM_HELP do the job and exit here
                      EXIT FUNCTION
                      '
                  END SELECT
                  '
                  TS1 = TS1 + "F1"
                  '
                CASE %VK_F2 TO %VK_F11		' function keys F2 - F12
                  '
                  TS1 = TS1 + "F" + FORMAT$( CBWPARAM_PARSED - %VK_F1 + 1 )
                  '
                  ' numpad keys
                  '
                CASE %VK_NUMPAD0 TO %VK_NUMPAD9
                  '
                  TS1 = TS1 + CHR$( CBWPARAM_PARSED - %VK_NUMPAD0 + 48 )
                  '
                  IF Return_Alt_Shift_Etc = %TRUE THEN
                    TS1 = TS1 + " (numpad)"
                  END IF
                  '
                CASE %VK_MULTIPLY
                  '
                  IF Return_Alt_Shift_Etc = %TRUE THEN
                    TS1 = TS1 + "Multiply (numpad)"
                  ELSE
                    TS1 = TS1 + "*"
                  END IF
                  '
                CASE %VK_ADD
                  '
                  IF Return_Alt_Shift_Etc = %TRUE THEN
                    TS1 = TS1 + "Add (numpad)"
                  ELSE
                    TS1 = TS1 + "+"
                  END IF
                  '
                CASE %VK_SUBTRACT
                  '
                  IF Return_Alt_Shift_Etc = %TRUE THEN
                    TS1 = TS1 + "Substract (numpad)"
                  ELSE
                    TS1 = TS1 + "-"
                  END IF
                  '
                CASE %VK_DECIMAL
                  '
                  IF Return_Alt_Shift_Etc = %TRUE THEN
                    TS1 = TS1 + "Decimal (numpad)"
                  ELSE
                    TS1 = TS1 + "."
                  END IF
                  '
                  ' end numpad keys
                  ' printable chars
                  '
                CASE 32, 48 TO 57, 65 TO 90		' Space, 0 - 9, A - Z (ASCII codes)
                  '
                  TS1 = TS1 + CHR$( CBWPARAM_PARSED )
                  '
                CASE ELSE
                  '
                  EXIT FUNCTION
                  '
              END SELECT
              '
              FUNCTION = TS1
              '
            END FUNCTION
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            SUB Add_Columns_To_List_View( BYVAL WinHandle AS DWORD, BYVAL ListViewID AS LONG, BYVAL ListBoxHeaders AS STRING )
              '
              ON ERROR GOTO Add_Columns_To_List_View_Error_Handler
              '
              LOCAL TS1 AS STRING
              LOCAL lCol AS LONG
              LOCAL hCtl AS DWORD
              LOCAL tLVC AS LV_COLUMN
              LOCAL szBuf AS ASCIIZ * 128
              LOCAL lStyle AS LONG
              '
              CONTROL HANDLE WinHandle, ListViewID TO hCtl
              '
              lStyle = ListView_GetExtendedListViewStyle( hCtl )
              ListView_SetExtendedListViewStyle( hCtl, lStyle OR %LVS_EX_FULLROWSELECT OR %LVS_EX_GRIDLINES )
              ' Load column headers.
              tLVC.mask = %LVCF_FMT OR %LVCF_TEXT OR %LVCF_SUBITEM
              tLVC.pszText = VARPTR( szBuf )
              '
              FOR lCol = 1 TO PARSECOUNT( ListBoxHeaders )
                '
                TS1 = PARSE$( ListBoxHeaders, lCol )
                IF RIGHT$( TS1, 1 ) = "*" THEN
                  tLVC.fmt = %LVCFMT_RIGHT
                ELSE
                  tLVC.fmt = %LVCFMT_LEFT
                END IF
                szBuf = RTRIM$( TS1, "*" )
                tLVC.iOrder = lCol
                ListView_InsertColumn( hCtl, lCol, tLVC )
                '
              NEXT lCol
              '
              ' Auto size columns to fit headers
              FOR lCol = 0 TO PARSECOUNT( ListBoxHeaders )
                '
                ListView_SetColumnWidth( hCtl, lCol, %LVSCW_AUTOSIZE_USEHEADER )
                '
              NEXT lCol
              '
              EXIT SUB
              '
            Add_Columns_To_List_View_Error_Handler :
              '
              MSGBOX "Add_Columns_To_List_View Error" + STR$( ERR ), %MB_ICONERROR OR %MB_TASKMODAL, "Epos"
              '
            END SUB
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            SUB Populate_List_View( BYVAL WinHandle AS DWORD, ListViewID AS LONG, ListViewDataArray( ) AS STRING, BYVAL ListViewArrayQty AS QUAD, BYVAL ListViewColQty AS LONG, BYVAL CursorLine AS LONG )
              '
              ON ERROR GOTO Populate_List_View_Error_Handler
              '
              ' If ListViewID is -ve then set focus to it on exit
              LOCAL lCol AS LONG
              LOCAL lRow AS LONG
              LOCAL hCtl AS DWORD
              '  LOCAL tLVC AS LV_COLUMN
              LOCAL tLVI AS LV_ITEM
              LOCAL szBuf AS ASCIIZ * 512
              ' LOCAL lStyle AS LONG
              DIM ColDataFlagArray( 0 TO ListViewColQty - 1 ) AS BYTE
              '
              CONTROL HANDLE WinHandle, ABS( ListViewID ) TO hCtl
              '
              IF ListViewID < 0 THEN
                CONTROL SET FOCUS WinHandle, ABS( ListViewID )
              END IF
              '
              CALL ListView_DeleteAllItems( hCtl )
              ' Load data
              FOR lRow = 0 TO ListViewArrayQty - 1
                tLVI.stateMask = %LVIS_FOCUSED
                tLVI.pszText = VARPTR( szBuf )
                tLVI.iItem = lRow
                FOR lCol = 0 TO ListViewColQty - 1
                  IF ListViewDataArray( lRow + 1, lCol + 1 ) <> "" THEN
                    ColDataFlagArray( lCol ) = 1
                  END IF
                  szBuf = ListViewDataArray( lRow + 1, lCol + 1 )
                  tLVI.iSubItem = lCol
                  tLVI.lParam = lRow
                  IF lCol = 0 THEN
                    tLVI.mask = %LVIF_TEXT OR %LVIF_PARAM OR %LVIF_STATE
                    ListView_InsertItem( hCtl, tLVI )
                  ELSE
                    tLVI.mask = %LVIF_TEXT
                    ListView_SetItem( hCtl, tLVI )
                  END IF
                NEXT lCol
              NEXT lRow
              '
              IF ListViewArrayQty <> 0 THEN
                ' Auto size columns (only if it contains data)
                FOR lCol = 0 TO ListViewColQty - 1
                  IF ColDataFlagArray( lCol ) = 1 THEN
                    ListView_SetColumnWidth( hCtl, lCol, %LVSCW_AUTOSIZE )
                  END IF
                NEXT lCol
              END IF
              '
              ' if row select asked for then automatically select the cursor row required
              IF CursorLine > ListViewArrayQty THEN
                CursorLine = ListViewArrayQty
              END IF
              ' set focus row
              Listview_SetItemState( hCtl, CursorLine - 1, %LVIS_SELECTED OR %LVIS_FOCUSED, %LVIS_SELECTED OR %LVIS_FOCUSED )
              ' ensure row is visible
              Listview_EnsureVisible( hCtl, CursorLine - 1, %TRUE )
              '
              EXIT SUB
              '
            Populate_List_View_Error_Handler :
              '
              MSGBOX "Populate_List_View Error" + STR$( ERR ), %MB_ICONERROR OR %MB_TASKMODAL, "Epos"
              '
            END SUB
            
            
            
            '----------------------------------------------------------------------------(')
            
            
            
            FUNCTION KeyBoardProc( BYVAL iCode AS INTEGER, BYVAL wParam AS DWORD, BYVAL lParam AS LONG ) AS DWORD
              '
              LOCAL lShiftMode AS LONG
              '
              IF ISFALSE( lParam AND &H80000000 ) THEN		' bit 31 (2^31) NOT set: some key is pressed
                IF ISTRUE( lParam AND &H20000000 ) THEN
                  lShiftMode = %MOD_ALT		' bit 29 (2^29) set: Alt-key is down
                END IF
                IF ( GETASYNCKEYSTATE( %VK_CONTROL ) AND &H8000 ) THEN _
                  lShiftMode = lShiftMode + %MOD_CONTROL		' eventually add Ctrl
                IF ( GETASYNCKEYSTATE( %VK_SHIFT ) AND &H8000 ) _
                  THEN lShiftMode = lShiftMode + %MOD_SHIFT		' eventually add Shift
                POSTMESSAGE Current_Keyboard_Hook_DlgHan_GL, %WM_USER + 101, wParam, lShiftMode		' wParam holds virtual keycode
              END IF
              '
              FUNCTION = CALLNEXTHOOKEX( ghKeyb, iCode, wParam, lParam )		' proceed
              '
            END FUNCTION

            Comment

            Working...
            X