16 March 2009
IDE: not perfect? F5 and the _KeyUp event
We all know the editor isn't perfect, but this problem took me by surprise. I only discovered this problem with the GFA-BASIC 32 IDE last week when I was creating a simple test program to study the way GFA-BASIC 32 handles the COM events for the Ocx controls. It turns out that the WM_KEYUP message from the F5 key press to start the program isn't discarded before the program is executed. A description I discovered this when I put a TextBox on a Form using the form editor and then returned to the text editor to start the form using the LoadForm command. I inserted all TextBox event Subs to study the way they are executed from inside the GfaWin23.OCX dll. I first run the program without the debugger using Trace commands to make sure events were executed. Surprisingly, the first event I received was a _KeyUp event for the TextBox, but I didn't hit any key! I removed the LoadForm command and replaced it by statements to open a Form and a TextBox by hand, so I created a form without the use of a form resource. Now the _KeyUp event didn't get fired. How come? I tried to start the LoadForm variant using a mouse click on the Run button in the toolbar, now the _KeyUp event didn't fire. The conclusion was obvious, the WM_KEYUP message of the F5 accelerator key never was discarded. The solution When you use commands (OpenW, Form, Dialog) to open a window or form, GFABASIC-32 invokes an internal DoEvents to display the window immediately after the command is executed. The first internal DoEvents will also read the pending WM_KEYUP from the message queue and you will never be bothered with it. In case of a LoadForm command all forms and controls are created without ever calling the internal DoEvents function. The first time a message is read from the queue is with your Sleep command inside your message loop. Hence the _KeyUp event. Consequently, the solution is simple. To get rid of the pending WM_KEYUP from F5 put a DoEvents statement as the first line in your program when it uses the LoadForm command. DoEvents LoadForm frm1 Do Sleep Until Me Is Nothing Where does the event come from? For those who are as curious as me, the WM_KEYUP is a result from the way Windows handles the TranslateAccelerator() API function. This function sends, not posts, a WM_COMMAND to the window procedure after an accelerator key is used. But beware, the TranslateAccelerator() API function doesn't wait for a complete set of WM_KEYDOWN/WM_KEYUP to send the WM_COMMAND, no instead it sends the WM_COMMAND after the first WM_KEYDOWN. The IDE then responds by compiling and running the program, all from a sended WM_COMMAND message. The IDE never returns to its main message loop before ending your program. When the GFA-BASIC source is started the WM_KEYUP is still waiting in the system's message queue and is retrieved in the first GetMessage() or PeekMessage() API call, which will be in your main message loop. Hence the _KeyUp event.