1- using System . Drawing ;
1+ using ScreenGrab . Extensions ;
2+ using System . Drawing ;
23using System . Windows ;
3- using ScreenGrab . Extensions ;
4+ using System . Windows . Threading ;
45using WpfScreenHelper ;
56
67namespace ScreenGrab ;
@@ -11,6 +12,8 @@ public abstract class ScreenGrabber
1112
1213 public static Action < Bitmap > ? OnCaptured { get ; set ; }
1314
15+ private static TaskCompletionSource < Bitmap ? > ? _captureTaskCompletionSource ;
16+
1417 public static void Capture ( bool isAuxiliary = false )
1518 {
1619 if ( IsCapturing ) return ;
@@ -47,4 +50,117 @@ public static void Capture(bool isAuxiliary = false)
4750 screenGrab . Activate ( ) ;
4851 }
4952 }
53+
54+ /// <summary>
55+ /// 同步方式捕获屏幕截图,类似 Window.ShowDialog() 的阻塞式调用
56+ /// </summary>
57+ /// <param name="isAuxiliary">是否显示辅助线</param>
58+ /// <returns>返回捕获的 Bitmap,如果用户取消则返回 null</returns>
59+ public static Bitmap ? CaptureDialog ( bool isAuxiliary = false )
60+ {
61+ if ( IsCapturing )
62+ return null ;
63+
64+ Bitmap ? result = null ;
65+ var frame = new DispatcherFrame ( ) ;
66+
67+ IsCapturing = true ;
68+
69+ var allScreens = Screen . AllScreens ;
70+ var allScreenGrab = Application . Current . Windows . OfType < ScreenGrabView > ( ) . ToList ( ) ;
71+ var numberOfScreenGrabWindowsToCreate = allScreens . Count ( ) - allScreenGrab . Count ;
72+
73+ for ( var i = 0 ; i < numberOfScreenGrabWindowsToCreate ; i ++ )
74+ {
75+ var view = new ScreenGrabView ( bitmap =>
76+ {
77+ // 截图成功时保存结果并退出消息循环
78+ result = bitmap ;
79+ frame . Continue = false ;
80+ } , isAuxiliary )
81+ {
82+ OnGrabClose = ( ) =>
83+ {
84+ IsCapturing = false ;
85+ // 关闭时退出消息循环
86+ frame . Continue = false ;
87+ }
88+ } ;
89+ allScreenGrab . Add ( view ) ;
90+ }
91+
92+ foreach ( var ( screen , screenGrab ) in allScreens . Zip ( allScreenGrab ,
93+ ( displayInfo , screenGrab ) => ( displayInfo , screenGrab ) ) )
94+ {
95+ screenGrab . WindowStartupLocation = WindowStartupLocation . Manual ;
96+ screenGrab . WindowState = WindowState . Normal ;
97+ var screenWithScaledBounds = screen . ScaledBounds ( ) ;
98+
99+ screenGrab . Width = screenWithScaledBounds . Width ;
100+ screenGrab . Height = screenWithScaledBounds . Height ;
101+ screenGrab . Left = screenWithScaledBounds . X ;
102+ screenGrab . Top = screenWithScaledBounds . Y ;
103+
104+ screenGrab . Show ( ) ;
105+ screenGrab . Activate ( ) ;
106+ }
107+
108+ // 阻塞等待用户完成截图或取消
109+ Dispatcher . PushFrame ( frame ) ;
110+
111+ return result ;
112+ }
113+
114+ /// <summary>
115+ /// 异步方式捕获屏幕截图,类似 Dialog 的使用方式
116+ /// </summary>
117+ /// <param name="isAuxiliary">是否显示辅助线</param>
118+ /// <returns>返回捕获的 Bitmap,如果用户取消则返回 null</returns>
119+ public static Task < Bitmap ? > CaptureAsync ( bool isAuxiliary = false )
120+ {
121+ if ( IsCapturing )
122+ return Task . FromResult < Bitmap ? > ( null ) ;
123+
124+ _captureTaskCompletionSource = new TaskCompletionSource < Bitmap ? > ( ) ;
125+
126+ IsCapturing = true ;
127+
128+ var allScreens = Screen . AllScreens ;
129+ var allScreenGrab = Application . Current . Windows . OfType < ScreenGrabView > ( ) . ToList ( ) ;
130+ var numberOfScreenGrabWindowsToCreate = allScreens . Count ( ) - allScreenGrab . Count ;
131+
132+ for ( var i = 0 ; i < numberOfScreenGrabWindowsToCreate ; i ++ )
133+ {
134+ var view = new ScreenGrabView ( bitmap =>
135+ {
136+ // 截图成功时完成任务
137+ _captureTaskCompletionSource ? . TrySetResult ( bitmap ) ;
138+ } , isAuxiliary )
139+ {
140+ OnGrabClose = ( ) =>
141+ {
142+ IsCapturing = false ;
143+ }
144+ } ;
145+ allScreenGrab . Add ( view ) ;
146+ }
147+
148+ foreach ( var ( screen , screenGrab ) in allScreens . Zip ( allScreenGrab ,
149+ ( displayInfo , screenGrab ) => ( displayInfo , screenGrab ) ) )
150+ {
151+ screenGrab . WindowStartupLocation = WindowStartupLocation . Manual ;
152+ screenGrab . WindowState = WindowState . Normal ;
153+ var screenWithScaledBounds = screen . ScaledBounds ( ) ;
154+
155+ screenGrab . Width = screenWithScaledBounds . Width ;
156+ screenGrab . Height = screenWithScaledBounds . Height ;
157+ screenGrab . Left = screenWithScaledBounds . X ;
158+ screenGrab . Top = screenWithScaledBounds . Y ;
159+
160+ screenGrab . Show ( ) ;
161+ screenGrab . Activate ( ) ;
162+ }
163+
164+ return _captureTaskCompletionSource . Task ;
165+ }
50166}
0 commit comments