The MASM Forum

General => The Campus => Topic started by: RuiLoureiro on February 15, 2013, 04:29:01 AM

Title: A question about windows
Post by: RuiLoureiro on February 15, 2013, 04:29:01 AM
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

Title: Re: A question about windows
Post by: qWord on February 15, 2013, 04:38:44 AM
it is very simple: use PostQuitMessage only if you wish to exit the message loop.
Title: Re: A question about windows
Post by: dedndave on February 15, 2013, 04:40:11 AM
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
Title: Re: A question about windows
Post by: qWord on February 15, 2013, 05:01:50 AM
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).
Title: Re: A question about windows
Post by: dedndave on February 15, 2013, 05:22:23 AM
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
Title: Re: A question about windows
Post by: RuiLoureiro on February 15, 2013, 08:40:54 AM
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:
Title: Re: A question about windows
Post by: dedndave on February 15, 2013, 11:09:51 AM
 :t
i bet we will see a GUI calculator in the near future   :biggrin:
Title: Re: A question about windows
Post by: RuiLoureiro on February 15, 2013, 09:36:38 PM
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!

Title: Re: A question about windows
Post by: RuiLoureiro on February 15, 2013, 11:26:00 PM
 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 !
Title: Re: A question about windows
Post by: qWord on February 15, 2013, 11:31:02 PM
Set the parent window of Y to X (CreateWindowEx->hWndParent = hMainWnd)
Title: Re: A question about windows
Post by: RuiLoureiro on February 15, 2013, 11:39:30 PM
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 ?
Title: Re: A question about windows
Post by: dedndave on February 16, 2013, 12:18:45 AM
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
Title: Re: A question about windows
Post by: RuiLoureiro on February 16, 2013, 04:45:23 AM
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

Title: Re: A question about windows
Post by: 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
Title: Re: A question about windows
Post by: RuiLoureiro on February 16, 2013, 08:50:45 AM
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  ;)
Title: Re: A question about windows
Post by: RuiLoureiro on February 17, 2013, 07:59:48 AM
Dave,       
        I think you understood now why i call SetClassLong everytime we want to
        change the background color. As far as i know, when the system wants to
        paint that window, it uses the class background color which we give
        when we call RegisterClassEx. So we need to change that class background
        color. We can use SetClassLong or we can use SelectObject if we get DC.
        SetClassLong seems to be the best way.
       
        I had no time today to do anything in home.
Title: Re: A question about windows
Post by: dedndave on February 17, 2013, 08:11:35 AM
well - i didn't notice what you were doing
it's a little unusual to change the bg color whenever the OS needs to update it - lol
Title: Re: A question about windows
Post by: qWord on February 17, 2013, 08:21:25 AM
Quote from: RuiLoureiro on February 16, 2013, 04:45:23 AMthe problem is this: my OverlappedWndX and Y assumes the window
        has not a parent and i dont want to modify it ... by now  :biggrin:
well, I can't see the problem. However, I'm not sure what you mean with "assumes the window has not a parent ".

qWord
Title: Re: A question about windows
Post by: MichaelW on February 17, 2013, 05:22:07 PM
In the several hours I spent on this, reusing a single class for all of the windows, I could not find any better method than changing the class background brush "on the fly".  Overlapped4.exe initializes the second window correctly, but if you drag it off screen and back it does not redraw correctly. This simpler source uses a single window procedure, opens multiple "child" windows, which can be closed independently, or collectively by closing the main window, and which redraw correctly. Tested under Windows 2000 and XP.

;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================
    .data
      hInstance HMODULE     0
      hWnd      HWND        0
      hwndMain  HWND        0
      x         dd          50
      y         dd          30
      nIndex    dd          COLOR_SCROLLBAR
      wcx       WNDCLASSEX  <>
      msg       MSG         <>
      className db          "test_class",0
    .code
;==============================================================================
include \masm32\procs\button.asm
;==============================================================================

