之前有个程序要实现窗口最小化截图一直没实现,今天在网上看了一个文章说是实现是,下载了程序测试了一下,还真的可以,不过有时候是黑屏,原因后面再说。看了源码分析实现原理:
首先,获取窗口风格,然后设置成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( false , false ); } /// <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
本帖有隐藏附件,请您回复后查看。
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (29)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 蒋林斌(Ben Jiang) 2022-10-19引用 16楼77777777777777
- 蒋林斌(Ben Jiang) 2022-10-19引用 17楼
11111111111111111111111111
-
-
-
-
-
-
- /llxIaO/ll欣 2023-3-14引用 24楼
这是一个好方法
-
-
-
-
-
-
站点信息
- 文章2302
- 用户1336
- 访客10981245
每日一句
Success is not in never falling, but in rising every time we fall.
成功不是从不跌倒,而是每次跌倒后都能重新站起来。
成功不是从不跌倒,而是每次跌倒后都能重新站起来。
排名前5的开源在线机器学习
Android自定义蜂窝view
Android应用性能优化系列视图篇——隐藏在资源图片中的内存杀手
Java中的(耦合)控制反转
OpenGL读取帧缓存数据
首发:Thinkpad T550黑苹果10.13.4安装教程
反编译修改class文件变量
IntelliJ IDEA2018~2019.1激活码-注册码
p2p通信,打洞技术,穿越NAT的实现(附NAT环境检测工具)
【黑苹果安装】——如何在windows下操作EFI分区
Could not resolve io.flutter 解决方法
MPAndroidChart标记控件MarkerView的使用方法
imencode和imdecode使用
新会员