News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

A question about windows

Started by RuiLoureiro, February 15, 2013, 04:29:01 AM

Previous topic - Next topic

RuiLoureiro

Hi all

I decided to play with overlapped windows and system colors
but i found something that i suppose it isnt correct.
The problem is this: When we choose Next Window (use Overlapped1.exe)
it creates the second overlapped window Y. Whenever we try Next Window
it shows the next window. But if we try to close this second window
Y it closes all.
Someone can tell me If is it correct or i am doing something wrong ?

Main   Window X: invoke  OverlappedWndX  => _hWndX, WndProcA
Second Window Y: invoke  OverlappedWndY  => _hWndY, WndProcB  <-- it should call this, no?

Class X = "Overlapped_A"
Class Y = "Overlapped_B"

I cannot post all the files because a lot of procedures and data
them are in my libs.

You can read the folowing asm and and try Overlapped1.zip (.exe)


; File:     Overlapped1.asm
; by:       Rui Loureiro
;==============================================================================
                               include Protos.inc
;==============================================================================
WinMain         proto :DWORD,:DWORD,:DWORD,:DWORD
WndProcA        proto :DWORD,:DWORD,:DWORD,:DWORD
WndProcB        proto :DWORD,:DWORD,:DWORD,:DWORD
;-----------------------------------------------------------------------------------------------
IDM_Menu1    equ 1000
IDM_SAIR     equ 2203
;===============================================================================================
;                           Constantes e Estruturas
;----------------------------------------------------------------------------------------------
.const
                 include .\RCLLIB6\Constant.inc
; ««««««««««««««««««««««««««««««««« Data Section ««««««««««««««««««««««««««««««««««««««««««««
.data
_Menu           db "Menu", 0
_NextColor      dd 0
_WindowNameX    db "Overlapped - COLOR_BACKGROUND", 0
; ««««««««««««««««««««««««««««««««« Data? Section ««««««««««««««««««««««««««««««««««««««««««««
.data?
;---------------------------------------
_msg         MSG <?>

_hWndX       dd ?       ; main   window X
_hWndY       dd ?       ; second window Y
; «««««««««««««««««««««««««««««««««« Code Section «««««««««««««««««««««««««««««««««««««««««««
.code
;---------------------------------------
start:
            invoke  GetModuleHandle, 0
            mov     _hInstance, eax
           
            invoke  WinMain, _hInstance, NULL, NULL, SW_SHOWDEFAULT

; ##############################################################################################
WinMain     proc    hInst:DWORD, hPrevInst:DWORD, CmdLine:DWORD, CmdShow:DWORD

            ;                      x,y,lx,ly,fPos,hBrh,nIcon,nMenu,nWnd,style,exstyle,pPrc
            invoke  OverlappedWndX,10,10,684,400,0,COLOR_BACKGROUND, 0, addr _Menu,
                                   addr _WindowNameX,WS_MINMAX,300h, addr WndProcA           
            mov     _hWndX, eax

            invoke  ShowWindow, _hWndX, SW_SHOWNORMAL
            invoke  UpdateWindow, _hWndX
            ;
            ; Loop de espera de mensagens
            ;
    @@:     invoke  GetMessage, ADDR _msg, NULL, 0, 0                       
            cmp     eax,0h                              ;check if return value=0 => exit
            je      @F                                  ;go forward @@

            invoke  TranslateMessage, ADDR _msg
            invoke  DispatchMessage,  ADDR _msg
            jmp     @B                                  ;go backward @@                 
            ;
            ; Termina o programa
            ;-------------------
    @@:     invoke  ExitProcess, 0         
WinMain     endp
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
WndProcA        proc    hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

                mov     edx, wParam
                mov     eax, uMsg
               
                cmp     eax, WM_CREATE
                je      _WM_CREATE
               
                cmp     eax, WM_COMMAND
                je      _WM_COMMAND
               
                cmp     eax, WM_CLOSE
                je      _WM_CLOSE

                cmp     eax, WM_DESTROY
                je      _WM_DESTROY
               
                cmp     eax, WM_SYSCOMMAND
                je      _WM_SYSCOMMAND
; -----------------------------------------------------------------
_EndProcA:      invoke   DefWindowProc, hWnd, uMsg, wParam, lParam
                ret
; -----------------------------------------------------------------
;                             WM_CREATE
; -----------------------------------------------------------------
_WM_CREATE:         call    GetAllBrushSys
                    call    CriaAllBrushRcl
                    jmp     _ExitProcA
