News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

using tab to switch between editboxes and buttons

Started by white scorpion, October 10, 2005, 07:42:45 PM

Previous topic - Next topic

white scorpion

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

Darrel

Is it possible to use a Dialog box?

Regards,

Darrel

farrier

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.
It is a GOOD day to code!
Some assembly required!
ASM me!
With every mistake, we must surely be learning. (George...Bush)

white scorpion

Thanks farrier,

I will let you know if it worked  :U

MichaelW

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 :(


eschew obfuscation

farrier

 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
It is a GOOD day to code!
Some assembly required!
ASM me!
With every mistake, we must surely be learning. (George...Bush)

Ratch

White Scorpion,
     Couldn't you add the WS_TABSTOP style on each control you want to move to with the tab key?  Ratch

tenkey

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".
A programming language is low level when its programs require attention to the irrelevant.
Alan Perlis, Epigram #8

Mincho Georgiev

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!





white scorpion

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

CorAsm

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...

hutch--

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.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

farrier

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]
It is a GOOD day to code!
Some assembly required!
ASM me!
With every mistake, we must surely be learning. (George...Bush)

CorAsm

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

zooba

'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