WndProc proc hwnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

    SWITCH uMsg

        CASE WM_CREATE

            ;-------------------------------------------
            ; Cannot use hWnd here because WM_CREATE is
            ; sent before CreateWindowEx returns.
            ;-------------------------------------------

            .IF hwndMain == 0
                push hwnd
                pop hwndMain
                invoke PushButton, chr$("Next"), hwnd, 0, 0, 100, 30, 1000
            .ENDIF

        CASE WM_COMMAND

            SWITCH wParam

                CASE 1000

                    inc nIndex
                    .IF nIndex > COLOR_INFOBK
                        mov nIndex, COLOR_SCROLLBAR
                    .ENDIF

                    add x, 30
                    add y, 30

                    STYLE = WS_OVERLAPPED or WS_SYSMENU or WS_VISIBLE
                    invoke CreateWindowEx, 0,
                                           ADDR className,
                                           str$(nIndex),
                                           STYLE,
                                           x,y,100,100,
                                           hwnd, NULL,
                                           NULL, NULL
                    push eax
                    invoke UpdateWindow, eax
                    pop eax
                    invoke SetWindowLong, eax, 0, nIndex

            ENDSW

        CASE WM_ERASEBKGND

            mov eax, hwndMain
            .IF hwnd == eax
                invoke GetSysColorBrush, COLOR_WINDOW
            .ELSE
                invoke GetWindowLong, hwnd, 0
                .IF eax == 0
                    invoke GetSysColorBrush, nIndex
                .ELSE
                    invoke GetSysColorBrush, eax
                .ENDIF
            .ENDIF
            invoke SetClassLong, hwnd, GCL_HBRBACKGROUND, eax

            invoke DefWindowProc, hwnd, uMsg, wParam, lParam
            ret

        CASE WM_CLOSE

            invoke DestroyWindow, hwnd

        CASE WM_DESTROY

            mov eax, hwndMain
            .IF hwnd == eax
                invoke PostQuitMessage, NULL
            .ENDIF

        DEFAULT

            invoke DefWindowProc, hwnd, uMsg, wParam, lParam
            ret

    ENDSW

    return 0

WndProc endp

;==============================================================================
start:
;==============================================================================

    mov hInstance, rv(GetModuleHandle, NULL)

    mov wcx.cbSize,        SIZEOF WNDCLASSEX
    mov wcx.style,         CS_BYTEALIGNWINDOW
    mov wcx.lpfnWndProc,   WndProc
    mov wcx.cbClsExtra,    0
    mov wcx.cbWndExtra,    4
    m2m wcx.hInstance,     hInstance
    mov wcx.hbrBackground, 0              ; <<----<<<<
    mov wcx.lpszMenuName,  NULL
    mov wcx.lpszClassName, OFFSET className
    mov wcx.hIcon,         rv(LoadIcon, NULL, IDI_APPLICATION)
    mov wcx.hCursor,       rv(LoadCursor, NULL, IDC_ARROW)
    mov wcx.hIconSm,       0

    invoke RegisterClassEx, ADDR wcx

    invoke CreateWindowEx, 0,
                           ADDR className,
                           chr$("Test"),
                           WS_OVERLAPPED or WS_SYSMENU,
                           0,0,800,600,
                           NULL, NULL,
                           NULL, NULL
    mov hWnd, eax

    invoke ShowWindow, hWnd, SW_SHOWNORMAL
    invoke UpdateWindow, hWnd

  msgLoop:

    invoke GetMessage, ADDR msg, NULL, 0, 0
    .IF eax != 0
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
        jmp   msgLoop
    .ENDIF

    exit msg.wParam

;==============================================================================
end start

Title: Re: A question about windows
Post by: RuiLoureiro on February 18, 2013, 02:18:27 AM
MichaelW,
         Thanks to see you here !  :biggrin:

«but if you drag it off screen and back it does not redraw correctly».

See what happen with the name of that second window when we drag it
off screen. It changes because the system sends WM_ERASEBKGND.

That example shows us that when the windows is off screen we get
WM_ERASEBKGND.
It is easy to solve that problem.

        About your test prog, the following is the key when
        we get WM_ERASEBKGND:

            «invoke SetClassLong, hwnd, GCL_HBRBACKGROUND, eax
             invoke DefWindowProc, hwnd, uMsg, wParam, lParam».