; -----------------------------------------------------------------
;                             WM_COMMAND
; -----------------------------------------------------------------
_WM_COMMAND:        switch edx
                    case IDM_Menu1
                    ;
        _ini:       mov     ebx, _NextColor
                    ;
                    add     ebx, 1
                    mov     _NextColor, ebx
                   
                    invoke  GetSystemColor, ebx
                    jnc     short @F
                    ;
                    mov     _NextColor, 0
                    jmp     short _ini                   

            @@:     mov     ebx, eax
                    add     eax, 1
                    invoke  SetClassLong, _hWndY, GCL_HBRBACKGROUND, eax

                    invoke  GetNameSysColor, _NextColor

            ; ---------------------------------------------------------------------------
            ;                    Open Overlapped Window Y
            ;                    Name = eax, hBrush = ebx
            ;          When we close the previous _hWndY it closes all windows
            ; ---------------------------------------------------------------------------
            ;                      x,y,lx,ly,fPos,hBrh,nIcon,nMenu,nWnd,style,exstyle,pPrc
            invoke  OverlappedWndY,100,100,500,300,0,ebx, 0, 0,
                                   eax,0,300h, addr WndProcB
            mov     _hWndY, eax
            invoke  ShowWindow, _hWndY, SW_SHOWNORMAL
            invoke  UpdateWindow, _hWndY
                   
                    jmp     _ExitProcA
                    ; --------------
                    ;     SAIR
                    ; --------------
                    case    IDM_SAIR

                    invoke  SendMessage, hWnd, WM_CLOSE, 0, 0
                    jmp     _ExitProcA                   
                    endsw
                     
                    jmp     _EndProcA
; -----------------------------------------------------------------
;                             WM_SYSCOMMAND
; -----------------------------------------------------------------
_WM_SYSCOMMAND: cmp     edx, SC_CLOSE
                jne     _EndProcA
; -----------------------------------------------------------------
;                             WM_CLOSE
; -----------------------------------------------------------------
_WM_CLOSE:      call      DestroyAllBrushes

                invoke    DestroyWindow,  hWnd
                jmp       _ExitProcA
; -----------------------------------------------------------------
;                             WM_DESTROY
; -----------------------------------------------------------------
_WM_DESTROY:    invoke   PostQuitMessage, 0
                ;
_ExitProcA:     mov     eax, 0
                ret
WndProcA        endp
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
WndProcB        proc    hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

                mov     edx, wParam
                mov     eax, uMsg
               
                cmp     eax, WM_CLOSE
                je      _WM_CLOSE

                cmp     eax, WM_DESTROY
                je      _WM_DESTROY
               
                cmp     eax, WM_SYSCOMMAND
                je      _WM_SYSCOMMAND

; -----------------------------------------------------------------
_EndProcB:      invoke   DefWindowProc, hWnd, uMsg, wParam, lParam
                ret
; -----------------------------------------------------------------
;                             WM_SYSCOMMAND
; -----------------------------------------------------------------
_WM_SYSCOMMAND: cmp     edx, SC_CLOSE
                jne     _EndProcB
; -----------------------------------------------------------------
;                             WM_CLOSE
; -----------------------------------------------------------------
_WM_CLOSE:      invoke  DestroyWindow,  hWnd
                xor     eax, eax
                ret
; -----------------------------------------------------------------
;                             WM_DESTROY
; -----------------------------------------------------------------
_WM_DESTROY:    invoke  PostQuitMessage, 0
                xor     eax, eax
                ret
WndProcB        endp
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    end     start


qWord

it is very simple: use PostQuitMessage only if you wish to exit the message loop.
MREAL macros - when you need floating point arithmetic while assembling!

dedndave

when you PostQuitMessage, it terminates the program
(it tells the message loop to exit)
you have the same exit code in both WndProc's

when you receive a WM_CLOSE message, it is a good time to perform clean-up
if you do handle this message, you should also call DestroyWindow or allow DefWindowProc to do it for you
if you have no clean-up to perform, just let DefWindowProc handle the message (it calls DestroyWindow)

when the main window receives WM_DESTROY, you call PostQuitMessage
for child window proc's, just ignore this message and allow DefWindowProc to handle it

for both types of windows, it is not necessary to handle WM_SYSCOMMAND:SC_CLOSE
the OS does that for you by sending a WM_CLOSE message

BTW: good to see you, Rui   :t

qWord

