How to trap page up/down keys in an Edit box

How to trap page up/down keys in an Edit box

I would like to trap the page up/down keys when in an Edit box (in a Fortran Windows Dialog app) and perform the page up/down operation on another List box instead. Normally these keys do not invoke the callback. I would like to solve this without affecting the normal page up/down operation when the List box is selected.
Is there a special SendMessage command, or are there any special Properties settings? (W2K, CVF 6.6)
Greg

8 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

You'll have to subclass edit boxes themselves, (call SetWindowLong(GWL_WNDPROC) from dialog-init callback) and catch WM_CHAR/(wParam=VK_PRIOR/VK_NEXT). Need I elaborate?

Jugoslav

Could you please elaborate. I'm not sure what the new address for the window procedure argument should be. I tried using the old address (using GetWindowLong), and it still doesn't catch any direction keys. Also, isn't the handle that of the edit box?

I tried this using a standard Win32 procedure, however my final goal is to use a Win32 Modeless DIALOG procedure that normally traps inputs via SetDlgSub.
Greg

The new address will be your subclassing procedure:

!This goes to dialog-initialization callback:
INTERFACE
  INTEGER FUNCTION MyEditProc(...
END INTERFACE
...
!lpfnOldEditProc must be global
lpfnOldEditProc = SetWindowLong(GetDlgItem(Dlg%hWnd, IDC_EDIT1), GWL_WNDPROC, LOC(MyEditProc))
...
!Your window procedure:
INTEGER FUNCTION MyEditProc(hWnd, Msg, wParam, lParam)
!DEC$ATTRIBUTES STDCALL:: MyEditProc
USE DFWIN
USE GLOBALS, ONLY: lpfnOldEditProc
INTEGER, INTENT(IN):: hWnd, Msg, wParam, lParam
!
IF (Msg == WM_CHAR) THEN
   IF (wParam == VK_PRIOR) THEN
       !Page up
   ELSE IF (wParam == VK_NEXT) THEN
       !Page down
   ELSE
      MyEditProc = CallWindowProc(lpfnOldEditProc, hWnd, Msg, wParam, lParam)
   END IF
ELSE
   MyEditProc = CallWindowProc(lpfnOldEditProc, hWnd, Msg, wParam, lParam)
END IF
END FUNCTION MyEditProc

I don't think there's a way to trap the input normally via SetDlgSub. If you want to reach Dlg from within MyEditProc, you'll have to make it global.

HTH
Jugoslav

I'm fuzzy in these areas, but was able to properly trap using WM_GETDLGCODE rather than WM_CHAR.
Also, my understanding is that CallWindowProc sends all commands other than scroll to be processed in the normal manner.
This includes sending the normal character keys to the DlgSetSub callback.
The callback used is shown below.
Thanks again for your invaluable help.
Greg

!Callback for Input edit box to trap all keys
INTEGER FUNCTION MyEditProc(hWnd, Msg, wParam, lParam)
!DEC$ATTRIBUTES STDCALL:: MyEditProc
USE DFWIN
USE GLOBALData, ONLY: lpfnOldEditProc, hDlg_IDC_Output
INTEGER, INTENT(IN):: hWnd, Msg, wParam, lParam
!
INTEGER iSt
	SELECT CASE(Msg)
	CASE (WM_GETDLGCODE)
		IF (wParam == VK_PRIOR) THEN
			!Page up
			iSt=SendMessage(hDlg_IDC_Output, EM_SCROLL, SB_PAGEUP, 0) 
		ELSE IF (wParam == VK_NEXT) THEN
			!Page down
			iSt=SendMessage(hDlg_IDC_Output, EM_SCROLL, SB_PAGEDOWN, 0) 
		ELSE
			MyEditProc = CallWindowProc(lpfnOldEditProc, hWnd, Msg, wParam, lParam)
		END IF
	CASE DEFAULT
		MyEditProc = CallWindowProc(lpfnOldEditProc, hWnd, Msg, wParam, lParam)
	END SELECT
END FUNCTION MyEditProc

Um, WM_GETDLGCODE? I agree it has something to do with that (and I did forget about it first time), but docs say that WM_GETDLGCODE/wParam is not used; at best, you discovered an undocumented feature. Your code may work but I wouldn't bet it would work everywhere.

This works the following way: some keys (Enter, Tab, Arrows) in the dialog have special handling. IsDialogMessage in the dialog modal loop receives these keys and sends WM_GETDLGCODE to the control which has focus to "hear its opinion". If it returns zero, the message is converted to appropriate action (e.g. Tab key will be converted to WM_NEXTDLGCTL); otherwise, if it returns some (combination of) DLGC_ constant, the keypress is converted to normal keyboard input -- WM_CHAR (as if it is a normal window, not a dialog).

Now, I don't know what group PageUp/Down keys belong to. Try using my code (WM_CHAR) but add WM_GETDLGCODE handling and just return... uh, try DLGC_WANTARROWS or DLGC_WANTCHARS -- the docs are rather vague. DLGC_WANTALLKEYS will certainly work, but that will disable tab key as well.

Jugoslav

The following WM_CHAR block traps all characters, but not the direction keys.
Using DLGC_WANTALLKEYS traps characters and tab key in that block but still not direction keys.
All keys are trapped in the WM_GETDLGCODE block.
Greg

SELECT CASE(Msg)
CASE (WM_GETDLGCODE)
  TrapScrollProc = DLGC_WANTARROWS .OR. DLGC_WANTCHARS
CASE (WM_CHAR)
  SELECT CASE(wParam)
  CASE (VK_PRIOR)
    iSt=SendMessage(hDlg_IDC_Output, EM_SCROLL, SB_PAGEUP, 0)   !Page up
  CASE (VK_NEXT)
    iSt=SendMessage(hDlg_IDC_Output, EM_SCROLL, SB_PAGEDOWN, 0) !Page down
  CASE DEFAULT
    TrapScrollProc = CallWindowProc(lpfn_ScrollProc, hWnd, Msg, wParam, lParam)
  END SELECT
CASE DEFAULT
  TrapScrollProc = CallWindowProc(lpfn_ScrollProc, hWnd, Msg, wParam, lParam)
END SELECT

OK, I finally tested it myself (actually, I did test it the first time, but not on an edit box in a dialog). I couldn't get WM_CHAR to pass through as well, but what does work is to trap WM_KEYDOWN instead (and delete CASE(WM_GETDLGCODE)). You'll probably want to add EM_SCROLLCARET after EM_SCROLL.

Regards
Jugoslav

Leave a Comment

Please sign in to add a comment. Not a member? Join today