News:

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

WS_TABSTOP

Started by RuiLoureiro, August 12, 2008, 08:30:51 PM

Previous topic - Next topic

RuiLoureiro

Michael,
          many Thanks for your HELP.

          Something failed when i want to set the backgroud window to green.
          It gives me «Blue text on green background.  ->  green UNDER THE TEXT  !!!»
          See my file Dialog5_1 ( last proc DlgProc1)

          But it works when i use default background (this is what i want first).
          This solve my problem
          Its in the file Dialog5_2
         
          About documentation, it is good but seems to have some BUGS;

         «Microsoft could have done a better job on the WM_CTLCOLORSTATIC documentation,
         and it should have included a working example.». I say the same

          note: The file  rsrc.rc  is elsewhere behind

Thanks for the code
Rui

PS:
«are you aware that I posted an example that displays a list of the system colors»
Sorry Michael, i was sleeping ! I downloaded it now and saw it. Nice work. Thanks.

EDIT:
Paul,
        WS_EX_TRANSPARENT doesnt work with EDITTEXT control. Thanks
Rui


[attachment deleted by admin]

RuiLoureiro

Quote from: jj2007 on August 13, 2008, 09:21:51 PM
You can always subclass the control and catch the background draw message.

Hi jj2007,
             I tried to studied subclass today. I did an example but it didnt run well ! I think i need
a good and simple example to understand what is subclassing, what it does.
Where to put SetWindowLong ? Catching the background message could be a good example.

Rui

jj2007

Quote from: RuiLoureiro on August 15, 2008, 06:14:07 PM
I think i need a good and simple example to understand what is subclassing, what it does.

It is really simple: You can catch all the "internal" messages of the control, and react to them. Here is a skeleton for an edit control. Instead of returning 0, you can return specific values, e.g. a brush. Sorry I am too tired right now to elaborate more on this, but MSDN has all these messages somewhere.

invoke SetWindowLong, hEdit, ; use just behind the line
GWL_WNDPROC, SubEdit ; where you create your control
mov opEdit, eax ; the old pointer, see below

SubEdit PROTO:DWORD,:DWORD,:DWORD,:DWORD ; move to proto section
opEdit dd ? ; move to data? section

SubEdit proc hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
SWITCH uMsg

CASE WM_KEYDOWN
return 0

CASE WM_CHAR
return 0

CASE WM_KEYUP
return 0

DEFAULT
xor eax, eax

ENDSW
  invoke CallWindowProc, opEdit, hwnd, uMsg, wParam, lParam
  ret
SubEdit endp

RuiLoureiro

Quote from: jj2007 on August 15, 2008, 06:37:37 PM
It is really simple: You can catch all the "internal" messages of the control, and react to them.

Hi jj2007,
            I wrote this code below to test the use of SetWindowLong.
            Could you comment it, if you dont mind
            Thanks

This is the procedure called by a Dialog window:
..................................................................
IDC_Exit    = This is the ID of EXIT BUTTON
_hIDC_Exit = This is the EXIT BUTTON's handle
...................................................................      

DlgProc     proc     hWnd:DWORD, iMsg:DWORD, wParam:DWORD, lParam:DWORD

            mov      eax, hWnd
            mov      _hDlgWnd, eax  ; This is the Dialog window's handle
                       
     .if iMsg==WM_INITDIALOG

            ; ------------------------------
            ; Get the handle of EXIT button
            ; ------------------------------
            invoke GetDlgItem, hWnd, IDC_Exit
            mov    _hIDC_Exit, eax   ; This is the EXIT BUTTON's handle
           
            ;###########################################################
            ;**** ExitProc is the NEW processor to the EXIT button  ****
            ; **********************************************************
            invoke  SetWindowLong, eax, GWL_WNDPROC, offset ExitProc
            mov     _hSubDlg, eax
            ;###########################################################
etc.


            So, after                                   
                                 
                invoke  SetWindowLong, eax, GWL_WNDPROC, offset ExitProc

            all messages to the EXIT button are processed by ExitProc, no ?
           
            They are NOT processed inside DlgProc. No or can be ?
           

This is the ExitProc:        