For all windows, WM_DESTROY is the point where resources should be freed because WM_CLOSE is send only to top level windows (which have this X-Button/sysmenu).
MREAL macros - when you need floating point arithmetic while assembling!

dedndave

some child windows may have the close box   :biggrin:

but, you are still right - WM_DESTROY is the better place to handle clean-up for child windows that do not
my mistake

RuiLoureiro

qWord,
        Thanks for your answer.
        Nice to see you here again ! ;)

«it is very simple: use PostQuitMessage only if you wish to exit the message loop.»
       
        Yes it is, i forgot it ! I wrote an example recently, but the second window has
        also a message loop !

Dave,
        Nice to see you here again. ;)
        Good to see you also, Dave

        Thanks for your answer
        and the advice about what to do
        when we receive WM_DESTROY
        (I used it in WM_CLOSE - DestroyAllBrushes)
       
Now we can see overlapped2.zip with much more colors
and not close the second window ! :greensml:

dedndave

 :t
i bet we will see a GUI calculator in the near future   :biggrin:

RuiLoureiro

Quote from: dedndave on February 15, 2013, 11:09:51 AM
:t
i bet we will see a GUI calculator in the near future   :biggrin:
Yes Dave, wait and see !  :t
Now i am writing a window to be used as a dialog
with some STATIC, 1 COMBOBOX, 2 LISTBOX and
a matrix of 12 lines by 7 columns of EDIT (84 EDIT)
plus 3 EDIT where we put the sum of colums 5,6,7.
It is ready and works correctly and quickly. My problem was not
to write code but to think about how to structure the data
in a way that we use a set of simple procedures to do the work
in this case and in all cases like this without much more work for
12 lines or 4 lines or for 50 lines!


RuiLoureiro

 Now i have a simple problem: how to open the second window
in front of the first. Whats the API ? First i open the main wnd X
then i create the wnd Y but it is behind the main . How to change it ?
Thanks !

qWord

Set the parent window of Y to X (CreateWindowEx->hWndParent = hMainWnd)
MREAL macros - when you need floating point arithmetic while assembling!

RuiLoureiro

Quote from: qWord on February 15, 2013, 11:31:02 PM
Set the parent window of Y to X (CreateWindowEx->hWndParent = hMainWnd)
Ok thanks qWord .
Meanwhile, isnt there an API to change it ? No ?

dedndave

oh - and set the WS_CHILD style flag
in the hMenu parameter, specify a unique control ID from 1 to 65535

there are a few API's that can change the Z-order of windows
SetWindowPos is one

RuiLoureiro

qWord,
        many thanks to you  :t
       
        the problem is this: my OverlappedWndX and Y assumes the window
        has not a parent and i dont want to modify it ... by now  :biggrin:

Dave,
        Yes, it is.  ;) Thanks  :t

        Meanwhile i want to share what i did

            . i added a button: «Next Window»

            . now i am using a best method. First i create
              the second window Y when we get WM_CREATE
              and then we call GetClientRect
              (Retc is to be used in WM_ERASEBKGND).
             
              When the system sends WM_ERASEBKGND to WndProcB ( Y ) 
              we use SetClassLong to set the new class brush and we exit
              to DefWindowProc (the system must paint it !).
             
              This is done after the window is created
              ( The first color and name is this (see the .asm):
                mov     ebx, COLOR_BACKGROUND
                mov     eax, offset _WindowNameX
              )
              but it isnt the first window name and first color.

            . When we choose the button «Next Window» we simple
              use InvalidateRect and the system do the work
              sending WM_ERASEBKGND ...

i attached Overlapped4.zip (.asm ; .exe)


; File:     Overlapped4.asm
; by:       Rui Loureiro
;=========================================================
                               include Protos.inc
;=======================================================
WinMain         proto :DWORD,:DWORD,:DWORD,:DWORD
WndProcA        proto :DWORD,:DWORD,:DWORD,:DWORD
WndProcB        proto :DWORD,:DWORD,:DWORD,:DWORD
;-----------------------------------------------------------------------------------------------
IDM_Menu1    equ 1000
IDM_SAIR     equ 2203

IDBUTAO1     equ 500
;=========================================================
;                           Constantes e Estruturas
;----------------------------------------------------------------------------------------------
.const
                 include .\RCLLIB6\Constant.inc
; ««««««««««««««««««««««« Data Section ««««««««««««««««««««««««
.data
_Menu           db "Menu", 0

_NextColorX     dd 0
_NextColorY     dd 0

