The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: white scorpion on October 10, 2005, 07:42:45 PM

Title: using tab to switch between editboxes and buttons
Post by: white scorpion on October 10, 2005, 07:42:45 PM
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
Title: Re: using tab to switch between editboxes and buttons
Post by: Darrel on October 10, 2005, 08:08:53 PM
Is it possible to use a Dialog box?

Regards,

Darrel
Title: Re: using tab to switch between editboxes and buttons
Post by: farrier on October 10, 2005, 08:44:30 PM
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.
Title: Re: using tab to switch between editboxes and buttons
Post by: white scorpion on October 10, 2005, 08:58:20 PM
Thanks farrier,

I will let you know if it worked  :U
Title: Re: using tab to switch between editboxes and buttons
Post by: MichaelW on October 10, 2005, 09:54:03 PM
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 :(


Title: Re: using tab to switch between editboxes and buttons
Post by: farrier on October 11, 2005, 01:05:07 AM
 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
Title: Re: using tab to switch between editboxes and buttons
Post by: Ratch on October 11, 2005, 01:36:56 AM
White Scorpion,
     Couldn't you add the WS_TABSTOP style on each control you want to move to with the tab key?  Ratch
Title: Re: using tab to switch between editboxes and buttons
Post by: tenkey on October 11, 2005, 02:32:22 AM
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".
Title: Re: using tab to switch between editboxes and buttons
Post by: Mincho Georgiev on October 11, 2005, 11:52:02 AM
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!




Title: Re: using tab to switch between editboxes and buttons
Post by: white scorpion on October 13, 2005, 09:37:27 AM
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
Title: Re: using tab to switch between editboxes and buttons
Post by: CorAsm on December 18, 2005, 12:52:26 PM
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...
Title: Re: using tab to switch between editboxes and buttons
Post by: hutch-- on December 18, 2005, 02:53:33 PM
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.
Title: Re: using tab to switch between editboxes and buttons
Post by: farrier on December 18, 2005, 06:12:06 PM
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]
Title: Re: using tab to switch between editboxes and buttons
Post by: 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
Title: Re: using tab to switch between editboxes and buttons
Post by: zooba on December 19, 2005, 01:09:26 PM
'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
Title: Re: using tab to switch between editboxes and buttons
Post by: G`HOST on December 22, 2005, 06:47:35 AM
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.
Title: Re: using tab to switch between editboxes and buttons
Post by: CorAsm on December 22, 2005, 10:46:32 AM
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