写在前面
在做录屏或截屏操作时,需要获取当前正在运行中的桌面程序句柄,在网上查找资源的的时候,发现了一个工具类还不错,这边做个验证记录。
参考代码
public class WindowApi{//寻找目标进程窗口 [DllImport("USER32.DLL")]public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);//设置进程窗口到最前 [DllImport("USER32.DLL")]public static extern bool SetForegroundWindow(IntPtr hWnd);#region GetWindowCapture的dll引用[DllImport("user32.dll")]private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rectangle rect);[DllImport("gdi32.dll")]private static extern IntPtr CreateCompatibleDC(IntPtr hdc // handle to DC);[DllImport("gdi32.dll")]private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, // handle to DCint nWidth, // width of bitmap, in pixelsint nHeight // height of bitmap, in pixels);[DllImport("gdi32.dll")]private static extern IntPtr SelectObject(IntPtr hdc, // handle to DCIntPtr hgdiobj // handle to object);[DllImport("gdi32.dll")]private static extern int DeleteDC(IntPtr hdc // handle to DC);[DllImport("user32.dll")]private static extern bool PrintWindow(IntPtr hwnd, // Window to copy,Handle to the window that will be copied.IntPtr hdcBlt, // HDC to print into,Handle to the device context.UInt32 nFlags // Optional flags,Specifies the drawing options. It can be one of the following values.);[DllImport("user32.dll")]private static extern IntPtr GetWindowDC(IntPtr hwnd);#endregion/// <summary>/// 根据句柄获取截图/// </summary>/// <param name="hWnd"></param>/// <returns></returns>public static Bitmap GetWindowCapture(IntPtr hWnd){IntPtr hscrdc = GetWindowDC(hWnd);Rectangle windowRect = new Rectangle();GetWindowRect(hWnd, ref windowRect);int width = Math.Abs(windowRect.X - windowRect.Width);int height = Math.Abs(windowRect.Y - windowRect.Height);IntPtr hbitmap = CreateCompatibleBitmap(hscrdc, width, height);IntPtr hmemdc = CreateCompatibleDC(hscrdc);SelectObject(hmemdc, hbitmap);PrintWindow(hWnd, hmemdc, 0);Bitmap bmp = Image.FromHbitmap(hbitmap);DeleteDC(hscrdc);//删除用过的对象DeleteDC(hmemdc);//删除用过的对象return bmp;}/// <summary>/// 根据句柄获取截图路径/// </summary>/// <param name="hWnd"></param>/// <returns></returns>public static string GetCapturePath(IntPtr hWnd){string path = string.Empty;string dicPath = AppDomain.CurrentDomain.BaseDirectory + "Intercept";if (!Directory.Exists(dicPath)){Directory.CreateDirectory(dicPath);}using (Bitmap bitmap = GetWindowCapture(hWnd)){path = dicPath + "\\" + Guid.NewGuid().ToString().Replace("-", "") + ".png";bitmap.Save(path);}return path;}private delegate bool WNDENUMPROC(IntPtr hWnd, int lParam);//用来遍历所有窗口 [DllImport("user32.dll")]private static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);//获取窗口Text [DllImport("user32.dll")]private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount);//获取窗口类名 [DllImport("user32.dll")]private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount);//自定义一个结构,用来保存句柄信息public struct WindowInfo{public IntPtr hWnd;public string szWindowName;public string szClassName;}public static WindowInfo[] GetAllDesktopWindows(){//用来保存窗口对象 列表List<WindowInfo> wndList = new List<WindowInfo>();//enum all desktop windows EnumWindows(delegate (IntPtr hWnd, int lParam){WindowInfo wnd = new WindowInfo();StringBuilder sb = new StringBuilder(256);//get hwnd wnd.hWnd = hWnd;//get window name GetWindowTextW(hWnd, sb, sb.Capacity);wnd.szWindowName = sb.ToString();//get window class GetClassNameW(hWnd, sb, sb.Capacity);wnd.szClassName = sb.ToString();//add it into list wndList.Add(wnd);return true;}, 0);return wndList.ToArray();}[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);/// <summary>/// 释放内存/// </summary>public async static Task ClearMemory(){//获得当前工作进程Process proc = Process.GetCurrentProcess();long usedMemory = proc.PrivateMemorySize64;if (usedMemory > 1024 * 1024 * 10){GC.Collect();GC.WaitForPendingFinalizers();if (Environment.OSVersion.Platform == PlatformID.Win32NT){SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);}await Task.Delay(10);}}}
调用结果
调用示意:
var programList = WindowApi.GetAllDesktopWindows().Where(x => !string.IsNullOrEmpty(x.szWindowName)).ToList();
listBoxWindows.DataSource = programList.Select(x => x.szWindowName).ToList();