Im working on normal windows again (not dialogs) for a new OOP Class and i can't seem to find good info on setting tab stops to various controls created by CreateWindowEx. I did a couple searches on the board, and didnt find anything that is directly applicable to various controls.

Does anyone have a suggestion or know of the solution??

Posted on 2003-08-20 21:04:13 by NaN
Well i found the answer with some patience while Googling...

The standard message loop inspired by Hutch that most follow doesn't support tabing thru your controls. This message loop will by using the IsDialogMsg API:
ProcessMessages         PROC USES edi esi ebx hWnd:DWORD


mov ebx, hWnd
lea esi, msg
xor edi, edi
invoke GetMessage,esi,edi,edi,edi
cmp eax, edi
je @F
invoke IsDialogMessage, ebx, esi
cmp eax, edi
jne @B
invoke TranslateMessage, esi
invoke DispatchMessage, esi
jmp @B

ProcessMessages ENDP

I wrote it to conserve bytes by using registers entirely. A TAB key is considered a 'dialog message' and as such will do the translation and dispatching for you regarding such and action.

For controls you want to Tab to, you simply have to add the WS_TABSTOP in the child control's styles.

From my test, it works for all but Multiline edit controls. For some reason it will tab to it, but i cant tab off it :confused:

Can anyone enlighten be why? Here is the sytles im useing to create a multiline edit:


Anywho there you go...
Posted on 2003-08-20 21:44:13 by NaN
It is so that you can use the tab button in editors. :grin: So I can conclude that it cannot work because you are using WS_TABSTOP together with ES_MULTILINE.
Posted on 2003-08-21 03:01:43 by roticv
Ya... I beleive its the ES_MULTILINE as well, but the thing is that the tab key doesnt do anything in the edit window either :confused:

Posted on 2003-08-21 07:22:17 by NaN
As a sidenote, one should watch out for unintended program behaviour when using the IsDialogMessage API. For example, I usually have a simple "instructions screen" in my programs. There is a static text, and a pushbutton. It looks like this:

| |
| -------------------------- |
| | | |
| | (Some instruction text) | |
| | | |
| -------------------------- |
| |
| |
| ----------------- |
| | Continue button | |
| ----------------- |

To help people read the instructions more thoroughly, the "Continue" button is invisible initially. It becomes visible only after some 10 or 20 seconds.

With a message loop ? la hutch-- (no IsDialogMessage), it is impossible to continue before the button becomes visible. Which is the intended effect.

With a message loop ? la NaN, it is possible to continue before the button becomes visible -- simply press ENTER, and the button "fires". It does not matter if the button is already visible or not, ENTER will trigger the button. Even worse, ENTER also works if the button has the WS_DISABLED style.

So the IsDialogMessage API is not a plug-in-and-forget function, but may require special attention for possible, unexpected side-effects.


Posted on 2003-08-21 09:37:46 by Frank
Thanks for the tip.. i will have to play around and see if i can reproduce the same...

Posted on 2003-08-22 23:47:48 by NaN
to allow tabbing away from a multiline edit you have to tell windows not to interpret the tab as a tab key, but as a control key:
Subclass the edit window and do something like this

EditProc: ;hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
push dword [esp+16] ;lParam
push dword [esp+16] ;wParam
push dword [esp+16] ;uMsg
push dword [esp+16] ;hWnd
push [hDefEditProc]
call [CallWindowProc]
cmp dword [esp+8],WM_GETDLGCODE ;uMsg
jnz .ExitProc
mov ecx,[esp+4] ;hWnd
cmp ecx,[hEditMain]
jnz .ExitProc
and eax,not DLGC_WANTTAB
ret 16

Just check if the button is visible/enabled in your IDOK command handler
Posted on 2003-08-23 02:33:42 by Joshua