qWord,
        Thanks to put the problem !
       
        «well, I can't see the problem.»

    .   the problem is to test all cases.
        But there is no problem because it works in all cases
        in the same way.

        «However, I'm not sure what you mean with
        "assumes the window has not a parent ".»

    .   i wrote OverlappedWndX and OverlappedWndY to my lib
        to register and create (and more things) a window with
        only this arguments:

          x,y,lx,ly,fPos,hBrh,nIcon,nMenu,nWnd,style,exstyle,pPrc
               
      all other are 0 (=> so it assumes the window has not a parent).

    . But now i have OverlappedWndX, OverlappedWndY,
      OverlappedWndZ (with hPar - 13 args)
      PopupWindowX, ChildWindowX (with hPar- 13 args)

In the next post we will see this:
     
In Overlapped5.exe we create the second window overlapped without parent
In Overlapped6.exe we create the second window overlapped with parent
In Overlapped7.exe we create the second window popup with parent
In Overlapped8.exe we create the second window child with parent

In all cases we create the main window as overlapped

In all cases the second window is inside a function and
has also a second message loop. It means that when we
call that function we need to wait it exits on the next line
...
EDIT:
MichaelW,
          I want to create the second window in another class with
          a new window procedure to control the messages more
          easily.
Title: Re: A question about windows
Post by: RuiLoureiro on February 18, 2013, 02:42:35 AM
In all cases i didnt solve the drag problem because it is a simple question.

The second window is created with invoke FuncWndY. The Param is to be
used in another case.

I am using the PostQuitMessage with Code to exit the second loop

Here is Overlapped5.zip to Overlapped8.zip (.exe .asm)
Title: Re: A question about windows
Post by: dedndave on February 18, 2013, 03:08:53 AM
QuoteI want to create the second window in another class with a
new window procedure to control the messages more easily.

you can create another class with its' own WndProc without having another thread and message loop   :P

i don't understand what problem you are having "drag problem" ?

tell us what you want - we can make small examples easily
you want a main window, with a second window (that has no title bar) you can move inside it ?

i do understand that writing your own drag/move code isn't simple - lol
Title: Re: A question about windows
Post by: RuiLoureiro on February 18, 2013, 05:18:30 AM
Dave,
      do you know ? No home ... w o r k ... rule !
     
      you misunderstood the question. MichaelW wrote and posted an exemple
      where he creates 2 wnds using the same class. In my examples i
      used 2 classes because ...

      If we take the 2nd wnd with mouse and move it, you will see the problem.

***---***

      Now we can see Overlapped10.zip (.ex .asm) using a new thread.
      In this case we call ThreadFuncY which runs the function
      FuncWndY. When we choose a button to exit we send a message
      WM_RETURN to the main window X.

      We can move the second window, no problem now...
Title: Re: A question about windows
Post by: RuiLoureiro on February 18, 2013, 11:09:56 PM
Quote from: RuiLoureiro on February 15, 2013, 11:26:00 PM
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 !

set extended window style of the second window Y to WS_EX_TOPMOST
and dont set it to the main window X.
An API to do this: «invoke SetForegroundWindow, hWndY»
Title: Re: A question about windows
Post by: dedndave on February 18, 2013, 11:29:51 PM
sounds simple, huh
but, it's not
in the end, you might like SetWindowPos   :biggrin:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539%28v=vs.85%29.aspx)
be sure to read the user comments - lol

Raymond Chen and Mark Russinovich are always good
http://blogs.msdn.com/b/oldnewthing/archive/2009/02/20/9435239.aspx (http://blogs.msdn.com/b/oldnewthing/archive/2009/02/20/9435239.aspx)
http://blogs.msdn.com/b/oldnewthing/archive/2008/08/01/8795860.aspx (http://blogs.msdn.com/b/oldnewthing/archive/2008/08/01/8795860.aspx)

one from CodeProject
http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo (http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo)

a couple functions....
LockSetForegroundWindow
AllowSetForegroundWindow 

and, a little goodie on multi-threaded input queues
http://support.microsoft.com/kb/90975 (http://support.microsoft.com/kb/90975)
QuoteCreating a window can force an implicit AttachThreadInput(), when a parent window is created in
one thread and the child window is being created in another thread. When windows are created
(or set) in separate threads with a parent-child relationship, the input queues are attached.
Title: Re: A question about windows
Post by: RuiLoureiro on February 18, 2013, 11:56:26 PM
. Did you read this particular question/example, Dave ?
  Or do you want to show other cases ?
Simply i didnt know.
                                                                            handle, window procedure