ExitProc    proc  hWnd:DWORD, iMsg:DWORD, wParam:DWORD, lParam:DWORD

.if  iMsg==WM_COMMAND
            mov     eax, wParam
            mov     edx,eax
            shr     edx,16
            .if edx == BN_CLICKED
                             .if eax==IDC_Exit ; <- This is the ID of EXIT BUTTON
                              ;
                              ;invoke    SendMessage, hWnd, WM_CLOSE, NULL, NULL
                              invoke    SendMessage, _hDlgWnd, WM_CLOSE, NULL, NULL                             

                        mov  eax, TRUE
                        ret
                             
                .endif
              .endif
.endif
;
; not processed HERE
; ******************
invoke    CallWindowProc, _hSubDlg, hWnd, iMsg, wParam, lParam
ret
ExitProc    endp


         The only thing i want to do inside ExitProc is to close the Dialog window
         if i click at the EXIT button.
         Whats is wrong ?

Thank you
Rui         

jj2007

You don't explain well what your problem is, and I don't see in your code any message boxes that indicate you are actually debugging your code - so I am just guessing now: It might be that you need to use DWL_DLGPROC instead of GWL_WNDPROC. Quote from MSDN:

The following values are also available when the hWnd parameter identifies a dialog box.

DWL_DLGPROC
    Sets the new address of the dialog box procedure.

If you want to know what's going on, just test it with both variants, and see if you can catch any messages, e.g WM_PAINT. With the latter, it is highly recommended to use this macro:

.data
ShowMSG dd IDOK

deb MACRO arg ; deb "Wow, I got a WM_PAINT!"
  pushad
  .if ShowMSG==IDOK
mov ShowMSG, IDCANCEL ; prevent multiple boxes
invoke MessageBox, hWnd, chr$(<arg>), addr DebugMsg, MB_OKCANCEL
mov ShowMSG, eax
  .endif
  popad
ENDM


Once you click Cancel, you will no longer see boxes.

Usage:

.if  iMsg==WM_COMMAND
            deb "Command"
            mov     eax, wParam
            mov     edx,eax
            shr     edx,16
            .if edx == BN_CLICKED
                              deb "Clicked"
                             .if eax==IDC_Exit ; <- This is the ID of EXIT BUTTON
                              deb "exit"
                              ;

RuiLoureiro

jj2007,
         Thanks for the reply

         Ok, i attached some files Dialog7_1.zip (asm & exe)
                                   Dialog7_2.zip (asm & exe)
                                   rsrc.zip (rsrc.rc)
         
         1. In the example Dialog7_1.asm i used
         
            invoke  SetWindowLong, eax, DWL_DLGPROC, offset ExitProc
         
            and inside ExitProc i have:
         
            ExitProc  proc  hWnd:DWORD, iMsg:DWORD, wParam:DWORD, lParam:DWORD

            deb "START ExitProc"

            The result is: it never triggers «deb "START ExitProc"».

            OK, hWnd parameter DOESNT identify a dialog box
                BUT an EXIT button

        2. Now, comment this ( inside Dialog7_1.asm )

                 ; invoke  SetWindowLong, eax, DWL_DLGPROC, offset ExitProc           

                uncomment this

                    invoke  SetWindowLong, eax, GWL_WNDPROC, offset ExitProc

           compile, run, Click on Open Dialog (in the menu)
           [to work, i am using Hutch Quick Editor ]

           i get  -->   "START ExitProc"

            OK, hWnd parameter identifies the EXIT button
                and NOW it goes to ExitProc


         3. In the example Dialog7_2.asm i used
         
            invoke  SetWindowLong, eax, GWL_WNDPROC, offset ExitProc
            ;deb "START ExitProc"

         4. Run, Click on Open Dialog (in the menu)
                 Click on Exit button

           i get  -->   "EXIT inside DlgProc"

           and NOT "EXIT inside ExitProc". Thats the question.
           Why isnt it processed by ExitProc ?

           There is something i dont understand well
           about SetWindowLong !
           
           Thats all for now

Thanks
Rui


[attachment deleted by admin]

jj2007

