c# – 如何使用SharpDX绘制透明表面?

(这个问题是基于 this其他问题的进一步调查,但不一样的问题,这是关于绘画问题的非常具体的问题.)

我试图在目标窗口上画一个透明的表面,问题是我不知道如何画它透明,所以在我的表面是黑色的时候,我看不到正确的方法来清除黑色该表面的颜色在下面的代码中.

我会阅读关于像素格式和alphamodes,但是,似乎我不能使用AlphaMode.Straight,据说是允许透明度.

我知道一个免费的应用程序可以做到这一点,它的名字是TurboHUD(一个应用程序,在游戏客户端的窗口上绘制一个透明的表面来绘制对象,也就是HUD).说实话,也许可以荒谬的是:我想从两年多前开始这样做,我仍然不知道如何开始这样做,做透明度,我需要在透明的表面上绘制对象.

我做错了什么?这个示例代码是用VB.NET编写的,但我也接受C#中的解决方案.

Imports SharpDX
Imports SharpDX.Direct2D1
Imports SharpDX.Direct3D
Imports SharpDX.dxgi
Imports SharpDX.Mathematics.Interop
Imports SharpDX.Windows

Public notinheritable Class Form1 : Inherits Form

    Private factory As New Direct2D1.Factory(Direct2D1.FactoryType.SingleThreaded)
    Private render As Windowrendertarget
    Private renderProps As HwndrendertargetProperties
    Private renderThread As Thread = nothing

    Private Sub Form1_Load() Handles MyBase.Shown

        Dim hwnd As IntPtr = Process.GetProcessesByName("notepad").Single().MainWindowHandle

        Me.renderProps = New HwndrendertargetProperties()
        Me.renderProps.Hwnd = hwnd
        Me.renderProps.PixelSize = New Size2(1920,1080)
        Me.renderProps.PresentOptions = PresentOptions.None

        Me.render = New Windowrendertarget(Me.factory,New rendertargetProperties(New PixelFormat(Format.B8G8R8A8_Unorm,Direct2D1.AlphaMode.Premultiplied)),Me.renderProps)

        Me.renderThread = New Thread(New ParameterizedThreadStart(AddressOf Me.DoRender))
        Me.renderThread.Priority = ThreadPriority.normal
        Me.renderThread.IsBackground = True
        Me.renderThread.Start()

    End Sub

    Private Sub DoRender(ByVal sender As Object)

        While True
            Me.render.BeginDraw()
            ' Me.render.Clear(New RawColor4(0,0))
            Me.render.Clear(SharpDX.Color.Transparent)
            Me.render.Flush()
            Me.render.EndDraw()
        End While

    End Sub

End Class

上面的代码是VB.NET适应this问题的接受答案.

解决方法

非常感谢@γηράσκωδ’αείπολλάδιδασκόμε建议我终于用SharpDx来做这个.

下面的代码包含一些外部图书馆的调用,但是我认为这个想法将会很清楚.

as @γηράσκωδ’αείπολλάδιδασκόμε说,使用Windowrendertarget似乎我需要以我自己的形式使用它,我的表单必须满足这些条件:

>有黑色背景颜色.
>成为无边界的形式.
>成为最顶层的窗口(显而易见).
>窗口框必须通过调用DwmExtendFrameIntoClientArea功能扩展到客户端区域.

然后我可以调用Windowrendertarget.Clear(Color.Transparent)方法来使Form变得透明.请注意,除了上述条件之外,Clear()方法对于不同于我们自己的窗体的任何其他窗口都不起作用,这意味着如果我们尝试在目标窗口上直接绘制透明表面,而不是使用我们的窗体来实现会产生不透明的纯色表面(我真的不明白为什么不能)

所以完成上述所有基本步骤之后,现在只是一个抛光的事情,如目标窗口顶部的源窗口的重叠(产生HUD效果),处理目标窗口大小调整,以及你想要什么下面的代码只是说明性的,我现在不处理好这些东西.

