C#实现后台最小化截图

Home / Article MrLee 2019-2-19 15224

之前有个程序要实现窗口最小化截图一直没实现,今天在网上看了一个文章说是实现是,下载了程序测试了一下,还真的可以,不过有时候是黑屏,原因后面再说。看了源码分析实现原理:

首先,获取窗口风格,然后设置成WS_EX_LAYERED风格(WS_EX_LAYERED支持透明),然后就是设置成透明的属性SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);紧接着就是还原窗口:ShowWindow(hWnd, ShowWindowEnum.Restore);再发送界面重绘消息,再用printwindow打印或者bitblt拷贝hdc就完成了。确实有效,就是感觉效率低,来回切换。前面说的有时候黑屏应该就是程序还未刷新完就开始截图逻辑(可能是这个原因,具体暂时不详)。核心源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
namespace MinimizeCapture
{
    class WindowSnap
    {
        #region Win32
        private const string PROGRAMMANAGER = "Program Manager";
        private const string RUNDLL = "RunDLL";
        private const uint WM_PAINT = 0x000F;
        private const int GWL_EXSTYLE = -20;
        private const int WS_EX_LAYERED = 0x80000;
        private const int LWA_ALPHA = 0x2;
        private enum ShowWindowEnum { Hide = 0, ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3, Maximize = 3, ShowNormalNoActivate = 4, Show = 5, Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8, Restore = 9, ShowDefault = 10, ForceMinimized = 11 };
        private struct RECT
        {
            int left;
            int top;
            int right;
            int bottom;
            public int Left
            {
                get return this.left; }
            }
            public int Top
            {
                get return this.top; }
            }
            public int Width
            {
                get return right - left; }
            }
            public int Height
            {
                get return bottom - top; }
            }
            public static implicit operator Rectangle(RECT rect)
            {
                return new Rectangle(rect.left, rect.top, rect.Width, rect.Height);
            }
        }
        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags);
        [DllImport("user32.dll")]
        private static extern uint SendMessage(IntPtr hWnd, uint msg, uint wParam, uint lParam);
        [DllImport("user32")]
        private static extern int GetWindowRect(IntPtr hWnd, ref RECT rect);
        [DllImport("user32")]
        private static extern int PrintWindow(IntPtr hWnd, IntPtr dc, uint flags);
        [DllImport("user32")]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount);
        [DllImport("user32")]
        private static extern int GetWindowTextLength(IntPtr hWnd);
        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsWindowVisible(IntPtr hWnd);
        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsIconic(IntPtr hWnd);
        private delegate bool EnumWindowsCallbackHandler(IntPtr hWnd, IntPtr lParam);
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool EnumWindows(EnumWindowsCallbackHandler lpEnumFunc, IntPtr lParam);
        [DllImport("user32")]
        private static extern int GetWindowLong(IntPtr hWnd, int index);
        [DllImport("user32")]
        private static extern int SetWindowLong(IntPtr hWnd, int index, int dwNewLong);
        [DllImport("user32")]
        private static extern int SetLayeredWindowAttributes(IntPtr hWnd, byte crey, byte alpha, int flags);
        #region Update for 4th October 2007
        [DllImport("user32")]
        private static extern int GetClassName(IntPtr hWnd, StringBuilder name, int maxCount);
        [DllImport("user32")]
        private static extern IntPtr GetParent(IntPtr hWnd);
        [DllImport("user32")]
        private static extern IntPtr SetParent(IntPtr child, IntPtr newParent);
        [DllImport("user32.dll")]
        private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool reDraw);
        [DllImport("user32.dll")]
        private static extern bool GetWindowInfo(IntPtr hwnd, ref WINDOWINFO pwi);
        [StructLayout(LayoutKind.Sequential)]
        private struct WINDOWINFO
        {
            public uint cbSize;
            public RECT rcWindow;
            public RECT rcClient;
            public WindowStyles dwStyle;
            public ExtendedWindowStyles dwExStyle;
            public uint dwWindowStatus;
            public uint cxWindowBorders;
            public uint cyWindowBorders;
            public ushort atomWindowType;
            public ushort wCreatorVersion;
            public static uint GetSize()
            {
                return (uint)Marshal.SizeOf(typeof(WINDOWINFO));
            }
        }
        [Flags]
        private enum WindowStyles : uint
        {
            WS_OVERLAPPED = 0x00000000,
            WS_POPUP = 0x80000000,
            WS_CHILD = 0x40000000,
            WS_MINIMIZE = 0x20000000,
            WS_VISIBLE = 0x10000000,
            WS_DISABLED = 0x08000000,
            WS_CLIPSIBLINGS = 0x04000000,
            WS_CLIPCHILDREN = 0x02000000,
            WS_MAXIMIZE = 0x01000000,
            WS_BORDER = 0x00800000,
            WS_DLGFRAME = 0x00400000,
            WS_VSCROLL = 0x00200000,
            WS_HSCROLL = 0x00100000,
            WS_SYSMENU = 0x00080000,
            WS_THICKFRAME = 0x00040000,
            WS_GROUP = 0x00020000,
            WS_TABSTOP = 0x00010000,
            WS_MINIMIZEBOX = 0x00020000,
            WS_MAXIMIZEBOX = 0x00010000,
            WS_CAPTION = WS_BORDER | WS_DLGFRAME,
            WS_TILED = WS_OVERLAPPED,
            WS_ICONIC = WS_MINIMIZE,
            WS_SIZEBOX = WS_THICKFRAME,
            WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW,
            WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
            WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
            WS_CHILDWINDOW = WS_CHILD,
        }
        #endregion
        #region Update for 10October 2007
        [Flags]
        private enum ExtendedWindowStyles : uint
        {
            WS_EX_DLGMODALFRAME = 0x00000001,
            WS_EX_NOPARENTNOTIFY = 0x00000004,
            WS_EX_TOPMOST = 0x00000008,
            WS_EX_ACCEPTFILES = 0x00000010,
            WS_EX_TRANSPARENT = 0x00000020,
            WS_EX_MDICHILD = 0x00000040,
            WS_EX_TOOLWINDOW = 0x00000080,
            WS_EX_WINDOWEDGE = 0x00000100,
            WS_EX_CLIENTEDGE = 0x00000200,
            WS_EX_CONTEXTHELP = 0x00000400,
            WS_EX_RIGHT = 0x00001000,
            WS_EX_LEFT = 0x00000000,
            WS_EX_RTLREADING = 0x00002000,
            WS_EX_LTRREADING = 0x00000000,
            WS_EX_LEFTSCROLLBAR = 0x00004000,
            WS_EX_RIGHTSCROLLBAR = 0x00000000,
            WS_EX_CONTROLPARENT = 0x00010000,
            WS_EX_STATICEDGE = 0x00020000,
            WS_EX_APPWINDOW = 0x00040000,
            WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE),
            WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST)
        }
        #endregion
        #endregion
        #region Statics
        #region Update for 10 Ocrober 2007
        private static bool forceMDI = true;
        /// <summary>
        /// if is true ,will force the mdi child to be captured completely ,maybe incompatible with some programs
        /// </summary>
        public static bool ForceMDICapturing
        {
            get return forceMDI; }
            set { forceMDI = value; }
        }
        #endregion
        [ThreadStatic]
        private static bool countMinimizedWindows;
        [ThreadStatic]
        private static bool useSpecialCapturing;
        [ThreadStatic]
        private static WindowSnapCollection windowSnaps;
        [ThreadStatic]
        private static int winLong;
        [ThreadStatic]
        private static bool minAnimateChanged = false;
        private static bool EnumWindowsCallback(IntPtr hWnd, IntPtr lParam)
        {
            bool specialCapturing = false;
            if (hWnd == IntPtr.Zero) return false;
            if (!IsWindowVisible(hWnd)) return true;
            if (!countMinimizedWindows)
            {
                if (IsIconic(hWnd)) return true;
            }
            else if (IsIconic(hWnd) && useSpecialCapturing) specialCapturing = true;
            if (GetWindowText(hWnd) == PROGRAMMANAGER) return true;
            windowSnaps.Add(new WindowSnap(hWnd, specialCapturing));
            return true;
        }
        /// <summary>
        /// Get the collection of WindowSnap instances fro all available windows
        /// </summary>
        /// <param name="minimized">Capture a window even it's Minimized</param>
        /// <param name="specialCapturring">use special capturing method to capture minmized windows</param>
        /// <returns>return collections of WindowSnap instances</returns>
        public static WindowSnapCollection GetAllWindows(bool minimized, bool specialCapturring)
        {
            windowSnaps = new WindowSnapCollection();
            countMinimizedWindows = minimized;//set minimized flag capture
            useSpecialCapturing = specialCapturring;//set specialcapturing flag
            EnumWindowsCallbackHandler callback = new EnumWindowsCallbackHandler(EnumWindowsCallback);
            EnumWindows(callback, IntPtr.Zero);
            return new WindowSnapCollection(windowSnaps.ToArray(), true);
        }
        /// <summary>
        /// Get the collection of WindowSnap instances fro all available windows
        /// </summary>
        /// <returns>return collections of WindowSnap instances</returns>
        public static WindowSnapCollection GetAllWindows()
        {
            return GetAllWindows(falsefalse);
        }
        /// <summary>
        /// Take a Snap from the specific Window
        /// </summary>
        /// <param name="hWnd">Handle of the Window</param>
        /// <param name="useSpecialCapturing">if you need to capture from the minimized windows set it true,otherwise false</param>
        /// <returns></returns>
        public static WindowSnap GetWindowSnap(IntPtr hWnd, bool useSpecialCapturing)
        {
            if (!useSpecialCapturing)
                return new WindowSnap(hWnd, false);
            return new WindowSnap(hWnd, NeedSpecialCapturing(hWnd));
        }
        private static bool NeedSpecialCapturing(IntPtr hWnd)
        {
            if (IsIconic(hWnd)) return true;
            return false;
        }
        private static Bitmap GetWindowImage(IntPtr hWnd, Size size)
        {
            try
            {
                if (size.IsEmpty || size.Height < 0 || size.Width < 0) return null;
                Bitmap bmp = new Bitmap(size.Width, size.Height);
                Graphics g = Graphics.FromImage(bmp);
                IntPtr dc = g.GetHdc();
                PrintWindow(hWnd, dc, 0);
                g.ReleaseHdc();
                g.Dispose();
                return bmp;
            }
            catch return null; }
        }
        private static string GetWindowText(IntPtr hWnd)
        {
            int length = GetWindowTextLength(hWnd) + 1;
            StringBuilder name = new StringBuilder(length);
            GetWindowText(hWnd, name, length);
            return name.ToString();
        }
        private static Rectangle GetWindowPlacement(IntPtr hWnd)
        {
            RECT rect = new RECT();
            GetWindowRect(hWnd, ref rect);
            return rect;
        }
        private static void EnterSpecialCapturing(IntPtr hWnd)
        {
            if (XPAppearance.MinAnimate)
            {
                XPAppearance.MinAnimate = false;
                minAnimateChanged = true;
            }
            winLong = GetWindowLong(hWnd, GWL_EXSTYLE);
            SetWindowLong(hWnd, GWL_EXSTYLE, winLong | WS_EX_LAYERED);
            SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
            ShowWindow(hWnd, ShowWindowEnum.Restore);
            SendMessage(hWnd, WM_PAINT, 0, 0);
        }
        private static void ExitSpecialCapturing(IntPtr hWnd)
        {
            ShowWindow(hWnd, ShowWindowEnum.Minimize);
            SetWindowLong(hWnd, GWL_EXSTYLE, winLong);
            if (minAnimateChanged)
            {
                XPAppearance.MinAnimate = true;
                minAnimateChanged = false;
            }
        }
        #endregion
        private Bitmap image;
        private Size size;
        private Point location;
        private string text;
        private IntPtr hWnd;
        private bool isIconic;
        /// <summary>
        /// Get the Captured Image of the Window
        /// </summary>
        public Bitmap Image
        {
            get
            {
                if (this.image != null)
                    return this.image;
                return null;
            }
        }
        /// <summary>
        /// Get Size of Snapped Window
        /// </summary>
        public Size Size
        {
            get return this.size; }
        }
        /// <summary>
        /// Get Location of Snapped Window
        /// </summary>
        public Point Location
        {
            get return this.location; }
        }
        /// <summary>
        /// Get Title of Snapped Window
        /// </summary>
        public string Text
        {
            get return this.text; }
        }
        /// <summary>
        /// Get Handle of Snapped Window
        /// </summary>
        public IntPtr Handle
        {
            get return this.hWnd; }
        }
        /// <summary>
        /// if the state of the window is minimized return true otherwise returns false
        /// </summary>
        public bool IsMinimized
        {
            get return this.isIconic; }
        }
        private WindowSnap(IntPtr hWnd, bool specialCapturing)
        {
            this.isIconic = IsIconic(hWnd);
            this.hWnd = hWnd;
            if (specialCapturing)
                EnterSpecialCapturing(hWnd);
            #region Child Support (Enter)
            WINDOWINFO wInfo = new WINDOWINFO();
            wInfo.cbSize = WINDOWINFO.GetSize();
            GetWindowInfo(hWnd, ref wInfo);
            bool isChild = false;
            IntPtr parent = GetParent(hWnd);
            Rectangle pos = new Rectangle();
            Rectangle parentPos = new Rectangle();
            if (forceMDI && parent != IntPtr.Zero && (wInfo.dwExStyle & ExtendedWindowStyles.WS_EX_MDICHILD) == ExtendedWindowStyles.WS_EX_MDICHILD
                //&& (
                //(wInfo.dwStyle & WindowStyles.WS_CHILDWINDOW) == WindowStyles.WS_CHILDWINDOW||
                //(wInfo.dwStyle & WindowStyles.WS_CHILD) == WindowStyles.WS_CHILD)
                )//added 10 october 2007
                 
            {
                StringBuilder name = new StringBuilder();
                GetClassName(parent, name, RUNDLL.Length + 1);
                if (name.ToString() != RUNDLL)
                {
                    isChild = true;
                    pos = GetWindowPlacement(hWnd);
                    MoveWindow(hWnd, int.MaxValue, int.MaxValue, pos.Width, pos.Height, true);
                    SetParent(hWnd, IntPtr.Zero);
                    parentPos = GetWindowPlacement(parent);
                }
            }
            #endregion
            Rectangle rect = GetWindowPlacement(hWnd);
            this.size = rect.Size;
            this.location = rect.Location;
            this.text = GetWindowText(hWnd);
            this.image = GetWindowImage(hWnd, this.size);
            #region Child Support (Exit)
            if (isChild)
            {
                SetParent(hWnd, parent);
                //int x = pos.X - parentPos.X;
                //int y = pos.Y - parentPos.Y;
                int x = wInfo.rcWindow.Left - parentPos.X;
                int y = wInfo.rcWindow.Top - parentPos.Y;
                if ((wInfo.dwStyle & WindowStyles.WS_THICKFRAME) == WindowStyles.WS_THICKFRAME)
                {
                    x -= SystemInformation.Border3DSize.Width;
                    y -= SystemInformation.Border3DSize.Height;
                }
                MoveWindow(hWnd, x, y, pos.Width, pos.Height, true);
            }
            #endregion
            if (specialCapturing)
                ExitSpecialCapturing(hWnd);
        }
        /// <summary>
        /// Gets the Name and Handle of the Snapped Window
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder str = new StringBuilder();
            str.AppendFormat("Window Text: {0}, Handle: {1}"this.text, this.hWnd.ToString());
            return str.ToString();
        }
    }
}

本文链接:https://it72.com:4443/12491.htm

本帖有隐藏附件,请您回复后查看。

推荐阅读
最新回复 (29)
返回