News:

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

Main Menu

Forcing a paint from Window handler?

Started by BlueMR2, September 26, 2014, 09:05:11 AM

Previous topic - Next topic

BlueMR2

I'm hung up with something that should be easy, but continues to elude me.  My key handling section of the window handler gets called as appropriate.  I then adjust some variables used by my paint handler.  However, the paint handler never gets called again.  I'm guessing I have to send some sort of signal to let windows know that I need to repaint.  Is that even the correct approach?  I've tried a number of things and while they all assemble fine, none of them seem to do anything.  :-)
My Code Site
https://github.com/BrianKnoblauch

dedndave

there are a couple ways to cause it to update, but first....

windows keeps track of what is called an "update region"

if some other window is on top of yours, let's say, in the lower right corner,
then that window is removed or minimized, the portion of your window that needs to be repainted is set into the update region

other things can cause the update region to change, as well
when windows sees that a window has no other (higher priority) messages in the queue,
and the update region is not NULL, it sends a WM_PAINT message
there is a RECT structure inside the PAINTSTRUCT that tells you what portion requires update

the simple way is to cause it to add the entire client area to the update region
        INVOKE  InvalidateRect,hWnd,NULL,<background_flag>
the first argument is the window handle
the second is a pointer to a client coordinate rectangle describing the region to add (NULL = entire client)
the third one is TRUE if you want the background redrawn, FALSE if not

http://msdn.microsoft.com/en-us/library/dd145002%28v=vs.85%29.aspx

in the left pane of that page, you'll see a few other functions
InvalidateRgn is similar (regions are irregular or non-rectangular areas)
ValidateRect and ValidateRgn are related
and, RedrawWindow may also be used to force a redraw (often used to redraw the entire window)

dedndave

you can use this thread for flicker related problems, as well   :biggrin:

Zen

BLUEMR2, 
As always,...DAVE (above) is correct.
If you need an immediate Repaint of the client area, just call: UpdateWindow.
I usually call this in tandem with: ShowWindow.
This NEVER fails and is totally foolproof,...:icon_eek:
Zen

dedndave

true enough - you may see the two functions used together
        INVOKE  InvalidateRect,hWnd,NULL,TRUE
        INVOKE  UpdateWindow,hWnd


InvalidateRect adds some area to the update region
but, the operating system treats WM_PAINT messages as a low priority
the message loop queue will only dispatch WM_PAINT to WndProc when no other messages are in the queue

UpdateWindow, on the other hand, causes the WM_PAINT message to be sent immediately, bypassing the queue
however - it only does so if the update region is not empty   :P

http://msdn.microsoft.com/en-us/library/dd145167%28v=vs.85%29.aspx

fearless

The RedrawWindow function seems to be quite useful for forcing updates. Useful for containers that have children and you dont want to enumerate them all before calling invalidrect/updatewindow.

Invoke RedrawWindow, hWin, NULL, NULL, RDW_UPDATENOW + RDW_INVALIDATE + RDW_ALLCHILDREN

dedndave

i was using RedrawWindow for a while - thinking it worked great
but, it may have a nasty side-effect
when calling RedrawWindow for several windows (children, etc), it seems to cause the desktop to refresh
this is particularly noticable when you first open the app

RedrawWindow may be a necessary call if you change the appearance of the non-client area (borders, etc)
otherwise, i stopped using it for general-purpose updates

BlueMR2

Well, gee, I'm really at a loss then.  Great information, but I'm still not able to get it working.  I know the right part of the key handler is called, I can insert an exit app function call in there and it happens.  However, when I have code there that updates the location variables for my graphics, I never see anything change on-screen.  I've tried limiting the update region to just the area affected and I've also tried it as the full window (via NULL).  I tried tracing it through with Ollydbg, but with my single screen machine here that doesn't work terribly well and I end up having to force a shutdown of Ollydbg.

I do an initial set of the variables based on the WM_CREATE message.  Is that ever called after the initial creation of the window?  Perhaps I misunderstand how that message works and I'm repeatedly overwriting my changes with the defaults?
My Code Site
https://github.com/BrianKnoblauch

