Hi All,
currently i'm writing a program (my first GUI program) and although everything works fine, i still have a problem.
I've created a window with 4 editboxes and 3 buttons, and i would like to use tab to fill in the editboxes or select the buttons.
What should i do or add to make this possible?
Codesnippet:
WndProc PROC hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE
invoke PutEditBox,hWnd
invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText,\
WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\
340,96,80,18,hWnd,ButtonID,hInstance,NULL
mov hwndButton,eax
invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText2,\
WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\
10,135,180,25,hWnd,ButtonID2,hInstance,NULL
mov hwndButton2,eax
invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText3,\
WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\
240,135,180,25,hWnd,ButtonID3,hInstance,NULL
mov hwndButton3,eax
.ELSEIF uMsg==WM_PAINT
invoke PutText
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF ax==IDM_EXIT || ax==ButtonID3
invoke PostQuitMessage,NULL
.ELSEIF ax==IDM_START || ax==ButtonID2
invoke StartProgram
.ELSEIF ax==IDM_CLEAR
invoke ClearEditBoxes
.ELSEIF ax==IDM_ABOUT
invoke MessageBoxA,NULL,addr about,addr abouthead,MB_OK
.ELSEIF ax==ButtonID
shr eax,16
.IF ax==BN_CLICKED
invoke OpenTargetFile
.ENDIF
.ENDIF
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc ENDP
PutEditBox procedure:
PutEditBox PROC hEdit:HWND
invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\
WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\
ES_AUTOHSCROLL,\
175,20,246,20,hEdit,8,hInstance,NULL
mov hwndEdit1,eax
invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\
WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\
ES_AUTOHSCROLL,\
175,45,246,20,hEdit,8,hInstance,NULL
mov hwndEdit2,eax
invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\
WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\
ES_AUTOHSCROLL,\
175,70,246,20,hEdit,8,hInstance,NULL
mov hwndEdit3,eax
invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\
WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\
ES_AUTOHSCROLL,\
175,95,160,20,hEdit,8,hInstance,NULL
mov hwndEdit4,eax
ret
PutEditBox ENDP
Should i be using another way to get the editboxes? And if so, what should i use?
Thanks in advance!
Kind regards,
Mark
Is it possible to use a Dialog box?
Regards,
Darrel
White Scorpion,
In your Message Loop you have to use the IsDialogMessage , and everything will work as expected. If everything else is correct This works even if no "dialog" is used!! Here is an example from my program :U
.while TRUE
invoke GetMessage, msg, NULL, 0, 0
.if eax, e, 0
jmp @f
.endif
invoke TranslateAccelerator, [gWnd], [hAccel], msg
.if eax, e, 0
invoke IsDialogMessage, [gWnd], msg
.if eax, e, 0
invoke TranslateMessage, msg
invoke DispatchMessage, msg
.endif
.endif
.endw
@@:
The code is FASM based, but it should be plain enough.
Thanks farrier,
I will let you know if it worked :U
I recently implemented tabbing between controls for a conventional window (instead of a dialog) with a subclass procedure. I was actually modifying FASM code generated by a compiler. The window I used had 4 edit controls and 3 buttons. Here are the relevant parts.
Data section:
;==========================================================
; Add a label above the compiler-defined control handle
; data and append a dword to each definition to store
; the address of the original (class) control procedure.
; The tab order of the controls will match the order in
; which the controls were created (which determined the
; order of the control handles in the table).
;==========================================================
tabtable:
ZZZt1: dd ?,0
ZZZt2: dd ?,0
ZZZt3: dd ?,0
ZZZt4: dd ?,0
ZZZb1: dd ?,0
ZZZb2: dd ?,0
ZZZb3: dd ?,0
;==========================================================
Code section:
;==========================================================
; The tab/shift-tab behavior will be the same for all
; controls so a single subclass procedure can be used to
; implement that behavior. Since the subclass procedure
; handles only the tab/shift-tab behavior, for the
; controls to be operable it must call the original
; (class) control procedures, and to do that it must be
; able to associate the addresses of the original control
; procedures with the control handles.
;
; Subclass the controls and store the addresses of the
; original control procedures.
;==========================================================
invoke SetWindowLong,dword [ZZZt1],GWL_WNDPROC,TabHandler
mov dword [ZZZt1+4],eax
invoke SetWindowLong,dword [ZZZt2],GWL_WNDPROC,TabHandler
mov dword [ZZZt2+4],eax
invoke SetWindowLong,dword [ZZZt3],GWL_WNDPROC,TabHandler
mov dword [ZZZt3+4],eax
invoke SetWindowLong,dword [ZZZt4],GWL_WNDPROC,TabHandler
mov dword [ZZZt4+4],eax
invoke SetWindowLong,dword [ZZZb1],GWL_WNDPROC,TabHandler
mov dword [ZZZb1+4],eax
invoke SetWindowLong,dword [ZZZb2],GWL_WNDPROC,TabHandler
mov dword [ZZZb2+4],eax
invoke SetWindowLong,dword [ZZZb3],GWL_WNDPROC,TabHandler
mov dword [ZZZb3+4],eax
;==========================================================
;==========================================================
; Process tab and shift-tab, and shift the focus.
;==========================================================
ctrl_count equ 7
TabHandler proc hwnd:dword,wmsg:dword,wparam:dword,lparam:dword
push ebx esi edi
; ------------------------------------
; Set EBX to index of current handle.
; ------------------------------------
xor ebx,ebx
mov edx,[hwnd]
@@:
cmp edx,[tabtable+ebx*8]
je @F
inc ebx
cmp ebx,ctrl_count
jb @B
@@:
.if [wmsg]=WM_KEYDOWN
.if [wparam]=VK_TAB
invoke GetAsyncKeyState,VK_SHIFT
and eax,80000000h ; isolate key-down bit
.if eax=0 ; tab
.if ebx<(ctrl_count-1)
inc ebx
.else
mov ebx,0
.endif
.else ; shift-tab
.if ebx>0
dec ebx
.else
mov ebx,(ctrl_count-1)
.endif
.endif
invoke SetFocus,dword [tabtable+ebx*8]
; -----------------
; Discard the key.
; -----------------
pop edi esi ebx
xor eax,eax
ret
.endif
.endif
invoke CallWindowProc,dword [tabtable+ebx*8+4],[hwnd],[wmsg],[wparam],[lparam]
pop edi esi ebx
ret
TabHandler endp
;==========================================================
Assuming farrier's IsDialogMessage method will work, it could have saved me some effort :(
MichaelW,
I was just about to do something like your code, when Google Groups came to the rescue. The code I found was part of a VB group discussion about something else entirely! Once I got the IsDialogMessage to work with the Key Accelerator, I went back and search the ASM boards and found more references to IsDialogMessage. But I didn't use the "correct" words in my search :(.
hth
farrier
White Scorpion,
Couldn't you add the WS_TABSTOP style on each control you want to move to with the tab key? Ratch
That's insufficient. You either need to use the IsDialogMessage function, or create a *modal* dialog box with a dialog box API. Oh, and there's a third way - intercept the keyboard messages and do your own "navigation".
Sometimes,the reason to not be able to tabswithing the controls of the DlgBox is unproperly reading of the Dlg Messages from the WinMain Func.
Make sure that you've already done the following
1st.
.repeat
invoke GetMessage,ADDR msg,0,0,0
.break .if(!eax)
.if hDlg != 0
invoke IsDialogMessage,hDlg,ADDR msg
.continue
.endif
invoke TranslateMessage,ADDR msg
invoke DispatchMessage, ADDR msg
.until FALSE
i.e. the message loop include the IsDialogMessage if handle of Dlg is not 0!
2nd:
invoke CreateDialogParam,hInstance,ID_DLG1,hwnd,ADDR DlgProc,0
mov hDlg,eax ;!!! so IsDialogMessage will be ON !
3th:
In your DlgProc when the Dlg is destroyed make sure that hDlg' value is set to NULL,so IsDialogMessage to be OFF;
like that:
.if uMsg == WM_DESTROY
mov hDlg,NULL
DestroyWindow(hwnd) ;where hwnd is the 1st param of the DlgProc
.if uMsg == WM_CLOSE
;THE SAME
----------------------------
4th:
To resolve the problems with your main window when you switching between the Dlg and Wnd you have to do the following in your WndProc function:
.if uMsg == WM_SETFOCUS
mov hDlg,NULL ;So IsDialogMessage is OFF and the Main Window will be focused!
invoke SetFocus
-----------------------------------------
When your message loop is ok (and Tabstop events of your Dlg Ctrl's) you not supposed to have problems with you tab switching
Dont Forget hDlg' value ,so IsDialogMessage to be properly turned ON and OFF !!!
Greetings!
Thanks for all your replies guys.
I've rewritten the program using a DialogBox and although i had some problems with the order the controls are selected, this was pretty easily solved so for now i don't have a problem with it anymore and it works just like i wanted :U
Hi i've got another prob with the tab switch... every time the focus ist set, from a editbox, to the next button or editbox, i got a message beep...
the focus is switching normally to the other window...
does anyone know what the problem is...
thx CorAsm
edit:
i used CreateWindowEx 'cos i want to know how it works from scrap on, so please give some infos without dialogs...
Cor,
There are two style you need to set that should fix the problem you have, make the edit control with the ES_MILTILINE style added and also use the ES_WANTRETURN and it should behave in the way you want.
Attached is a small example creating a window, with a few child windows which can be tabbed from one to the other.
FASM syntax. http://flatassembler.net/
hth,
farrier
[attachment deleted by admin]
thx for the answers...
may it be that i have to catch WM_CHAR instead of WM_KEYDOWN, 'cos i've tested my prog with '9' as my tab...
so i catched this one with WM_KEYDOWN -> VK_9 without a messagebeep but ht e character was send to the editbox.
if i catch with WM_CHAR -> ... the character i think it should work...
regards
'VK_9' refers to the character 9, not tab. You're after VK_TAB.
If you've got IsDialogMessage set up properly in your message loop, VK_TAB should never get there :U
Quote from: CorAsm on December 19, 2005, 12:31:00 PM
thx for the answers...
may it be that i have to catch WM_CHAR instead of WM_KEYDOWN, 'cos i've tested my prog with '9' as my tab...
so i catched this one with WM_KEYDOWN -> VK_9 without a messagebeep but ht e character was send to the editbox.
if i catch with WM_CHAR -> ... the character i think it should work...
regards
Well for tabbing you should respond to WM_KEYDOWN but if you are calling CallWindowProc in responce to WM_CHAR and then you try to Tab using any charecter key in WM_KEYDOWN then you will get the same result as you are getting.So instead of VK_9 use VK_TAB and in WM_KEYDOWN.
No it was just a test if this sound also happens, but it didn't.
My itention was right after i catched also the character of "TAB" thos massagebeep was gone so my tab switch works now fine without the messagebeep after hit tab...
regards and thx
CorAsm