News:

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

Main Menu

detect if the window of my app is totally being covered by another window

Started by Siekmanski, May 26, 2013, 08:32:46 PM

Previous topic - Next topic

Siekmanski

Is there a way to detect if the window of my app is totally ( not partially ) being covered by a window of another app.
Then I can stop drawing to my window.

I tried "WM_SHOWWINDOW" but had no succes.


   .elseif wMsg == WM_SHOWWINDOW
        .if wParam == FALSE
            .if lParam == SW_OTHERZOOM
                mov         b_Pause,TRUE
            .elseif  lParam == SW_OTHERUNZOOM
                mov         b_Pause,FALSE
             .endif
       .endif
       return   0
Creative coders use backward thinking techniques as a strategy.

dedndave

GetForegroundWindow

sorry - totally covered is a little more difficult
you would have to use WindowFromPoint or something

best thing to do is to update only the window portion that is requested in the PAINTSTRUCT rcPaint
if your window is totally covered, you won't get WM_PAINT messages at all

you are probably updating on some timer   :P
so - instead of drawing, InvalidateRect and UpdateWindow
and do the drawing in WM_PAINT

Siekmanski

Hoping there was some kind of windows message for this case.
Drawing from the WM_PAINT is not an option in my app.
Creative coders use backward thinking techniques as a strategy.

jj2007

This should do the job:

GetUpdateRect: If there is no update region, the return value is zero

As Dave already wrote, a fully covered window doesn't receive WM_PAINT - precisely because it has nothing to update.

dedndave


Siekmanski

"GetUpdateRect" didn't do the job.
It stops the drawing when the window is minimized but not if it is totally covered by another window.

The only thing I can think of is "WM_ACTIVATEAPP", drawing stops if my window has lost focus.
But what I really want is to stop drawing only if my window is totally covered.
Creative coders use backward thinking techniques as a strategy.

hfheatherfox07

Hello ,
Just a sily idea but have you tried
HWND_TOPMOST
I google that and masm32 and got so many snipits here on this forum
I know that command sets window top most , maybe a way to return that value ?

Some search results I got:

http://masm32.com/board/index.php?topic=1483.15

http://www.masmforum.com/board/index.php?PHPSESSID=786dd40408172108b65a5a36b09c88c0&topic=4662;prev_next=next


I did something similar with buttons focus , with set focus  WM_KILLFOCUS

http://www.masmforum.com/board/index.php?PHPSESSID=786dd40408172108b65a5a36b09c88c0&topic=17338.0


Maybe this can be of some help to you?
Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

jj2007

Quote from: Siekmanski on May 27, 2013, 03:55:44 AM
"GetUpdateRect" didn't do the job.
It stops the drawing when the window is minimized but not if it is totally covered by another window.

The sequence is:
- Windows thinks your window needs painting
- in that moment, GetUpdateRect returns a rectangle
- but you also get a WM_PAINT message
- in either case, you paint
- you ValidateRect
- if you don't, GetUpdateRect will continue complaining that there is a rectangle to be painted

So where in that sequence is your problem?

dedndave

i think, if you do not handle WM_PAINT messages, the default processing validates the update area
so - it might appear as though there is no update area

a possible workaround might be to have a "dummy" WM_PAINT handler
    .elseif uMsg==WM_PAINT
        INVOKE  BeginPaint,hWnd,offset ps
        INVOKE  EndPaint,hWnd,offset ps
        xor     eax,eax                   ;return FALSE


by using a static PAINTSTRUCT structure, you will have the most recent update rectangle
once you have read the rectangle values, you could set a member of
the structure to 0 to indicate it has been read (like ps.hdc, for example)

qWord

Using the update rectangle won't work if desktop composition (->DWM) is enabled, because the content of each window is stored separately and combined by/in the graphics card to the final screen-image. Therefore overlapping a window does not automatically invalidate the corresponding region.
Quote from: msdn: Desktop Window ManagerThe desktop composition feature, introduced in Windows Vista, fundamentally changed the way applications display pixels on the screen. When desktop composition is enabled, individual windows no longer draw directly to the screen or primary display device as they did in previous versions of Windows. Instead, their drawing is redirected to off-screen surfaces in video memory, which are then rendered into a desktop image and presented on the display.
MREAL macros - when you need floating point arithmetic while assembling!

jj2007

Quote from: dedndave on May 27, 2013, 06:22:04 AM
i think, if you do not handle WM_PAINT messages, the default processing validates the update area

I get the impression that he has the opposite problem: "It stops the drawing when the window is minimized but not if it is totally covered by another window."
You can paint using the DC directly, but if you do not validate the rect, how does Windows know that painting is complete? So GetUpdateRect will continue returning "I got a region that needs updating"...

Siekmanski

I don't want it to be always on top.
This is the D3D9 proggy I'm talking about,

http://masm32.com/board/index.php?topic=1890.msg20256#msg20256

Common\Direct3D9_Main.Asm