dedndave

#8
maybe this example will help - you can ignore the Bezier spline stuff, and just look at InvalidateRect, WM_PAINT, WM_TIMER, etc

http://masm32.com/board/index.php?topic=1969.msg20895#msg20895

WM_CREATE is sent only once
the window is created, but not displayed at that time (as i remember)
the CreateWindowEx call does not exit until WM_CREATE has returned

jj2007

Quote from: BlueMR2 on October 07, 2014, 05:29:34 AMI tried tracing it through with Ollydbg

That won't work, too much stuff happening in parallel.

Attached an example that uses the deb macro to display all messages in a console, with the exception of a few frequent but irrelevant ones, such WM_MOUSEMOVE. Plug in your code in the appropriate handlers and watch which messages are of interest. You can insert an extra deb wherever you need it - see Other WM_COMMAND in the source. Below a typical output. You can see that the first WM_PAINT comes late in the process, as msg #33. The edit control's ID is 103.

msg     chg:msgCount    1       uMsg = Start monitoring
msg     chg:msgCount    2       uMsg = WM_GETMINMAXINFO
msg     chg:msgCount    3       uMsg = WM_NCCREATE
msg     chg:msgCount    4       uMsg = WM_NCCALCSIZE
msg     chg:msgCount    5       uMsg = WM_CREATE
msg     chg:msgCount    6       uMsg = WM_WINDOWPOSCHANGING
msg     chg:msgCount    7       uMsg = WM_NCCALCSIZE
msg     chg:msgCount    8       uMsg = WM_WINDOWPOSCHANGED
msg     chg:msgCount    9       uMsg = WM_MOVE
msg     chg:msgCount    10      uMsg = WM_SIZE
msg     chg:msgCount    11      uMsg = WM_PARENTNOTIFY
msg     chg:msgCount    12      uMsg = WM_WINDOWPOSCHANGING
msg     chg:msgCount    13      uMsg = WM_ACTIVATEAPP
msg     chg:msgCount    14      uMsg = WM_NCACTIVATE
msg     chg:msgCount    15      uMsg = WM_ACTIVATE
msg     chg:msgCount    16      uMsg = WM_IME_SETCONTEXT
msg     chg:msgCount    17      uMsg = WM_IME_NOTIFY
msg     chg:msgCount    18      uMsg = WM_SETFOCUS
msg     chg:msgCount    19      uMsg = WM_KILLFOCUS
msg     chg:msgCount    20      uMsg = WM_IME_SETCONTEXT

Other WM_COMMAND
eax             103
edx             256
lParam          199984
msg     chg:msgCount    21      uMsg = WM_COMMAND
msg     chg:msgCount    22      uMsg = WM_SHOWWINDOW
msg     chg:msgCount    23      uMsg = WM_WINDOWPOSCHANGING
msg     chg:msgCount    24      uMsg = WM_NCPAINT
msg     chg:msgCount    25      uMsg = WM_GETTEXT
msg     chg:msgCount    26      uMsg = WM_ERASEBKGND
msg     chg:msgCount    27      uMsg = WM_WINDOWPOSCHANGED
msg     chg:msgCount    28      uMsg = WM_SIZE
msg     chg:msgCount    32      uMsg = WM_MOVE
msg     chg:msgCount    33      uMsg = WM_PAINT
msg     chg:msgCount    34      uMsg = WM_CTLCOLOREDIT
msg     chg:msgCount    35      uMsg = WM_CTLCOLOREDIT
msg     chg:msgCount    36      uMsg = WM_NCACTIVATE
msg     chg:msgCount    37      uMsg = WM_GETTEXT
msg     chg:msgCount    38      uMsg = WM_ACTIVATE
msg     chg:msgCount    39      uMsg = WM_ACTIVATEAPP

Other WM_COMMAND
eax             103
edx             512
lParam          199984

Zen