这是代码

Imports D2D1 = SharpDX.Direct2D1
Imports D3D = SharpDX.Direct3D
Imports dxgi = SharpDX.dxgi

Imports dxcolor = SharpDX.Color
Imports DxPoint = SharpDX.Point
Imports DxRectangle = SharpDX.Rectangle
Imports DxSize = SharpDX.Size2

Imports Device = SharpDX.Direct3D11.Device
Imports MapFlags = SharpDX.Direct3D11.MapFlags

Imports Elektro.Imaging.Tools
Imports Elektro.Interop.Win32
Imports Elektro.Interop.Win32.Enums
Imports Elektro.Interop.Win32.Types

Public notinheritable Class Form1 : Inherits Form

    <DllImport("dwmapi.dll")>
    Private Shared Function DwmExtendFrameIntoClientArea(ByVal hwnd As IntPtr,ByRef margins As Margins) As Integer
    End Function

    Private factory As New D2D1.Factory(D2D1.FactoryType.SingleThreaded)
    Private render As D2D1.Windowrendertarget
    Private renderProps As D2D1.HwndrendertargetProperties
    Private renderThread As Thread = nothing

    Private srcHwnd As IntPtr
    Private dstHwnd As IntPtr

    Private Sub Form1_Load() Handles MyBase.Shown

        ' Window handles of source and target window.
        Me.srcHwnd = Me.Handle
        Me.dstHwnd = Process.GetProcessesByName("notepad").Single().MainWindowHandle

        ' Form settings.
        Me.BackColor = Color.Black
        Me.FormBorderStyle = FormBorderStyle.None
        Me.TopMost = True

        ' DWM stuff for later to be able make transparent the source window.
        Dim rc As NativeRectangle ' a win32 RECT
        NativeMethods.GetClientRect(srcHwnd,rc)
        Dim margins As Margins
        margins.TopHeight = rc.Width
        margins.BottomHeight = rc.Height
        DwmExtendFrameIntoClientArea(srcHwnd,margins)
        ' ------------------------------------------------

        Me.renderProps = New D2D1.HwndrendertargetProperties()
        Me.renderProps.Hwnd = srcHwnd
        Me.renderProps.PixelSize = New DxSize(rc.Width,rc.Height)
        Me.renderProps.PresentOptions = D2D1.PresentOptions.None

        Me.render = New D2D1.Windowrendertarget(Me.factory,New D2D1.rendertargetProperties(New D2D1.PixelFormat(dxgi.Format.B8G8R8A8_Unorm,D2D1.AlphaMode.Premultiplied)),Me.renderProps)

        Me.renderThread = New Thread(New ParameterizedThreadStart(AddressOf Me.DoRender))
        Me.renderThread.Priority = ThreadPriority.normal
        Me.renderThread.IsBackground = True
        Me.renderThread.Start()

    End Sub

    Private Sub DoRender(ByVal sender As Object)

        While True
            Me.OverlapToWindow(Me.srcHwnd,Me.dstHwnd)
            Me.render.BeginDraw()
            Me.render.Clear(dxcolor.Transparent)
            Me.render.Flush()
            Me.render.EndDraw()
        End While

    End Sub

    Private Sub OverlapToWindow(ByVal srcHwnd As IntPtr,ByVal dstHwnd As IntPtr)
        ' Gets the (non-client) Rectangle of the windows,taking into account a borderless window of Windows 10.
        Dim srcRect As Rectangle = ImageUtil.GetRealWindowRect(srcHwnd)
        Dim dstRect As Rectangle = ImageUtil.GetRealWindowRect(dstHwnd)

        NativeMethods.SetwindowPos(srcHwnd,dstHwnd,dstRect.X,dstRect.Y,dstRect.Top,dstRect.Left,SetwindowPosFlags.IgnoreZOrder Or SetwindowPosFlags.IgnoreResize)
    End Sub

End Class

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...