Skip to content

Commit d4b5206

Browse files
committed
非可等待交换链的实现
1 parent 6dcb31e commit d4b5206

File tree

2 files changed

+77
-8
lines changed

2 files changed

+77
-8
lines changed

DirectX/D2D/NalaylikikiLijinewi/NativeMethods.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,16 @@ TranslateMessage
2222
DispatchMessage
2323
DefWindowProc
2424
GetClientRect
25-
WM
2625
WM_PAINT
2726
GetWindowLong
2827
SetWindowLong
2928
DwmIsCompositionEnabled
3029
UpdateLayeredWindow
3130
DwmExtendFrameIntoClientArea
3231
DCompositionCreateDevice
33-
NCCALCSIZE_PARAMS
32+
NCCALCSIZE_PARAMS
33+
EnableMouseInPointer
34+
WM_POINTERUPDATE
35+
GetPointerTouchInfo
36+
GetPointerDeviceRects
37+
ClientToScreen

DirectX/D2D/NalaylikikiLijinewi/Program.cs

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
11
// See https://aka.ms/new-console-template for more information
22

33
using NalaylikikiLijinewi.Diagnostics;
4+
45
using System;
56
using System.Collections.Generic;
67
using System.Drawing;
78
using System.Linq;
89
using System.Runtime.CompilerServices;
910
using System.Runtime.InteropServices;
1011
using System.Threading;
12+
13+
using Vortice.DCommon;
1114
using Vortice.Direct3D;
1215
using Vortice.Direct3D11;
16+
using Vortice.DirectComposition;
1317
using Vortice.DXGI;
1418
using Vortice.Mathematics;
19+
1520
using Windows.Win32;
1621
using Windows.Win32.Foundation;
1722
using Windows.Win32.Graphics.Gdi;
1823
using Windows.Win32.UI.Controls;
24+
using Windows.Win32.UI.Input.Pointer;
1925
using Windows.Win32.UI.WindowsAndMessaging;
20-
using Vortice.DCommon;
21-
using Vortice.DirectComposition;
26+
2227
using static Windows.Win32.PInvoke;
28+
2329
using AlphaMode = Vortice.DXGI.AlphaMode;
2430
using D2D = Vortice.Direct2D1;
2531

@@ -43,6 +49,10 @@ public DemoWindow()
4349
{
4450
var window = CreateWindow();
4551
HWND = window;
52+
53+
// 让鼠标也引发 WM_Pointer 事件
54+
EnableMouseInPointer(true);
55+
4656
ShowWindow(window, SHOW_WINDOW_CMD.SW_NORMAL);
4757

4858
var renderManager = new RenderManager(window);
@@ -123,15 +133,46 @@ private unsafe HWND CreateWindow()
123133
}
124134
}
125135

126-
private LRESULT WndProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam)
136+
private unsafe LRESULT WndProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam)
127137
{
128138
if ((WindowsMessage) message == WindowsMessage.WM_SIZE)
129139
{
130140
_renderManager?.ReSize();
131141
}
132142

143+
if (message == WM_POINTERUPDATE /*Pointer Update*/)
144+
{
145+
var pointerId = (uint) (ToInt32(wParam) & 0xFFFF);
146+
147+
global::Windows.Win32.Foundation.RECT pointerDeviceRect = default;
148+
global::Windows.Win32.Foundation.RECT displayRect = default;
149+
150+
GetPointerTouchInfo(pointerId, out POINTER_TOUCH_INFO pointerTouchInfo);
151+
152+
var pointerInfo = pointerTouchInfo.pointerInfo;
153+
154+
GetPointerDeviceRects(pointerInfo.sourceDevice, &pointerDeviceRect, &displayRect);
155+
156+
var x =
157+
pointerInfo.ptHimetricLocationRaw.X / (double) pointerDeviceRect.Width * displayRect.Width +
158+
displayRect.left;
159+
var y = pointerInfo.ptHimetricLocationRaw.Y / (double) pointerDeviceRect.Height * displayRect.Height +
160+
displayRect.top;
161+
162+
var screenTranslate = new Point(0, 0);
163+
ClientToScreen(HWND, ref screenTranslate);
164+
165+
x -= screenTranslate.X;
166+
y -= screenTranslate.Y;
167+
168+
_renderManager?.Move(x, y);
169+
}
170+
133171
return DefWindowProc(hwnd, message, wParam, lParam);
134172
}
173+
174+
private static int ToInt32(WPARAM wParam) => ToInt32((IntPtr) wParam.Value);
175+
private static int ToInt32(IntPtr ptr) => IntPtr.Size == 4 ? ptr.ToInt32() : (int) (ptr.ToInt64() & 0xffffffff);
135176
}
136177

137178
unsafe class RenderManager(HWND hwnd) : IDisposable
@@ -226,9 +267,16 @@ private void RenderCore()
226267

227268
renderTarget.BeginDraw();
228269

229-
var color = new Color4(Random.Shared.NextSingle(), Random.Shared.NextSingle(),
230-
Random.Shared.NextSingle(), 0.1f);
231-
renderTarget.Clear(color);
270+
//var color = new Color4(Random.Shared.NextSingle(), Random.Shared.NextSingle(),
271+
// Random.Shared.NextSingle(), 0.1f);
272+
//renderTarget.Clear(color);
273+
renderTarget.Clear(Colors.Transparent);
274+
275+
using var brush = renderTarget.CreateSolidColorBrush(Colors.Yellow);
276+
var position = _position;
277+
278+
var rectangleSize = 50;
279+
renderTarget.FillRectangle(new Rect((float) position.X, (float) position.Y, rectangleSize, rectangleSize), brush);
232280

233281
renderTarget.EndDraw();
234282
}
@@ -434,6 +482,23 @@ public void Dispose()
434482
}
435483

436484
private bool _isDisposed;
485+
486+
public void Move(double x, double y)
487+
{
488+
_position = new Position(x, y);
489+
}
490+
491+
private Position _position = new Position(0, 0);
492+
493+
/// <summary>
494+
/// 表示当前的位置
495+
/// </summary>
496+
/// <param name="X"></param>
497+
/// <param name="Y"></param>
498+
/// <remarks>
499+
/// 为什么需要选用 record 引用 class 类型,而不是 struct 结构体值类型?这是为了在渲染线程和 UI 线程之间共享这个位置数据。由于 record class 是引用类型,所以在两个线程之间共享时,不需要担心值类型的复制问题,完全原子化,不存在多线程安全问题
500+
/// </remarks>
501+
record Position(double X, double Y);
437502
}
438503

439504
readonly record struct RenderInfo(ID3D11Texture2D D3D11Texture2D, D2D.ID2D1RenderTarget D2D1RenderTarget) : IDisposable

0 commit comments

Comments
 (0)