Hi, BLUEMR2,   
This one has me mystified too. Like you stated in the first post, it should be simple.
Is this a normal windows app, or is it a DirectX app ?
If it is a DirectX app, you should be polling for the key down actions, and not waiting for the normal Windows message.
...Also, you can define your own windows message identifiers,...and, then call SendMessage to send them to your window. It's FUN. I often do this for testing purposes,...and, if you eventually post your source code here on the MASM Forum,...it confuses other assembly programmers,...yes, sometimes even DAVE,...
Here is: About Messages and Message Queues, MSDN, which you have no doubt already read.   
Here is: Keyboard Input, MSDN, which you undoubtedly have already read.
And, here's more: GetAsyncKeyState, MSDN,...again, I'm certain you have already read this,...

But, really,...what I'm wondering is: Why don't you show us some code ??? MASM Forum residents LOVE source code,...
Zen

Gunther

Quote from: Zen on October 07, 2014, 06:55:01 AM
But, really,...what I'm wondering is: Why don't you show us some code ??? MASM Forum residents LOVE source code,...

Excellent point, Zen.  :t

Gunther
You have to know the facts before you can distort them.

BlueMR2

OK, I'll try to trim it down to the bare essentials.  Here's an example based heavily (like 98%) :-) on Dave's "display a dot" code, but theoretically, the dot should move with various keypresses.  I've commented out some extra code that I tried that also does nothing.

I'll be going through the code recently attached above, as well as the referenced links again.  I appreciate all the help, whatever I'm missing is probably something really simple and silly...

