Ответ 1
Большое спасибо @ γηράσκω δ 'αεί πολλά διδασκόμε предложения, которые я, наконец, получил, чтобы сделать это, используя SharpDx.
В приведенном ниже коде содержатся некоторые вызовы во внешнюю библиотеку, однако я думаю, что идея будет очень понятной.
Как сказал @ γηράσκω δ 'αεί πολλά διδασκόμε, чтобы использовать WindowRenderTarget
, мне нужно использовать его в своей собственной форме, и моя форма должна удовлетворять следующим условиям:
- Есть черный цвет фона.
- Будьте без полей.
- Быть самым верхним окном (очевидно).
- Рамка окна должна быть расширена в клиентскую область, вызвав DwmExtendFrameIntoClientArea.
Затем я могу вызвать метод WindowRenderTarget.Clear(Color.Transparent)
, чтобы сделать форму прозрачной. Обратите внимание, что метод 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