VB.NET - 使用Graphics.FromHwnd作为句柄的非客户端绘图

时间:2015-09-26 18:46:33

标签: vb.net paint

我正在尝试做一些非客户区绘画来获得像windowsform这样的MS Office。我有一两个其他类型的帖子,但这里是Graphics.FromHwnd传递IntPtr.Zero作为arg完成的帖子。我咨询了很多信息,我试过,只是根本无法让它工作。 Dwm函数,GetWindowDC和/或这些的组合。什么都行不通。除了我发布的这个例子。

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

        Select Case m.Msg
            Case WinAPI.Win32Messages.WM_ACTIVATEAPP
                Me.Invalidate()
        End Select
    End Sub

    Private Sub Form6_LocationChanged(sender As Object, e As EventArgs) Handles Me.LocationChanged
        Me.Invalidate()
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)

        Dim usedColor As Color = Color.Beige
        Me.BackColor = usedColor
        Dim usedBrush As Brush = New SolidBrush(usedColor)

        'Dim hDC As IntPtr = WinAPI.GetWindowDC(Me.Handle.ToInt64)

        Using g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
            'Using g As Graphics = Graphics.FromHdc(hDC)

            'Caption
            Dim rect As Rectangle = New Rectangle(Me.Left, Me.Top, Me.Width, SystemInformation.CaptionHeight + 2 * SystemInformation.FrameBorderSize.Height)
            g.FillRectangle(usedBrush, rect)

            'left border
            rect = New Rectangle(Me.Left, Me.Top + SystemInformation.CaptionHeight + 2 * SystemInformation.FrameBorderSize.Height, (Me.Width - Me.ClientSize.Width) / 2, Me.ClientSize.Height)
            g.FillRectangle(usedBrush, rect)

            'right border
            rect = New Rectangle(Me.Right - 2 * SystemInformation.FrameBorderSize.Width, Me.Top + SystemInformation.CaptionHeight + 2 * SystemInformation.FrameBorderSize.Height, (Me.Width - Me.ClientSize.Width) / 2, Me.ClientSize.Height)
            g.FillRectangle(usedBrush, rect)

            'bottom border
            'If on maximize this border isn't drawn, by default the windowsize "drawing" is correct
            If Me.WindowState <> FormWindowState.Maximized Then
                rect = New Rectangle(Me.Left, Me.Bottom - 2 * SystemInformation.FrameBorderSize.Width, Me.Width, 2 * SystemInformation.FrameBorderSize.Height)
                g.FillRectangle(usedBrush, rect)
            End If

        End Using

        'WinAPI.ReleaseDC(Me.Handle.ToInt64, hDC)
    End Sub

    Private Sub Form6_Resize(sender As Object, e As EventArgs) Handles Me.Resize
        Me.Invalidate()
    End Sub

    Private Sub Form6_SizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
        Me.Invalidate()
    End Sub
End Class

要生成图形,我将IntPtr.Zero传递给孔屏幕。 我尝试了GetWindowDC API(在代码中注释),没有任何反应。句柄以Me.HandleMe.Handle.ToInt32.ToInt64传递,但没有结果 被调用的无效是试图在每种可能的情况下绘制。

带给我的问题:

  1. 表格没有启动画(无法弄清楚);
  2. 调整大小闪烁(可能是因为句柄是整个屏幕,甚至是双缓冲);
  3. 在调整大小时,可以看到光标上的绘画(再次可能是因为图形的句柄不是表单的句柄);
  4. 鼠标悬停在控制按钮上(最小,最大和关闭),所有绘图都会消失;
  5. 虽然我可以发现问题,但我无法通过其他方式工作,例如着名的GetWindowDC,无论我尝试了多少不起作用的示例,甚至是DWM功能。

    为了让我自己的“办公室”像表格一样,我会帮助改进这些代码或其他一些想法,这是受欢迎的。

    [编辑]

    上述代码的另一种风格。此代码在form_load事件中尝试过,但没有任何反应。

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    
        MyBase.OnPaint(e)
    
    
        If Not DwmAPI.DwmIsCompositionEnabled(True) Then
            Dim myHandle As IntPtr = WinAPI.FindWindow(vbNullString, Me.Text)
    
            Dim hDC As IntPtr = WinAPI.GetWindowDC(myHandle)
    
            Dim rect As WinAPI.RECT
    
            With rect
                .Left = 0
                .Right = Me.Width
                .Top = 0
                .Bottom = 30
            End With
    
            Using g As Graphics = Graphics.FromHdc(hDC)
                g.DrawString("TESTER", New Font(Me.Font.Name, 50), Brushes.Red, New Point(0, 0))
            End Using
    
            WinAPI.ReleaseDC(myHandle, hDC)
        End If
    End Sub
    

    结果如下: http://postimg.org/image/yyg07zf87/

    很明显,如果图形绘制在标题栏上而不是在图标下,我想要有任何东西,尽管可以看出绘图的坐标来自完整的表格区域而不是客户区域。如果我对表单进行双重缓冲,则不会绘制任何内容。有什么想法吗?

    感谢您的耐心等待。最好的问候。

0 个答案:

没有答案