It's GWL_WNDPROC, not the DLG variant. The button does not get many messages, but try yourself:

   .elseif iMsg==WM_KEYDOWN  ; confirm with space
      deb "Msg KEYDOWN"
   .elseif iMsg==WM_NOTIFY  ; never seen
      deb "Msg NOTIFY"
   .elseif iMsg==BM_SETSTATE  ; that's your's, Rui!
      deb "Msg BM_SETSTATE"

            ;.elseif iMsg==WM_PAINT

jj2007

Rui, I suppose you know the MSDN docu on button messages? Especially the section Notification Messages from Buttons is interesting.

RuiLoureiro

Quote from: jj2007 on August 17, 2008, 03:14:29 PM
Rui, I suppose you know the MSDN docu on button messages? Especially Notification Messages from Buttons

jj2007,
          not much about controls. I am reading that docs and doing some exercises now.
          It seems i am understanding what SetWindowLong does.
          Do you know ControlSpy ?
          Did you see WS_TABSTOP2 post ? Have any idea about the problem ?

Thank you jj2007
Rui

jj2007

Quote from: RuiLoureiro on August 18, 2008, 05:50:26 PM
Quote from: jj2007 on August 17, 2008, 03:14:29 PM
Rui, I suppose you know the MSDN docu on button messages? Especially Notification Messages from Buttons

jj2007,
          not much about controls. I am reading that docs and doing some exercises now.
          It seems i am understanding what SetWindowLong does.
Subclassing is an essential technique, so that is certainly a good exercise. Maybe this would work, too:
WndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
SWITCH uMsg

CASE WM_COMMAND ; specific WM_COMMAND messages
mov eax, wParam
shr eax, 16 ; shift right to get the HIWORD
mov cMsg, eax ; the WM_COMMAND message
switch cMsg

case LBN_SELCHANGE
deb "Listbox LBN_SELCHANGE"

case BN_CLICKED ; LbChk, BST_
deb "BN_CLICKED"

Quote
          Do you know ControlSpy ?
          Did you see WS_TABSTOP2 post ? Have any idea about the problem ?
No, but sounds interesting. Will have a look at the WS_TABSTOP2 post asap.

Quote
Thank you jj2007
Rui
My pleasure :thumbu

RuiLoureiro

jj2007,
           You gave me the link to MSDN. There, above, we have "Subclassing Controls" and Control Spy 2.0
http://www.microsoft.com/downloads/details.aspx?FamilyID=19d4294d-0531-4ec2-8b27-2e463b315f16&displaylang=en.

           I will try your example. When i try an example i need some time to think about the details
involved and it takes a lot of time.

Thank you !
Rui

jj2007

Quote from: RuiLoureiro on August 18, 2008, 08:54:10 PM
           I will try your example.
I used SWITCH/CASE for first level messages and switch/case for messages inside messages. It's a matter of taste.
Thanks for the link!
jj

RuiLoureiro

jj2007,
       
        It seems i solved the problem i had in WS_TABSTOP2 topic.
        Your «deb macro» was very useful. Thanks for that !
        I did this too,
       

.data
_DebugMsg db 'Test Window', 0    ; i use _DebugMsg for GLOBAL AND DebugMsg for LOCAL
                                 ; inside the same proc i can have both etc.
                                 ; This is an example
;....................................................................................
debWnd MACRO arg, hWnd          ; use:  debWnd "message WM_NOTIFY", hWnd
  pushfd
  pushad
  .if ShowMSG==IDOK
mov    ShowMSG, IDCANCEL ; prevent multiple boxes
invoke MessageBox, hWnd, chr$(<arg>), addr _DebugMsg, MB_OKCANCEL
mov    ShowMSG, eax
  .endif
  popad
  popfd
ENDM


       About SetWindowLong, it extends a default control processor to
       one we define, but it seems we never receive WM_COMMAND or
       WM_NOTIFY inside the new one (these messges are reported to
       the parent window, only - i think - by the default control processor)

       About Switch/Case, etc., i used it a long time ago and i know.
       
       1st level:  SWITCH
                       CASE
       2nd level:            switch
                                  case
                                 ...
Rui