TAB Capture - Subclass (WM_GetDlgCode)

Category: Controls - RichEdit

Date: 03-28-2012

Return to Index


 
'Programmers often want to manage keystrokes, rather than accept the default
'actions of Windows - which is to handle all keyboard input, interpreting some
'keystrokes as input and some as Dialog navigation keys.
 
'This library shows 3 ways to capture a TAB key - allowing the programmer to
'take custom action, including preventing focus moving to another control.
 
'1. Using WM_NextDlgCtl (no subclassing)
'2. Using WM_KeyDown (within subclass procedure)
'3. Using WM_GetDlgCode (within subclass procedure)
 
'This snippets shows how to implement #3.
 
'Compiler Comments:
'This code is written to compile with PBWin10. To compile with PBWin9,
'add this line:
#Include "CommCtrl.inc"
 
'Primary Code:
'Credit:  Edwin Knoppert
'By subclassing a RichEdit control, a programmer can gain access to the WM_GetDlgCode
'message which can be used to call the original RichEdit window procedure, with
'instructions to give the RichEdit control access to the TAB key (several instructions
'are allowed - see the list below).
 
'Then, with the TAB keystroke captured by the RichEdit control, the WM_Char
'(or WM_KeyUp or WM_KeyDown) message can be used to respond to the TAB
'character, including allowing/stopping the TAB key to be processed normally
'(shifting Focus to another Control)
 
'Here's a subclass procedure showing how to capture the TAB key. Note that Function=0
'is used to prevent focus from shifting to another control.
Function NewProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As LongAs Long
   Select Case Msg
      Case %WM_GETDLGCODE                 'establish control by the RichEdit
           Function = %DLGC_WANTALLKEYS
           Exit Function
      Case %WM_Char
           Select Case wParam
              Case %VK_Tab
                 Dialog Set Text hDlg, Time$   'just to show the TAB key was seen
                 Function = 0 : Exit Function    'do not further process the TAB key
           End Select
   End Select
   Function = CallWindowProc(OldProc&, hWnd, MsgwParamlParam)
End Function
 
'Constants that can be used to change the input an edit control processes include:
    DLGC_BUTTON            Button.
    DLGC_DEFPUSHBUTTON     Default push Button.
    DLGC_HASSETSEL         EM_SETSEL messages.
    DLGC_RADIOBUTTON       Radio Button.
    DLGC_STATIC            Static Control.
    DLGC_UNDEFPUSHBUTTON   Non-Default push Button.
    DLGC_WANTALLKEYS       All keyboard Input.
    DLGC_WANTARROWS        Direction keys.
    DLGC_WANTCHARS         WM_CHAR messages.
    DLGC_WANTMESSAGE       All keyboard Input (the application passes this message in the Msg structure to the Control).
    DLGC_WANTTAB           Tab key.
 
 
'Compilable Example:
'In this example, the RichEdit control is subclassed to enable using the
'WM_GetDlgCode message to have TAB messages sent to the RichEdit control.
'The WM_Char message is then used to detect when the TAB key is pressed.
#Compiler PBWin 10
#Compile EXE
#Dim All
#Include "win32api.inc
#Include "RichEdit.inc"
%ID_RichEdit = 500 : %ID_ListBox = 501
Global hDlg As DWord, hRichEdit As DWord, OldRichEditProc&, hListBox As DWord, OldListBoxProc&
 
Function PBMain() As Long
   Local style&, buf$
   Dim s(2) as String
   s(0)="One":s(1)="Two":s(3)="Three"
   buf$ =  "This is sample" + $CrLf + "text for the" + $CrLf + "edit control."
   style& = %WS_Child Or %WS_Visible Or %ES_MultiLine Or %WS_VScroll Or %ES_AutoHScroll _
      Or %WS_HScroll Or %ES_AutoVScroll Or %ES_WantReturn Or %ES_NoHideSel Or %WS_TabStop
   Dialog New Pixels, 0, "Test Code",300,300,200,155, %WS_OverlappedWindow To hDlg
   Control Add Button, hDlg, 100,"Paste", 30,10,140,20
   LoadLibrary("riched32.dll") : InitCommonControls
   Control Add ListBox, hDlg, %ID_ListBox, s(), 20,40,80,100
   Control Add "RichEdit", hDlg, %ID_RichEdit, buf$,110,40,80,100, style&
   SendMessage hRichEdit, %EM_SETEVENTMASK, 0, %ENM_SELCHANGE Or %ENM_CHANGE Or %ENM_LINK Or %ENM_KeyEvents
   Control Handle hDlg, %ID_RichEdit To hRichEdit
   Control Handle hDlg, %ID_ListBox To hListBox
   Dialog Show Modal hDlg Call DlgProc
End Function
 
CallBack Function DlgProc() As Long
   Select Case CB.Msg
      Case %WM_InitDialog
         OldRichEditProc& = SetWindowLong(GetDlgItem(hDlg, %ID_RichEdit), %GWL_WndProc, CodePTR(NewRichEditProc))  'subclass
         OldListBoxProc& = SetWindowLong(GetDlgItem(hDlg, %ID_ListBox), %GWL_WndProc, CodePTR(NewListBoxProc))  'subclass
      Case %WM_Destroy
         SetWindowLong hRichEdit, %GWL_WNDPROC, OldRichEditProc&   'un-subclass
         SetWindowLong hListBox, %GWL_WNDPROC, OldListBoxProc&   'un-subclass
      Case %WM_Command
         If CB.Ctl = 100 AND CB.Ctlmsg = %BN_Clicked Then MsgBox "No action asssigned."
   End Select
End Function
 
Function NewRichEditProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As LongAs Long
   Select Case Msg
      Case %WM_GETDLGCODE                 'establish control by the RichEdit
         Function = %DLGC_WANTALLKEYS
         Exit Function
      Case %WM_Char
         Select Case wParam
            Case %VK_Tab
               Dialog Set Text hDlg, Time$   'just to show the TAB key was seen
               Function = 0 : Exit Function    'do not further process the TAB key
         End Select
   End Select
   Function = CallWindowProc(OldRichEditProc&, hWnd, MsgwParamlParam)
End Function
 
Function NewListBoxProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As LongAs Long
   Select Case Msg
      Case %WM_GETDLGCODE                 'establish control by the RichEdit
         Function = %DLGC_WANTALLKEYS
         Exit Function
      Case %WM_Char
         Select Case wParam
            Case %VK_Tab
               Dialog Set Text hDlg, Time$   'just to show the TAB key was seen
               Function = 0 : Exit Function    'do not further process the TAB key
         End Select
   End Select
   Function = CallWindowProc(OldListBoxProc&, hWnd, MsgwParamlParam)
End Function
 
'gbs_00403
'Date: 03-10-2012
 
   '           iResult& = CallWindowProc(OldProc&, hWnd, %WM_GetDlgCode, 0, lParam)
   '           Function = iResult& Or %DLGC_WantTAb
   '           Function = %DlgC_WantChars Or %DlgC_WantTab Or %DlgC_WantArrows  'ALLKEYS
   '           Function = %DLGC_WANTTAB


created by gbSnippets
http://www.garybeene.com/sw/gbsnippets.htm