_ButtonName     db "Next Window",0    ;"SEGUINTE",0

_WindowNameX    db "Overlapped - COLOR_BACKGROUND", 0
; «««««««««««««««««««« Data? Section «««««««««««««««««««««««««««««
.data?
;---------------------------------------
_msg         MSG <?>
_rc          RECT <?>

_hWndX       dd ?       ; main   window X
_hWndY       dd ?       ; second window Y
_hButton1    dd ?
; «««««««««««««««««««« Code Section ««««««««««««««««««««««««««««««
.code
;---------------------------------------
start:
            invoke  GetModuleHandle, 0
            mov     _hInstance, eax
           
            invoke  WinMain, _hInstance, NULL, NULL, SW_SHOWDEFAULT

; ####################################################
WinMain     proc    hInst:DWORD, hPrevInst:DWORD, CmdLine:DWORD, CmdShow:DWORD

            ;                      x,y,lx,ly,fPos,hBrh,nIcon,nMenu,nWnd,style,exstyle,pPrc
            invoke  OverlappedWndX,10,10,684,400,0,COLOR_BACKGROUND, 0, addr _Menu,
                                   addr _WindowNameX,WS_MINMAX,300h, addr WndProcA           
            mov     _hWndX, eax

            ; doest work here
            ;call    GetAllBrushSys  ; get all system brushes to a table
            ;call    CriaAllBrushRcl ; create all and put into a table

            invoke  ShowWindow, _hWndX, SW_SHOWNORMAL
            invoke  UpdateWindow, _hWndX
            ;
            ; Loop de espera de mensagens
            ;
    @@:     invoke  GetMessage, ADDR _msg, NULL, 0, 0                       
            cmp     eax,0h                              ;check if return value=0 => exit
            je      @F                                  ;go forward @@

            invoke  TranslateMessage, ADDR _msg
            invoke  DispatchMessage,  ADDR _msg
            jmp     @B                                  ;go backward @@                 
            ;
            ; Termina o programa
            ;-------------------
    @@:     invoke  ExitProcess, 0         
WinMain     endp
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
WndProcA        proc    hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

                mov     edx, wParam
                mov     eax, uMsg
               
                cmp     eax, WM_CREATE
                je      _WM_CREATE
               
                cmp     eax, WM_COMMAND
                je      _WM_COMMAND
               
                cmp     eax, WM_CLOSE
                je      _WM_CLOSE

                cmp     eax, WM_DESTROY
                je      _WM_DESTROY
               
                cmp     eax, WM_SYSCOMMAND
                je      _WM_SYSCOMMAND
; -----------------------------------------------------------------
_EndProcA:      invoke   DefWindowProc, hWnd, uMsg, wParam, lParam
                ret
; -----------------------------------------------------------------
;                             WM_CREATE
; -----------------------------------------------------------------
_WM_CREATE:         call    GetAllBrushSys  ; get all system brushes to a table
                    call    CriaAllBrushRcl ; create all and put into a table

                    ; ---------------------------------------------------------
                    ;                 Open Overlapped Window Y
                    ;                 Name = eax, hBrush = ebx
                    ; ---------------------------------------------------------
                    mov     ebx, COLOR_BACKGROUND
                    mov     eax, offset _WindowNameX
                    ;                   x,y,lx,ly,fPos,hBrh,nIcon,nMenu,nWnd,style,exstyle,pPrc
                    invoke  OverlappedWndY,100,100,500,300,0,ebx, 0, 0,
                                   eax,0,300h, addr WndProcB
                    mov     _hWndY, eax

                    Invoke  GetClientRect, _hWndY, addr _rc

                    invoke  ShowWindow, _hWndY, SW_SHOWNORMAL
                    invoke  UpdateWindow, _hWndY

                    invoke  SetWindowPos, _hWndY, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE+SWP_NOSIZE

                    ;-----------------------------------------------------------------
                    ;                       Create Button
                    ;-----------------------------------------------------------------
                    invoke   CreateWindowEx,  0,
                             OFFSET _ButtonClass,
                             addr _ButtonName,
                             WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGS or WS_TABSTOP,
                             270, 8, 120, 30,
                             hWnd, IDBUTAO1, _hInstance, 0
                    mov      _hButton1, eax
                   
                    jmp     _ExitProcA
