News:

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

WS_TABSTOP2

Started by RuiLoureiro, August 13, 2008, 06:45:38 PM

Previous topic - Next topic

RuiLoureiro

Hi

The 2nd problem i have is about to control the ENTER key in a dialog box.
I have 4 controls: an edit box A, an edit box B, a pushbutton C and another D.
The focus start at edit box A. If i press ENTER it should go to B, then to C then
to D and then to A, etc.
If Msg ==WM_COMMAND  and  wParam == IDOK then i do

            invoke  GetNextDlgTabItem, hWnd, NULL, FALSE             
            invoke  SetFocus, eax

but it doesnt work. There is something i didnt understand.

If i use        invoke  GetDlgItem, hWnd, IDC_Morada       
                  invoke  SetFocus, eax

it works correctly.

i attached the file Dialog4_2.zip= .asm & .exe

    Any suggestion ?
Thanks
Rui


[attachment deleted by admin]

MichaelW

#1
The attachment contains a MASM32 in-memory dialog that handles the Enter key as you described, by installing a WH_MSGFILTER hook.

[attachment deleted by admin]
eschew obfuscation

RuiLoureiro

Michael,
         Thanks for your help           

         About   tab_on_enter    i have this,
           
Problems:
1. How to exit from MessageProc when i press the Enter button 3 times ?

2. If we press Enter 3 times we should be in the pushbutton C but
   it is not selected like if we use the Tab key.
   When we use tab key we see where we are. If we use Enter we never know
   when we are in C or D. Thats the problem.   

        Its the first time i am using hook. It seems a good solution.

Thanks
Rui

MichaelW

This is more complex than it at first seemed. I think what you are describing as "selected" is the presence of the heavy black border that indicates the default button. I can readily make the button with the focus the default button, but since the Enter key selects the default button, the Enter key cannot be used to navigate to or away from the button without actuating the button. I think there is probably some way to correct this problem, but I'm out of time to work on this. I have updated the attachment above with what I have so far.
eschew obfuscation

RuiLoureiro

Quote from: MichaelW on August 14, 2008, 05:31:30 PM
I think what you are describing as "selected" is the presence of the heavy black border that indicates the default button.

Hi Michael Webster,
                            many Thanks for your help !
                 
yes, of course, you understood the problem very well. The presence of the heavy black border
or other thing to show the diference between C and D at that time.

Restarting the question

I defined a modal dialog box in the resource file like this:


DefDialog1    DIALOG  10, 10, 160, 80
CAPTION "Type Name and Address"
STYLE 0x0004 | DS_CENTER | WS_CAPTION |                                 
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
EXSTYLE WS_EX_TOOLWINDOW       
BEGIN
    LTEXT "Name", IDC_TxtNome,         10,  7, 60,10   
    EDITTEXT              IDC_Nome,    10, 17,120,12, ES_LEFT | WS_TABSTOP
    LTEXT "Address",IDC_TxtMorada,     10, 32, 30,10       
    EDITTEXT              IDC_Morada,  10, 43,120,12, ES_LEFT | WS_TABSTOP

PUSHBUTTON "S&egue",  IDC_Exit,    20, 63, 52,13   // -> like button C
PUSHBUTTON "C&ancela",IDC_Cancela, 90, 63, 52,13 // -> like button D

END


The general question

The problem is this:
                     We have Edit Box A, Edit Box B, Button C, Button D;
                     We start at Edit Box A (but we can use the mouse to set the focus
                                             at Edit Box B);
                     When we press 2 times the ENTER key we dont know where we are:
                          - at the button C  or at the button D ?

What we want:
                     Starting at the Edit Box A (the caret is there),
                     If we press the Enter key, we go to the Edit Box B;
                     Pressing  the Enter key again, we need to show that we
                     are now at the button C (and not at D); In such a way that
                     if we press the Enter key again we are choosing the button C
                     ( and the dialog box should be closed - i want this).
                     If we dont want the button C, we should use TAB or mouse
                     to choose another.
                     
Your example doesnt solve the problem


@@:                 cmp     eax, _hIDC_Morada  ; <-- Second Edit
                    jne     @F
;.........................................................................
                    invoke GetWindowLong, _hIDC_Exit, GWL_STYLE
                    or     eax, 1
                    invoke SetWindowLong, _hIDC_Exit, GWL_STYLE, eax
                    invoke InvalidateRgn, _hIDC_Exit, NULL, FALSE
;.......................................................................
                    invoke  SetFocus, _hIDC_Exit
                       
                    jmp     _eMsgDlgProc1       ; exit
                    ;
@@:                 cmp     eax, _hIDC_Exit       ; <-- First PushButton
                    jne     _eMsgDlgProc1       ; exit


when we change the STYLE it means we choose the pushbutton and the dialog window
closes
. It is what we can see in the example Dialog6_2 (see the file below).
Without the code above the dialog window doesnt close ( see Dialog6_1 ).
To show that we are at the button "Segue" i used
invoke  SendMessage, _hIDC_Exit, BM_SETSTATE, TRUE, NULL    ; down and up
but it doesnt solve the problem.

