之前有个程序要实现窗口最小化截图一直没实现,今天在网上看了一个文章说是实现是,下载了程序测试了一下,还真的可以,不过有时候是黑屏,原因后面再说。看了源码分析实现原理:
首先,获取窗口风格,然后设置成WS_EX_LAYERED风格(WS_EX_LAYERED支持透明),然后就是设置成透明的属性SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);紧接着就是还原窗口:ShowWindow(hWnd, ShowWindowEnum.Restore);再发送界面重绘消息,再用printwindow打印或者bitblt拷贝hdc就完成了。确实有效,就是感觉效率低,来回切换。前面说的有时候黑屏应该就是程序还未刷新完就开始截图逻辑(可能是这个原因,具体暂时不详)。核心源码如下:
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();
}
}
}
本文链接:http://it72.com/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楼这是一个好方法
-
-
-
-
-
-
站点信息
- 文章2313
- 用户1336
- 访客11759686
每日一句
Happiness depends on your mindset.
幸福取决于你的心态。
幸福取决于你的心态。
新会员