; -----------------------------------------------------------------
;                             WM_COMMAND
; -----------------------------------------------------------------
_WM_COMMAND:        switch edx
                    case IDM_Menu1
                   
                        invoke  InvalidateRect, 0, addr _rc, FALSE
                   
                        jmp     _ExitProcA

                    case    IDBUTAO1
                                       
                        invoke  InvalidateRect, 0, addr _rc, FALSE

                    jmp     _ExitProcA
                                       
                    ; --------------
                    ;     SAIR
                    ; --------------
                    case    IDM_SAIR

                        invoke  SendMessage, hWnd, WM_CLOSE, 0, 0
                        jmp     _ExitProcA                   
                    endsw
                                         
                    jmp     _EndProcA
; -----------------------------------------------------------------
;                             WM_SYSCOMMAND
; -----------------------------------------------------------------
_WM_SYSCOMMAND: cmp     edx, SC_CLOSE
                jne     _EndProcA
; -----------------------------------------------------------------
;                             WM_CLOSE
; -----------------------------------------------------------------
_WM_CLOSE:      invoke    DestroyWindow,  hWnd
                jmp       _ExitProcA
; -----------------------------------------------------------------
;                             WM_DESTROY
; -----------------------------------------------------------------
_WM_DESTROY:    call     DestroyAllBrushes

                invoke   PostQuitMessage, 0
                ;
_ExitProcA:     mov     eax, 0
                ret
WndProcA        endp
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
WndProcB        proc    hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

                mov     edx, wParam
                mov     eax, uMsg

                cmp     eax, WM_ERASEBKGND
                je      _WM_ERASEBKGND
               
                cmp     eax, WM_CLOSE
                je      _WM_CLOSE

                cmp     eax, WM_DESTROY
                je      _WM_DESTROY
               
                cmp     eax, WM_SYSCOMMAND
                je      _WM_SYSCOMMAND

; -----------------------------------------------------------------
_EndProcB:      invoke   DefWindowProc, hWnd, uMsg, wParam, lParam
                ret
; -----------------------------------------------------------------
;                           WM_ERASEBKGND
; -----------------------------------------------------------------
_WM_ERASEBKGND:     
            @@:     mov     ebx, _NextColorX
                    add     ebx, 1
                    mov     _NextColorX, ebx
                   
                    invoke  GetSystemColor, ebx
                    jnc     short _sys
                    ;
                    mov     ebx, _NextColorY
                    add     ebx, 1
                    mov     _NextColorY, ebx
                   
                    invoke  GetIdxBrushRcl, ebx
                    jnc     short _rcl
                    ;
                    mov     _NextColorX, 0
                    mov     _NextColorY, 0                   
                    jmp     short @B            ; start again                   
;.......................................................................................
        _rcl:       invoke  SetClassLong, _hWndY, GCL_HBRBACKGROUND, eax

                    invoke  GetNameRclColor, _NextColorY
                    invoke  SetWindowText, _hWndY, eax
                    jmp     _EndProcB
;.......................................................................................
        _sys:       add     eax, 1
                    invoke  SetClassLong, _hWndY, GCL_HBRBACKGROUND, eax

                    invoke  GetNameSysColor, _NextColorX
                    invoke  SetWindowText, _hWndY, eax
                    jmp     _EndProcB
; -----------------------------------------------------------------
;                             WM_SYSCOMMAND
; -----------------------------------------------------------------
_WM_SYSCOMMAND: cmp     edx, SC_CLOSE
                jne     _EndProcB
; -----------------------------------------------------------------
;                             WM_CLOSE
; -----------------------------------------------------------------
_WM_CLOSE:      ;invoke  DestroyWindow,  hWnd
                xor     eax, eax
                ret
; -----------------------------------------------------------------
;                             WM_DESTROY
; -----------------------------------------------------------------
_WM_DESTROY:    xor     eax, eax
                ret
WndProcB        endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    end     start


dedndave

1) no need to handle WM_SYSCOMMAND
just let DefWindowProc handle it for you
it will send a WM_CLOSE message

2) the background may be erased several times in the course of a session
you only need to SetWindowLong one time, probably during WM_CREATE

RuiLoureiro

Quote from: dedndave on February 16, 2013, 08:26:28 AM
1) no need to handle WM_SYSCOMMAND
just let DefWindowProc handle it for you
it will send a WM_CLOSE message

2) the background may be erased several times in the course of a session
you only need to SetWindowLong one time, probably during WM_CREATE

Dave,

:biggrin:
1. Ok when we are not sure we process WM_SYSCOMMAND. No problems !

2. No you are not right. See Window Classes in Platform SDK  ;)