使用WM_PAINT绘制无效矩形

时间:2011-09-23 14:00:03

标签: vb.net gdi

为了在ComboBox(或其他任何内容)上绘制文字,我会覆盖WndProc()并抓住0x000F消息 - WM_PAINT

代码如下:

Protected Overrides Sub WndProc(ByRef m As Message)
    MyBase.WndProc(m)

    If m.Msg = &HF Then
        TextRenderer.DrawText(CreateGraphics, "The text over my control.", Font, _
                              ClientRectangle, ForeColor)
    End If
End Sub

它工作得非常好,但是有一个问题:如果我在屏幕的一侧拖动父窗口(为了隐藏窗体的一部分),我的控件的可见部分将被无限重绘。这使得文本重新绘制!

我认为有一种方法只能绘制控件的无效(隐藏)部分。我该怎么办?

修改

以下是一张图片中的问题:http://i.stack.imgur.com/WqGfI.png(这是一个链接,因为我暂时无法发布图片。)

更新

我尝试使用BeginPaint API,但返回的PAINTSTRUCT结构中包含的RECT结构仅包含零。

If m.Msg = WM_PAINT Then
    Dim ps As PAINTSTRUCT = New PAINTSTRUCT
    BeginPaint(Handle, ps)
    Console.WriteLine(ps.rcPaint.right)

    'painting goes here

    EndPaint(Handle, ps)
End If

我可以做点什么吗?我不知道如何处理,以便只绘制无效区域。

2 个答案:

答案 0 :(得分:0)

一个好的经验法则是,永远不要使用Me.CreateGraphics。

尝试将代码更改为:

<DllImport("User32.dll")> _
Public Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
End Function

<DllImport("user32.dll")> _
Private Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Boolean
End Function

Protected Overrides Sub WndProc(ByRef m As Message)
  MyBase.WndProc(m)

  If m.Msg = &HF Then
    Dim dc As IntPtr = GetWindowDC(m.HWnd)
    Using g As Graphics = Graphics.FromHdc(dc)
      TextRenderer.DrawText(g, "The text over my control.", Font, _
                          ClientRectangle, ForeColor)
    End Using
    ReleaseDC(m.HWnd, dc)
  End If
End Sub

答案 1 :(得分:0)

如果没有实际更新,您可能会尝试绘画。 PAINTSTRUCT的一部分指示是否应该实际擦除窗口。

这是我过去使用的内容。 GetUpdateRect可让您轻松查看是否实际更新过任何内容以及获取更新后的区域,而无需致电BeginPaint。请记住,BeginPaint仅在您没有将消息传递给基类时。 (我在此片段中使用NativeWindow类进行子类化。)

Dim hasUpdates As Boolean
Dim updRect As RECT
Dim r As Rectangle

hasUpdates = GetUpdateRect(_parentControl.Handle, updRect, False)
With updRect
    r = New Rectangle(.Left, .Top, .Right - .Left, .Bottom - .Top)
End With

' Invalidate the control so that the whole thing will be redrawn since
' our custom painting routine could redraw the entire client area.
If hasUpdates Then _parentControl.Invalidate(r)

' Pass the message along to be handled by the default paint event.
MyBase.DefWndProc(m)

' Now draw extras over the existing control.
If hasUpdates Then Me.PaintExtras(r)

如果hasUpdates为False,那么你要做的就是退出例程。

就用于绘制的图形而言,我使用Graphics.FromHwnd(ctrl.Handle)

取得了成功