WndProc proc hwnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD

    .if wMsg == WM_DESTROY
        invoke      PostQuitMessage,NULL
        return  0

;   .elseif wMsg == WM_ACTIVATEAPP
;       .if wParam == TRUE
;            mov         b_Pause,FALSE
;       .else
;            mov         b_Pause,TRUE
;       .endif
;       return   0

    .elseif wMsg == WM_SIZE
        .if wParam == SIZE_MINIMIZED
            mov         b_Pause,TRUE
        .elseif wParam == SIZE_MAXIMIZED
            coinvoke    g_pD3DDevice,IDirect3DDevice9,Reset,addr d3dpp
            mov         b_Pause,FALSE
        .elseif wParam == SIZE_RESTORED
            coinvoke    g_pD3DDevice,IDirect3DDevice9,Reset,addr d3dpp
            invoke      RenderD3d
            mov         b_Pause,FALSE
        .endif
        return  0

    .elseif wMsg == WM_PAINT
        invoke      ValidateRect,hwnd,NULL
        return  0

    .elseif wMsg == WM_KEYDOWN
        .if wParam == VK_ESCAPE
            invoke      PostQuitMessage,WM_QUIT
            return  0
        .elseif wParam == VK_F1
            mov         b_Pause,TRUE
            invoke      ToggleFullScreen
            mov         b_Pause,FALSE
        .endif
        return  0
    .else
        invoke      DefWindowProc,hwnd,wMsg,wParam,lParam
        ret
    .endif
WndProc endp


The message part,


    invoke      RtlZeroMemory,addr msg,sizeof msg

    .while ( msg.message != WM_QUIT )

        .if (b_Pause == FALSE)
            invoke      PeekMessage,addr msg,NULL,0,0,PM_REMOVE
        .else
            invoke      GetMessage,addr msg,NULL,0,0
        .endif

        .if eax != 0
            invoke      TranslateMessage,addr msg
            invoke      DispatchMessage,addr msg
        .else
            .if (b_Pause == FALSE)
                invoke      RenderD3d
            .endif
        .endif
    .endw
Creative coders use backward thinking techniques as a strategy.

Siekmanski

Also no succes:
   .elseif uMsg==WM_PAINT
        INVOKE  BeginPaint,hWnd,offset ps
        INVOKE  EndPaint,hWnd,offset ps
        xor     eax,eax                   ;return FALSE

In combination with:

    invoke      GetUpdateRect,hWnd,NULL,TRUE
    .if (eax == 0)
               invoke      RenderD3d
    .endif

Creative coders use backward thinking techniques as a strategy.

dedndave

give this a try   :P

IsWindowHidden PROC USES EBX ESI EDI hWnd:HWND

;---------------------------------

        LOCAL   _rcClient :RECT

;---------------------------------

        mov     ebx,hWnd
        INVOKE  GetClientRect,ebx,addr _rcClient
        mov     eax,_rcClient.bottom
        cmp     eax,_rcClient.top
        jbe     IsHdn2

        mov     edx,_rcClient.right
        cmp     edx,_rcClient.left
        jbe     IsHdn2

        INVOKE  ClientToScreen,ebx,addr _rcClient.left
        INVOKE  ClientToScreen,ebx,addr _rcClient.right
        INVOKE  WindowFromPoint,_rcClient.left,_rcClient.top
        cmp     eax,ebx
        jz      IsHdn3

        INVOKE  WindowFromPoint,_rcClient.right,_rcClient.top
        cmp     eax,ebx
        jz      IsHdn3

        INVOKE  WindowFromPoint,_rcClient.left,_rcClient.bottom
        cmp     eax,ebx
        jz      IsHdn3

        INVOKE  WindowFromPoint,_rcClient.right,_rcClient.bottom
        cmp     eax,ebx
        jz      IsHdn3

        mov     esi,_rcClient.bottom
        mov     edi,_rcClient.right
        add     esi,_rcClient.top
        shr     esi,1

IsHdn0: INVOKE  WindowFromPoint,edi,esi
        cmp     eax,ebx
        jz      IsHdn3

        dec     edi
        cmp     edi,_rcClient.left
        jae     IsHdn0

        mov     esi,_rcClient.right
        mov     edi,_rcClient.bottom
        add     esi,_rcClient.left
        shr     esi,1

IsHdn1: INVOKE  WindowFromPoint,esi,edi
        cmp     eax,ebx
        jz      IsHdn3

        dec     edi
        cmp     edi,_rcClient.top
        jae     IsHdn1

IsHdn2: mov     eax,TRUE
        jmp short IsHdn4

IsHdn3: xor     eax,eax

IsHdn4: ret

IsWindowHidden ENDP


EDIT: corrected a few mistakes

jj2007

Sorry if that is a stupid question - shouldn't it be the other way round, i.e. "render if there is something to update"?

Quote from: Siekmanski on May 27, 2013, 08:09:23 AM
    invoke      GetUpdateRect,hWnd,NULL,TRUE
    .if eax
               invoke      RenderD3d
    .endif