InvalidateRect / UpdateWindow失败但RedrawWindow工作正常,为什么?

时间:2012-06-26 04:54:39

标签: winapi assembly

我是Windows编程的新手,几个月前开始编写文本游戏。我决定重写代码的WM_PAINT部分,我通常会不断重绘整个客户区域,但我认为我会尝试重新绘制特定区域以减少闪烁。我注意到在我的代码的一个特定部分,InvalidateRect / UpdateWindow似乎不想工作,但如果我用RedrawWindow替换2个函数,它会完美显示。是否应该有一个InvalidateRect / UpdateWindow无法工作的实例但RedrawWindow在它的位置正常工作?

使用RedrawWindow替换我的代码中的所有InvalidateRect / UpdateWindow调用会有任何缺点吗?

感谢您提供信息!

.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 个答案:

答案 0 :(得分:0)

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

  • UpdateWindow()在函数返回之前立即发送WM_PAINT
  • RedrawWindow()(除非使用了标记RDW_UPDATENOW)只是将WM_PAINT放入消息队列中,以便绘画实际上稍后发生。

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

如果您的问题是由这种差异造成的,您可以尝试仅使用InvalidateRect()(不要拨打UpdateWindow(),也不要拨打RedrawWindow()。直接失效将导致{{1}当队列中没有其他事件时将会出现。(原来WM_PAINT阻止了,因为立即UpdateWindow()验证窗口是绘画的副作用。)