【问题标题】:InvalidateRect/UpdateWindow fails but RedrawWindow work fine, why?InvalidateRect/UpdateWindow 失败但 RedrawWindow 工作正常,为什么?
【发布时间】:2012-06-26 04:54:39
【问题描述】:

我是 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

【问题讨论】:

    标签: winapi assembly


    【解决方案1】:

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

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

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

    如果您的问题是由这种差异引起的,您可以尝试只使用InvalidateRect()(不要调用UpdateWindow(),也不要调用RedrawWindow()。rect 无效将导致然后WM_PAINT 将在队列没有时出现其他事件。(最初UpdateWindow() 阻止了这种情况,因为直接WM_PAINT 将窗口验证为绘画的副作用)。

    【讨论】:

      猜你喜欢
      • 2011-11-13
      • 2011-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-15
      相关资源
      最近更新 更多