1

我是 Windows 编程的新手,几个月前开始研究文字游戏。我决定重写我的代码的 WM_PAINT 部分,我通常会不断地重绘整个客户区,但我想我会尝试重绘特定区域来减少闪烁。我注意到在我的代码的一个特定部分,InvalidateRect/UpdateWindow 似乎不想工作,但如果我用 RedrawWindow 替换这两个函数,它会完美显示。是否应该存在 InvalidateRect/UpdateWindow 无法工作但 RedrawWindow 可以正常工作的情况?

将我的代码中的所有 InvalidateRect/UpdateWindow 调用替换为 RedrawWindow 会有什么缺点吗?

感谢您的信息!

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

1 回答 1

0

假设您将0其用作(如您所做的那样)的最后一个参数RedrawWindow(),确实存在一个重要区别:

  • UpdateWindow()WM_PAINT在函数返回之前立即发送。
  • RedrawWindow()(除非使用标志RDW_UPDATENOW)只是放置WM_PAINT到消息队列中,因此绘画实际上会在以后发生。

如果您使矩形无效,但随后更改窗口状态,这可能会有所不同。在情况 (1) 中,控件是使用“旧”数据绘制的,但 (2)“有效”。

如果您的问题是由这种差异引起的,您可以尝试InvalidateRect()仅使用 (不要调用UpdateWindow(), 也不RedrawWindow()。当队列中没有其他事件时,矩形失效将导致 thenWM_PAINT将出现。(最初UpdateWindow()阻止了这种情况,因为立即WM_PAINT验证窗口作为绘画的副作用)。

于 2012-06-26T08:24:00.567 回答