1
votes

I'm new to windows programming and started working on a text game a few months ago. I decided to rewrite the WM_PAINT section of my code, I normally had the entire client area continually redrawn but thought I'd try redrawing specific regions instead to reduce flicker. I noticed in one specific section of my code, InvalidateRect/UpdateWindow doesn't seem to want to work, but if I replace the 2 functions with RedrawWindow, it displays perfectly. Should there be an instance where InvalidateRect/UpdateWindow fails to work but RedrawWindow works fine in it's place?

Would there be any drawbacks to just replace all InvalidateRect/UpdateWindow calls in my code with RedrawWindow?

Thanks for an info!

.if uMsg==WM_PAINT
    invoke BeginPaint,hWnd,ADDR ps
    mov hdc,eax

  .if (PAINT_DMGMSG>0)    ;contains ->to a char's DMGMSG     
    invoke CreateFont,16,12,0,0,400,0,0,0,OEM_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,NULL   
    invoke SelectObject,hdc,eax
    mov hfont,eax
    invoke SetTextColor,hdc,COLOR_SNOWWHITE

    mov esi,TS_MSG2
    mov edi,TS_MSG1
    mov ecx,len(TS_MSG2)
    rep movsb
    mov BYTE ptr [edi],0
    mov esi,TS_MSG3
    mov edi,TS_MSG2
    mov ecx,len(TS_MSG3)
    rep movsb
    mov BYTE ptr [edi],0
    mov esi,PAINT_DMGMSG
    mov edi,TS_MSG3
    mov ecx,len(esi)
    rep movsb
    mov BYTE ptr [edi],0

    invoke TextOut,hdc,0,500,TS_MSG1,len(TS_MSG1)
    invoke TextOut,hdc,0,518,TS_MSG2,len(TS_MSG2)
    invoke TextOut,hdc,0,536,TS_MSG3,len(TS_MSG3)
    mov PAINT_DMGMSG,0
  .endif

    invoke EndPaint,hWnd,ADDR ps

.elseif uMsg==WM_CHAR           ;used to handle keyboard input
  push wParam 
  pop  char

            .if(SDWORD ptr [ebx+OFFSET_ALLEGIANCE]<0)&&(DWORD ptr [ebx+OFFSET_STATUS]!=STAT_DEAD)
                invoke Combat,[esi+12],ebx
                mov ebx,[edi+4]
                mov eax,[human.color]
                mov [ebx+OFFSET_CHARCOLOR],eax

                mov ebx,pChar
                mov ebx,[ebx+OFFSET_MOBMEM]
                .if (DWORD ptr [ebx+OFFSET_MOBMEM_DMGMSG]>0)
                    mov ebx,[ebx+OFFSET_MOBMEM_DMGMSG]
                    mov XYrc.left,0
                    mov XYrc.top,500
                    push wWin
                    pop XYrc.right
                    mov XYrc.bottom,560       ;+font height

                    mov PAINT_DMGMSG,ebx
;                   invoke InvalidateRect,hWnd,ADDR XYrc,TRUE
;                   invoke UpdateWindow,hWnd
                    invoke RedrawWindow,hWnd,ADDR XYrc,NULL,NULL    ;<- WORKS FINE!  
                .endif                              
            .endif
1

1 Answers

0
votes

Assuming you use 0 as the last argument for the RedrawWindow() (as you do), there indeed is one important difference:

  • UpdateWindow() sends WM_PAINT immediately, before the function returns.
  • RedrawWindow() (unless flag RDW_UPDATENOW is used) just places WM_PAINT into the message queue so the painting actually happens later.

This can make difference, if you invalidate the rectangle, but change the window state then after. In case (1), the control is painted using the "old" data, but (2) "works".

If your issue is caused by this difference, you may try to use InvalidateRect() only (do not call UpdateWindow(), nor RedrawWindow(). The rect invalidation will cause then WM_PAINT will come when the queue has no other event in it. (Originally UpdateWindow() prevented that as the immediate WM_PAINT validates the window as a side effect of the painting).