Main   Window X: invoke  OverlappedWndX  => _hWndX,    WndProcA
Second Window Y: invoke  OverlappedWndY  => _hWndY,    WndProcB

Class X = "Overlapped_A"
Class Y = "Overlapped_B"
Title: Re: A question about windows
Post by: dedndave on February 19, 2013, 12:03:18 AM
well - i have a hard time reading some of your text
i just know, from experience, that SetForegroundWindow doesn't always work the way you think it should   :biggrin:

here is some code i use to bring a window to the front
        INVOKE  SetWindowPos,hWnd,HWND_TOPMOST,eax,eax,eax,eax,SWP_NOMOVE or SWP_NOSIZE
        INVOKE  SetWindowPos,hWnd,HWND_NOTOPMOST,eax,eax,eax,eax,SWP_NOMOVE or SWP_NOSIZE

the value in EAX doesn't matter

the first call sets the window to topmost
the second call allows the user to change z-order, by normal clicking
Title: Re: A question about windows
Post by: dedndave on February 19, 2013, 12:57:16 AM
another way SetWindowPos may be used is to set one window behind another
let's say your app is running, but the user has another window on top to work with that app
your window may be partially visible, but not on top
your app has a main window and a "non-child" foreground window
you don't want to take over the topmost position in the z-order because that would annoy the user
but, you want your foreground window to be on top of your main window

        INVOKE  SetWindowPos,hMainWindow,hForeWindow,eax,eax,eax,eax,SWP_NOMOVE or SWP_NOSIZE

SetWindowPos is one of the most powerful tools you have when it comes to controlling z-order   :t
Title: Re: A question about windows
Post by: RuiLoureiro on February 19, 2013, 09:05:18 AM
Dave,
      I used and tested SetWindowPos in all Overlapped?.exe after your suggestion
      some posts before without any problems.
     
      Following what i want to do, i dont want to change the z-order in any time
      in any case after creating the windows.
      In the cases like this where i want to use 2 windows, i want to
      start specifying if the 2nd window has a parent or not and the styles to get
      the behavior i want (minimized, maximized, or restored). After testing i
      decide what to do. For example, if the 2nd window has a parent we have
      one behavior; If it has not we have another behavior;If it is a child it
      has another. But in any case i dont want to change. For now it is like a rule.
      Well, if i dont want to change the z-order in any time in any case i must start
      choosing the correct style or the second has a parent as qWord suggested
      which works well too.

Here is Overlapped9.zip (without SetWindowPos or SetForegroundWindow )
The 2nd window is overlapped without parent and uses WS_EX_TOPMOST.
Overlapped9 uses 57 color brushes.

Is there any problem that i dont know ?
Thanks
Title: Re: A question about windows
Post by: dedndave on February 19, 2013, 09:38:28 AM
i don't know if these are "problems"   :P
it may be the way you intended it to be

in the pic, i have clicked on Windows Explorer to bring it to the front
your foreground window is topmost, and does not allow it

also - the program is 230 kb   :icon_eek:

