News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

A question about windows

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

Previous topic - Next topic

RuiLoureiro

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.

dedndave

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

qWord

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
MREAL macros - when you need floating point arithmetic while assembling!

MichaelW

#18
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

Well Microsoft, here's another nice mess you've gotten us into.

RuiLoureiro

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.

RuiLoureiro

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)

dedndave

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

RuiLoureiro

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

RuiLoureiro

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»

dedndave

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
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/2008/08/01/8795860.aspx

one from CodeProject
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
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.

RuiLoureiro

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

dedndave

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

dedndave

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

RuiLoureiro

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

dedndave

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:



i cannot see other possible problems without looking at the code