本帖最后由 VisualEleven 于 2015-01-29 13:37:07 编辑

解决方案 »

  1.   

    针对,
    “还有,我尝试在DefWindowProc中用BeginPaint返回的DC中画图,然后直接return,则没有显示,不清楚原因。为什么OnPaint中和DefWindowProc中同样的代码,表现不同?”发现重载WindowProc而不是DefWindowProc以后,用BeginPaint返回的DC是可以画出来的,而且它对InvalidateRect的响应也正确。其他部分不会重绘。
      

  2.   

    创建按钮后,子类化 按钮, 在 按钮 的 OnPaint 画。
      

  3.   

    楼主遇到疑问从来不看MSDN的吗?
    The BeginPaint function automatically sets the clipping region of the device context to exclude any area outside the update region. The update region is set by the InvalidateRect or InvalidateRgn function and by the system after sizing, moving, creating, scrolling, or any other operation that affects the client area. If the update region is ed for erasing, BeginPaint sends a WM_ERASEBKGND message to the window. An application should not call BeginPaint except in response to a WM_PAINT message. Each call to BeginPaint must have a corresponding call to the EndPaint function. If the caret is in the area to be painted, BeginPaint automatically hides the caret to prevent it from being erased. If the window's class has a background brush, BeginPaint uses that brush to erase the background of the update region before returning. 
      

  4.   

    The GetDC function retrieves a common, class, or private DC depending on the class style of the specified window. For class and private DCs, GetDC leaves the previously assigned attributes unchanged. However, for common DCs, GetDC assigns default attributes to the DC each time it is retrieved. For example, the default font is System, which is a bitmap font. Because of this, the handle to a common DC returned by GetDC does not tell you what font, color, or brush was used when the window was drawn. To determine the font, call GetTextFace.Note that the handle to the DC can only be used by a single thread at any one time.After painting with a common DC, the ReleaseDC function must be called to release the DC. Class and private DCs do not have to be released. ReleaseDC must be called from the same thread that called GetDC. The number of DCs is limited only by available memory. 
      

  5.   

    一个dc设置某些区域不刷新 必须调用相关的api 比如ExcludeClipRect
    而Beginpaint获取的HDC 正是经过这种处理后的HDC
    你GetDC获取的 自然是没有处理过的
    另外在dialog函数中写这种代码 直接CPaintDC dc(this)就可以了 
    只有在WNDPROC里才需要 begin end
      

  6.   

    首先谢谢allenhiman的回答,但你贴的英文部分貌似没有回答我开始提的问题,特别是GetDC返回的DC和Update Region的关系,是完全不识别,还是不由InvalidateRect设置。可不可以这样理解,如果我想只用GetDC来画,则我必须自己触发重绘流程(而不是使用InvalidateRect),而且在触发之前,需要显式设置Update Region(用你说的ExcludeClipRect)。为什么GetDC不能识别InvalidateRect设置的Update Region,而可以识别到用ExcludeClipRect显式设置的Update Region呢?还有不理解为什么DefWindowProc不能使用BeginPaint返回的DC画出东西,而WindowProc可以。
      

  7.   

    GetDC  是窗口有效后的 DC , 
    如果 窗口 有 无效区, 必须 使用 paintDC。你 可以 叫 窗口 有效, ValidateRect (这个函数不常用,Beginpaint  后 窗口 就有效了 )
      

  8.   

    我想现在清楚了,总结一下。
    BeginPaint, EndPaint, WM_PAINT, OnPaint, CPaintDC, Invalidate, InvalidateRect和无效区域,是相关的。
    GetDC, ReleaseDC和上面的所有都完全没关系。可以直接在通过GetDC获得的DC进行绘图,但有个小难点在于需要自己维护背景,如果后画的东西没有完全覆盖之前画的部分,则未覆盖的部分会露出来,所以用这种方式绘图,需要在程序中调用所有要更新的区域的绘图操作,可能是多层的背景前景绘图。另外,关于闪烁,只要在一块区域中绘制多次,就会有闪烁,
    如果用WM_PAINT的响应绘制,则如果能够绘制全部更新区域,且不透明,则可以重载WM_ERASEBKGROUND,然后return true;来禁用系统画背景色,或者在Invalidate/InvalidateRect中第二个参数用false也是一样的。
    如果用GetDC来绘制,也是需要能够绘制全部更新区域,且不透明。无论哪种,只要保证在一块区域中只绘制一次就没问题。