11// See https://aka.ms/new-console-template for more information
22
33using NalaylikikiLijinewi . Diagnostics ;
4+
45using System ;
56using System . Collections . Generic ;
67using System . Drawing ;
78using System . Linq ;
89using System . Runtime . CompilerServices ;
910using System . Runtime . InteropServices ;
1011using System . Threading ;
12+
13+ using Vortice . DCommon ;
1114using Vortice . Direct3D ;
1215using Vortice . Direct3D11 ;
16+ using Vortice . DirectComposition ;
1317using Vortice . DXGI ;
1418using Vortice . Mathematics ;
19+
1520using Windows . Win32 ;
1621using Windows . Win32 . Foundation ;
1722using Windows . Win32 . Graphics . Gdi ;
1823using Windows . Win32 . UI . Controls ;
24+ using Windows . Win32 . UI . Input . Pointer ;
1925using Windows . Win32 . UI . WindowsAndMessaging ;
20- using Vortice . DCommon ;
21- using Vortice . DirectComposition ;
26+
2227using static Windows . Win32 . PInvoke ;
28+
2329using AlphaMode = Vortice . DXGI . AlphaMode ;
2430using 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
137178unsafe 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
439504readonly record struct RenderInfo ( ID3D11Texture2D D3D11Texture2D , D2D . ID2D1RenderTarget D2D1RenderTarget ) : IDisposable
0 commit comments