This one has me puzzled... ???
If I put only the following code into a _WM_KEYDOWN handler for a RichEdit (for instance): Beep
Function=%True
I get a beep for each keystroke and non-printable characters are blocked (a couple excepts mentioned below). So far, so good. But then I do get all printable characters (Ok, I didn't verify all, but all alpha, numeric, and many others including, "/.,?><":';" etc.
Shouldn't the "Function = %True" stop processing for all keystrokes in this scenario?
I actually tested two controls, and EditBox and a RichEdit. Tab took me to the next control for both of them. Enter was blocked for the RichEdit, but made it to the EditBox.
Any thoughts?
David
David,
In order to intercept (and 'swallow' ) some keystrokes entered in a control, I think you need to subclass that control.
If you do not subclass the control, keystrokes are passed to the controls form WndProc routine no matter what.
Someone please correct me if I'm wrong ...
Kind regards
Thanks for the reply Eddy,
It's my understanding that FF is subclassing the controls for us. That is why we have the option to use "Function = %True", to let FF know we don't want further processing on that message to occur (actually FF passes the flag along to let Windows know we don't want further processing done). I also believe there are many messages that wouldn't be available to us unless FF was subclassing the controls. Of course, I could be wrong on any one of these beliefs. :-\
Hi guys, I haven't tested any of this (not at development computer) but whenever I want to have full control over incoming messages to a Form or Control, I intercept them in the FF_PUMPHOOK handler. There you get the raw, unprocessed, incoming message and you can do anything with it. It has always worked great for me.
Will give that a try... I've seen you give that advice before (not to me thankfully), so I should have thought of it. I'll let you know how it turns out.
Works perfectly! Thanks Paul!
That does seem to indicate that there is some bug in the FF message handlers though.
Best regards,
David
Hi David,
I had occassion to do a lot of work today with key handling in one of my programs so I decided to use the message handlers rather than the PumpHook. In order to catch all of the keystrokes you need to handle WM_KEYDOWN, WM_CHAR and also %WM_GETDLGCODE. Works perfectly for me.
Here is a template that you can use.
'--------------------------------------------------------------------------------
Function FORM1_TEXT1_CUSTOM ( _
ControlIndex As Long, _ ' index in Control Array
hWndForm As Dword, _ ' handle of Form
hWndControl As Dword, _ ' handle of Control
wMsg As Long, _ ' type of message
wParam As Dword, _ ' first message parameter
lParam As Long _ ' second message parameter
) As Long
Select Case wMsg
Case %WM_CHAR
Function = -1: Exit Function
' Prevent the message beeps when Enter or Escape are pressed
'Select Case wParam
' Case %VK_RETURN, %VK_ESCAPE
' Function = -1
' Exit Function
'End Select
Case %WM_KEYDOWN
Function = -1: Exit Function
'Select Case wParam
' Case %VK_RETURN
' ' do something here in response to the ENTER key
' Function = -1
' Case %VK_ESCAPE
' ' do something here in response to the ESCAPE key
' Function = -1
' Exit Function
'End Select
Case %WM_GETDLGCODE
' MS system responds irregular to Enter key - better handle it ourselves
Local pMsg As TAGMSG Ptr
Local iMsg As Long
pMsg = lParam
If pMsg > 0 Then
iMsg = @pMsg.Message
If (iMsg = %WM_KEYDOWN) Or (iMsg = %WM_CHAR) Then
Function = %DLGC_WANTALLKEYS
Exit Function
End If
End If
End Select
End Function
Well, I must admit that I didn't try the custom message handler. ??? But that's only because there is a dedicated handler for WM_CHAR and WM_KEYDOWN. ::) Are those supposed to be used some other way? It's strange because I could see the FF routine hat called that handler pass the return code along to whatever called it. I didn't try to follow it further up.
I didn't know about WM_GETDLGCODE. Thanks for the tip and the template!
I guess I could have broke the code out into the separate WM_CHAR and WM_KEYDOWN handlers but I would still have to use WM_GETDLGCODE in the Custom handler.... so, I decided to put it all in one place for the sake of togetherness. :)
I see what's going on now! I reread my first post. It was written poorly and my message was not so clear. :-[
Look at the attached project.
Compile and run the project and observe the control behavior when typing. Remove the comment on the line in the pump hook and retest as before. Notice the different behavior.
Best regards,
David
It is not as easy/clear as you might expect. You should read up on how Windows handles key processing. It can be confusing. In FireFly, if you intercept WM_KEYDOWN in the PumpHook then the message never makes it to the TanslateMessage function that is in FireFly's message loop.
If the message makes it to TranslateMessage then it will get dispatched to the Form/Control and will also generate a WM_CHAR message. At that point you need to deal with WM_CHAR (regular alphanumeric kind of characters) and WM_KEYDOWN (for arrow keys, function keys, Jome/End, PgUp, PgDn, etc)
These links may help to explain things better than me:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646276(v=vs.85).aspx
...and I shouldn't be using the %VK_ codes in WM_CHAR. I should be testing for character codes (eg. ENTER = 13, ESCAPE = 27, etc).
But why would FF translate it before calling the Control's WM_KEYDOWN message handler. Shouldn't it be calling it after that message handler returns so that it can skip the TranslateMessage call if the handler returns a %True?
It's OK if the answer is that it couldn't be done any other way. :)
Quote from: David Kenny on October 26, 2013, 11:20:29 PM
But why would FF translate it before calling the Control's WM_KEYDOWN message handler. Shouldn't it be calling it after that message handler returns so that it can skip the TranslateMessage call if the handler returns a %True?
I guess that it could have been done that way but it sure would have resulted in one hell of a large message pump. I would have to add code to preprocess every message handler for every form and every control in the application. Whereas, now the design of FireFly allows the messages for the form/control to be processed in the individual specific forms/controls Window Procedures. It makes for better modular code with no loss of functionality.
I guess that I implied that it is TranslateMessage that sends the keystroke messages to the form/control but it is actually DispatchMessage that does that work. TranslateMessage and DispatchMessage are usually paired together in the message pump.
QuoteI guess that it could have been done that way but it sure would have resulted in one hell of a large message pump.
I can accept that. I had always been operating under the assumption that code could be plucked from a case structure in a regular PB program and inserted into the appropriate FF message handler (and you can some 99% of the time ;D) and it would work the same. But it's good to know the conditions that dictate when it needs to be handled differently.
I withdraw my assertion that there must be some bug in FF's message pump as it's more a limitation that I was unaware of.
Thanks Paul!