Isnt there another idea to solve the problem ?

Thanks
Rui


[attachment deleted by admin]

MichaelW

I was able to produce the behavior you describe by simply adding a flag to control the processing of the BN_CLICKED notification. It turns out that you CAN use Enter to navigate AWAY from the default button without actuating it. I have updated the attachment above.
eschew obfuscation

RuiLoureiro

HI MichaelW,
                      YES ! IT SEEMS TO WORK in my proc. But give me a bit of time to complete
                    my example and i will post the result here. Now iam going to take some air

       Many thanks to YOU !  :U
Rui

RuiLoureiro

Hi Michael,
             Thanks for your help.
             
             I found an unexpected problem.
             
             The first time i open the dialog box it works correctly:
             with ENTER we pass to 2nd EDIT BOX and then to 1st BUTTON
             and next we close the dialob box as we want. Correct.
             
             Now, we open the dialog box again. The caret is in the
             1st EDIT BOX (correct). Now we press ENTER and the focus
             moves to 1st BUTTON ( NOT to the 2nd EDIT BOX !!! ).
             It jumps from 1st EDIT BOX to 1st BUTTON !

             Why ? It seems windows doesnt RESET all initial conditions.
             See my file Dialog6_4.zip (asm & exe)

            I put a main window in your code and the same happens
            See the file tab_on_enter1.zip (asm & exe) and rsrc.rc

            Is there any way to correct this problem ? I dont know
            where the problem comes from ! I hope you be able to
            explain it.

            note: i had some unexpected problems in the internet connection
Thanks
Rui                     


[attachment deleted by admin]

RuiLoureiro

#8
Hi Michael,
            Did you see my last post ?

            OK, i found the solution.
           
            The problem was here: CallNextHook => Call Next Hook
            It was calling the same Hook 2 times (our Hook proc)

        ;-----------------------------------------
        ; Return whatever CallNextHookEx returns. 
        ;-----------------------------------------
        invoke  CallNextHookEx, _hHook, code, wParam, lParam

           
        I attached the file Dialog6_5.zip (exe & asm)
        to see the problem when we Open Dialog more
        than 1 time (the 1st time it works correctly).

        In the file Dialog6_6.zip (exe & asm) the
        problem is corrected.

        EDITDialog6_5  was  updated
Rui


[attachment deleted by admin]

MichaelW

Hi Rui,

Yes, I saw your post and spent some time trying to find the bug, but was called away before I found it, and by the next day I had forgotten about it. Eliminating the call to CallNextHookEx should not be necessary because for this test there should be no other WH_MSGFILTER hooks. The call to CallNextHookEx is necessary in situations were there are other WH_MSGFILTER hooks, to give them a chance to receive the hook notifications. I found the problem when I checked the return value from UnhookWindowsHookEx and discovered that the function was returning zero, indicating failure, so each time the dialog is opened a new hook is installed, and never uninstalled. So starting with the second time the dialog is opened the hook procedure is called more than once for each event. Knowing this the problem was easy to find - the handle returned by SetWindowsHookEx was not being saved to _hHook.

eschew obfuscation

RuiLoureiro

Hi MichaelW,
              Thanks for all !

1st:
Quote
«Eliminating the call to CallNextHookEx should not be necessary
because for this test there should be no other WH_MSGFILTER hooks.»
Quote

     __> CallNextHookEx    => i have not NEXT hook !!! (In this case)
                                          So it could not call anything !

2nd:
Quote
«... the problem was easy to find
- the handle returned by SetWindowsHookEx was not being saved to _hHook
Quote

    __> When i read this, i thought: it is not possible ! The computer cannot fail
            and i havent ghosts to eat instructions !
       
        Meanwhile i was seeing the source files Dialog6_1.asm, Dialog6_2.asm
       
        This is what we can see there:

   ;------------------------------------------------
   ; Install a WH_MSGFILTER hook so our MessageProc
   ; callback can intercept the dialog's messages.
   ;------------------------------------------------
   invoke   GetCurrentThreadId
   invoke   SetWindowsHookEx, WH_MSGFILTER, ADDR MsgDlgProc1, 0, eax
   mov      _hHook, eax


        [ But, in both files, i have the variable _eHook !]

        In the file Dialog6_3.asm ( it wasnt posted ) i have the same
        but
        in the file Dialog6_4.asm ( posted ) we can see this:
       

     invoke   GetCurrentThreadId
     invoke   SetWindowsHookEx, WH_MSGFILTER, ADDR MsgHook, 0, eax
           
     ; ----------------------------------------
     ; Set Keyboard Focus at the first Edit Box
     ; ----------------------------------------
     invoke   GetDlgItem, hWnd, IDC_Nome


        So, «mov  _hHook, eax» isnt there. What did i do? I removed _eHook.
        And _hHook was removed too. I took «_hHook» by «_eHook». This was
        what happen. It is explained.

        The file Dialog6_5.zip above was updated. Now, MsgHook ends with
        CallNextHookEx.

        MichaelW,
                  many people saw this topic. But only you answered.
                  And only you saw what was wrong !
                  Thank you so much!
Rui