(http://img803.imageshack.us/img803/133/ruia.png)

i cannot see other possible problems without looking at the code
Title: Re: A question about windows
Post by: RuiLoureiro on February 21, 2013, 03:10:44 AM
Dave,

«i don't know if these are "problems" it may be the way you intended it to be»

    .   Yes it is to test, to see what happen in each case


«also - the program is 230 kb»

    .   I dont know why. Maybe this has something to do with the inclusion
        of my lib, no ?
Title: Re: A question about windows
Post by: RuiLoureiro on February 23, 2013, 05:16:10 AM
Dave,
        The problem (of 230K) is with my lib.
       
        The masm assembler put all things
        that belong to my lib into the
        previous Overlapped.exe files.
       
        I would like to know why if
        it needs only one file or so ?
        Is there no way to avoid it ?

        Here is Overlapped12 10K bytes.

        Now i want to put a green button.
        Do you know how to do that ?
        Thanks !
Title: Re: A question about windows
Post by: qWord on February 23, 2013, 05:24:58 AM
Quote from: RuiLoureiro on February 23, 2013, 05:16:10 AMIs there no way to avoid it ?
there is a way: put everything in separate modules, whereas procedures/functions and variables that have a direct dependency can be place in one module (e.g. function A call function B -> A and B could be in the same module*)

EDIT: *as long as B private for that module.
Title: Re: A question about windows
Post by: dedndave on February 23, 2013, 05:36:06 AM
setting the background color on buttons can be a pain in the butt   :P
the easiest way might be to set a green image into the button

as for the library....
yes - everything in seperate modules, as qWord said
but, there is more at play than that
your library module(s) have large arrays of uninitialized data or something that are declared in the .DATA section
they should be moved to the .DATA? section
we can't really say, because  we don't have the source   :P

i know your lib has a lot of code
and it has a lot of text strings in it (probably the biggest thing)
but, i would guess it should be under 50 kb or so
Title: Re: A question about windows
Post by: RuiLoureiro on February 23, 2013, 06:10:09 AM
qWord,
        Thanks !
        You should know that my lib is a set of asm files
        something like this: Cnv0.asm, Cnv1.asm, Cnv2.asm,
        Win0.asm, Win1.asm, Msg.asm, Prn0.asm, Prn1.asm,
        Fic2.asm, FicIo.asm, FicLis.asm, Fnt.asm, etc. etc. etc.       
        This is compiled to Mylib.lib (now 660K only).
        Each file has its externdef/protos in files .glb
        (Cnv0.glb, etc. etc.).
       
        In Overlapped9.exe i used Mylib.lib and i included
        only Win1.glb and i got 230K. I copy/paste Win1.asm
        into Overlapped12 and i got 10K !
        Why 230K in this case ?

        Well when i work in a large project i need nearly all
        Mylib.lib or so. And nowadays memory is not a problem
        to run it.

Dave,
        «your library module(s) have large arrays of uninitialized data»
       
        .   I cannot define arrays of uninitialized data because
            all my arrays have a structure behind like all my strings,
            tables, etc.
       
        Now Overlapped12.zip is .exe and .asm.
Title: Re: A question about windows
Post by: dedndave on February 23, 2013, 06:18:38 AM
i am guessing that the object modules are not seperate, though
when you build the library, you should be adding numerous small OBJ's

on the other hand, you may intend to use the entire library when you make your calculator program
if that's the case, it will work, as is
but - not very nice if you want to use a specific module elsewhere

the source we needed to see was for the lib code - not the GUI   :P
you probably don't want to give that up, yet
but - you'll figure it out   :t
Title: Re: A question about windows
Post by: RuiLoureiro on February 23, 2013, 07:08:12 AM
Dave,
          the calculator program doesnt use any file of mylib
          and doesnt use mylib.lib. It was written as a standalone,
          procedure by procedure. And what is in that program is
          not in any file of mylib and is not in mylib.lib. 
          It is in a separate lib ;)
Title: Re: A question about windows
Post by: dedndave on February 23, 2013, 09:04:46 AM
ok - my mistake - it is something else
the fact remains that the library probably requires a little re-organization   :P
Title: Re: A question about windows
Post by: dedndave on February 23, 2013, 12:37:25 PM
hey, Rui - i just happened to think....
if you look at how Hutch builds the masm32.lib,
in the \masm32\m32lib folder, you will find a file named make.bat
it shows how he creates a response file to build the lib
Title: Re: A question about windows
Post by: RuiLoureiro on February 26, 2013, 07:00:04 AM
Dave,
        i am using the same as make.bat in m32lib folder

Is this:

@echo off
cls
del    MyLib.lib
dir /b *.asm > ml.rsp : create a response file for ML.EXE
echo.
echo    *******************************************
echo    ** Assembling MyLib.lib library modules **
echo    *******************************************
echo.
:\masm32\bin\ml /c /coff MyLib.asm
:dir  *.obj

\masm32\bin\ml /c /coff @ml.rsp
if errorlevel 0 goto okml

del ml.rsp
echo ASSEMBLY ERROR BUILDING LIBRARY MODULES
goto theend

:okml
echo.
echo    ********************************
echo    ****** Linking MyLib.lib *******
echo    ********************************
echo.

\masm32\bin\link -lib *.obj /out:MyLib.lib

if exist MyLib.lib goto theend

echo ---------------------------------
echo LINK ERROR BUILDING LIBRARY
echo ---------------------------------

:theend
if exist MyLib.lib del *.obj

dir *.lib
pause