Also, sorry for the big gaps in time between posts, but lately I only get an hour or 2 every couple of weeks to play on my computer at home...  :-(


.686
option casemap:none

include \masm32\include\masm32rt.inc

FSWnd   PROTO :HWND,:UINT,:WPARAM,:LPARAM

.data
    icc INITCOMMONCONTROLSEX <sizeof INITCOMMONCONTROLSEX,0>
    wc  WNDCLASSEX <sizeof WNDCLASSEX,NULL,FSWnd,0,0,?,?,?,COLOR_SCROLLBAR+1,NULL,szClassName,?>
    szAppName       db 'ProjectCQB',0
    szClassName     db 'ProjectCQBClass',0

.data?
    hwndMain        HWND    ?
    dwXpos          dd      ?
    dwYpos          dd      ?
    msg             MSG     <>
    updateregion    RECT    <>          ; Left, Top, Right, Bottom

.code
start:
    call    main                       
    invoke  ExitProcess,eax   
   
FSPaint PROC    hWnd:HWND
    local   ps      :PAINTSTRUCT
    invoke  BeginPaint,hWnd,addr ps
    invoke  SetPixel,ps.hdc,dwXpos,dwYpos,0
    invoke  EndPaint,hWnd,addr ps
    ret
FSPaint ENDP

FSWnd   PROC    hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    mov     eax,uMsg
    .if eax==WM_PAINT
        invoke  FSPaint,hWnd
        xor     eax,eax
    .elseif eax==WM_CREATE
        invoke  GetSystemMetrics,SM_CYSCREEN
        mov     edx,eax
        push    eax
        shr     edx,1
        mov     dwYpos,edx
        invoke  GetSystemMetrics,SM_CXSCREEN
        mov     edx,eax
        shr     edx,1
        mov     dwXpos,edx
        pop     ecx
        mov     edx,hWnd
        mov     hwndMain,edx
        invoke  SetWindowPos,edx,HWND_TOPMOST,0,0,eax,ecx,0
        xor     eax,eax
    .elseif eax==WM_CHAR
        .if     wParam==VK_ESCAPE
        invoke  PostMessage,hWnd,WM_SYSCOMMAND,SC_CLOSE,NULL    ; Close full screen window
        .elseif wParam==VK_UP
        dec     dwYpos       
        .elseif wParam==VK_DOWN
        inc     dwYpos
        .elseif wParam==VK_RIGHT
        inc     dwXpos
        .elseif wParam==VK_LEFT
        dec     dwXpos
        .endif   
        ;mov     eax, dwXpos     
        ;mov     updateregion.left, eax
        ;mov     updateregion.right, eax
        ;mov     eax, dwYpos
        ;mov     updateregion.top, eax
        ;mov     updateregion.bottom, eax
        ;invoke  InvalidateRect,hWndMain,offset updateregion,FALSE
        invoke  InvalidateRect,hWnd,NULL,FALSE
        invoke  UpdateWindow,hWnd
        xor     eax,eax       
    .elseif eax==WM_CLOSE
        invoke  DestroyWindow,hWnd
        xor     eax,eax
    .elseif eax==WM_DESTROY
        invoke  PostQuitMessage,NULL
        xor     eax,eax
    .else
        invoke  DefWindowProc,hWnd,uMsg,wParam,lParam
    .endif
    ret
FSWnd   ENDP

main   PROC
        invoke  InitCommonControlsEx,offset icc         ;initialize common controls
                                                        ;register the window class
        xor     edi,edi                                 ;EDI = 0
        mov     esi,offset wc                           ;ESI = offset wc
        invoke  GetModuleHandle,edi
        mov     [esi].WNDCLASSEX.hInstance,eax
        xchg    eax,ebx                                 ;EBX = wc.hInstance
        invoke  LoadIcon,ebx,501
        mov     [esi].WNDCLASSEX.hIcon,eax
        mov     [esi].WNDCLASSEX.hIconSm,eax
        invoke  LoadCursor,edi,IDC_ARROW
        mov     [esi].WNDCLASSEX.hCursor,eax
        invoke  RegisterClassEx,esi
                                                        ;create the window
        invoke  CreateWindowEx,edi,offset szClassName,offset szAppName,
                WS_POPUP or WS_VISIBLE or WS_CLIPCHILDREN,
                CW_USEDEFAULT,SW_SHOWNORMAL,edi,edi,edi,edi,ebx,edi
        invoke  UpdateWindow,eax
                                                        ;message loop
        mov     esi,offset msg                          ;ESI = msg structure address
        jmp short mLoop1
mLoop0: invoke  TranslateMessage,esi
        invoke  DispatchMessage,esi
mLoop1: invoke  GetMessage,esi,edi,edi,edi
        inc     eax                                     ;exit only
        shr     eax,1                                   ;if 0 or -1
        jnz     mLoop0                                  ;otherwise, we loop
        mov     eax,[esi].MSG.wParam
        ret
main   ENDP

end start
My Code Site
https://github.com/BrianKnoblauch

six_L

.data
        dwYpos dd 100
        dwXpos dd 100


.elseif uMsg == WM_KEYDOWN
.if     wParam==VK_ESCAPE
invoke  PostMessage,hWnd,WM_SYSCOMMAND,SC_CLOSE,NULL    ; Close full screen window
.elseif wParam==VK_UP
;mov eax,dwYpos
;sub     eax,5     
;mov dwYpos,eax
dec dwYpos
.elseif wParam==VK_DOWN
;mov eax,dwYpos
;add     eax,5     
;mov dwYpos,eax
inc dwYpos
.elseif wParam==VK_RIGHT
;mov eax,dwXpos
;add     eax,5     
;mov dwXpos,eax
inc dwXpos
.elseif wParam==VK_LEFT
;mov eax,dwXpos
;sub     eax,5     
;mov dwXpos,eax
dec dwXpos
.endif   
;mov     eax, dwXpxos     
;mov     updateregion.left, eax
;mov     updateregion.right, eax
;mov     eax, dwYpos
;mov     updateregion.top, eax
;mov     updateregion.bottom, eax
;invoke  InvalidateRect,hWndMain,offset updateregion,FALSE
invoke  InvalidateRect,hWin,NULL,FALSE
invoke  UpdateWindow,hWin

.elseif uMsg==WM_PAINT

invoke  BeginPaint,hWin,addr ps
invoke  SetPixel,ps.hdc,dwXpos,dwYpos,0FFFF00h ;****************
invoke  EndPaint,hWin,addr ps

Say you, Say me, Say the codes together for ever.

dedndave

Six_L - what's the advantage of using WM_KEYDOWN over WM_CHAR ?