SpiedWindow.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. using System.Drawing;
  2. using System.Drawing.Imaging;
  3. using System.Globalization;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. namespace DummyCursor.Spy
  7. {
  8. public class SpiedWindow : EventArgs
  9. {
  10. public SpiedWindow(IntPtr handle)
  11. {
  12. Handle = handle;
  13. }
  14. public IntPtr Handle { get; }
  15. public Rectangle Area
  16. {
  17. get
  18. {
  19. RECT rect;
  20. GetWindowRect(Handle, out rect);
  21. return rect;
  22. }
  23. }
  24. public Rectangle ClientArea
  25. {
  26. get
  27. {
  28. RECT rectW;
  29. GetWindowRect(Handle, out rectW);
  30. RECT rectC;
  31. GetClientRect(Handle, out rectC);
  32. POINT pt = new Point(rectW.X, rectW.Y);
  33. ScreenToClient(Handle, ref pt);
  34. rectW.X -= pt.X;
  35. rectW.Y -= pt.Y;
  36. rectW.Width = rectC.Width;
  37. rectW.Height = rectC.Height;
  38. return rectW;
  39. }
  40. }
  41. public string Caption
  42. {
  43. get
  44. {
  45. var len = GetWindowTextLength(Handle);
  46. var str = new StringBuilder(len + 1);
  47. GetWindowText(Handle, str, len + 1);
  48. return str.ToString();
  49. }
  50. }
  51. public SpiedWindow GetParentWindow()
  52. {
  53. return new SpiedWindow(GetParent(Handle));
  54. }
  55. public void SeParentWindow(IntPtr parentHandle)
  56. {
  57. SetParent(Handle, parentHandle);
  58. }
  59. public IEnumerable<SpiedWindow> GetChildren()
  60. {
  61. var children = new List<SpiedWindow>();
  62. EnumChildWindows(Handle, (hWnd, lp) =>
  63. {
  64. children.Add(new SpiedWindow(hWnd));
  65. return true;
  66. }, IntPtr.Zero);
  67. return children;
  68. }
  69. public override string ToString()
  70. {
  71. return Caption;
  72. }
  73. public void PrintTo(Graphics graphics, Point itemLocation)
  74. {
  75. using var bmp = GetScreenShot();
  76. if (bmp != null) graphics.DrawImage(bmp, itemLocation);
  77. }
  78. private Bitmap GetScreenShot()
  79. {
  80. var sz = Area.Size;
  81. if (sz == Size.Empty) return null;
  82. var bmp = new Bitmap(sz.Width, sz.Height, PixelFormat.Format32bppArgb);
  83. using var g = Graphics.FromImage(bmp);
  84. var hdc = g.GetHdc();
  85. PrintWindow(Handle, hdc, PW_RENDERFULLCONTENT);
  86. g.ReleaseHdc(hdc);
  87. return bmp;
  88. }
  89. public static SpiedWindow FindByCaption(string caption)
  90. {
  91. var hWnd = WndFinder.FindWindowsWithText(caption).FirstOrDefault();
  92. if (hWnd == IntPtr.Zero) return null;
  93. return new SpiedWindow(hWnd);
  94. }
  95. #region Under the Hood
  96. [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
  97. static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
  98. [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
  99. static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
  100. [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
  101. private static extern IntPtr GetParent(IntPtr hWnd);
  102. [DllImport("user32.dll", SetLastError = true)]
  103. private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
  104. [DllImport("user32.dll")]
  105. [return: MarshalAs(UnmanagedType.Bool)]
  106. private static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
  107. [DllImport("user32.dll")]
  108. [return: MarshalAs(UnmanagedType.Bool)]
  109. private static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
  110. [DllImport("user32.dll")]
  111. [return: MarshalAs(UnmanagedType.Bool)]
  112. static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
  113. [DllImport("user32.dll")]
  114. [return: MarshalAs(UnmanagedType.Bool)]
  115. private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
  116. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  117. private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
  118. [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  119. private static extern int GetWindowTextLength(IntPtr hWnd);
  120. private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
  121. [StructLayout(LayoutKind.Sequential)]
  122. private struct RECT
  123. {
  124. public int Left, Top, Right, Bottom;
  125. public RECT(int left, int top, int right, int bottom)
  126. {
  127. Left = left;
  128. Top = top;
  129. Right = right;
  130. Bottom = bottom;
  131. }
  132. public RECT(Rectangle r)
  133. : this(r.Left, r.Top, r.Right, r.Bottom)
  134. {
  135. }
  136. public int X
  137. {
  138. get { return Left; }
  139. set
  140. {
  141. Right -= (Left - value);
  142. Left = value;
  143. }
  144. }
  145. public int Y
  146. {
  147. get { return Top; }
  148. set
  149. {
  150. Bottom -= (Top - value);
  151. Top = value;
  152. }
  153. }
  154. public int Height
  155. {
  156. get { return Bottom - Top; }
  157. set { Bottom = value + Top; }
  158. }
  159. public int Width
  160. {
  161. get { return Right - Left; }
  162. set { Right = value + Left; }
  163. }
  164. public Point Location
  165. {
  166. get { return new Point(Left, Top); }
  167. set
  168. {
  169. X = value.X;
  170. Y = value.Y;
  171. }
  172. }
  173. public Size Size
  174. {
  175. get { return new Size(Width, Height); }
  176. set
  177. {
  178. Width = value.Width;
  179. Height = value.Height;
  180. }
  181. }
  182. public static implicit operator Rectangle(RECT r)
  183. {
  184. return new Rectangle(r.Left, r.Top, r.Width, r.Height);
  185. }
  186. public static implicit operator RECT(Rectangle r)
  187. {
  188. return new RECT(r);
  189. }
  190. public static bool operator ==(RECT r1, RECT r2)
  191. {
  192. return r1.Equals(r2);
  193. }
  194. public static bool operator !=(RECT r1, RECT r2)
  195. {
  196. return !r1.Equals(r2);
  197. }
  198. public bool Equals(RECT r)
  199. {
  200. return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
  201. }
  202. public override bool Equals(object obj)
  203. {
  204. if (obj is RECT)
  205. return Equals((RECT)obj);
  206. if (obj is Rectangle)
  207. return Equals(new RECT((Rectangle)obj));
  208. return false;
  209. }
  210. public override int GetHashCode()
  211. {
  212. return ((Rectangle)this).GetHashCode();
  213. }
  214. public override string ToString()
  215. {
  216. return string.Format(CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top,
  217. Right, Bottom);
  218. }
  219. }
  220. [StructLayout(LayoutKind.Sequential)]
  221. public struct POINT
  222. {
  223. public int X;
  224. public int Y;
  225. public POINT(int x, int y)
  226. {
  227. this.X = x;
  228. this.Y = y;
  229. }
  230. public static implicit operator System.Drawing.Point(POINT p)
  231. {
  232. return new System.Drawing.Point(p.X, p.Y);
  233. }
  234. public static implicit operator POINT(System.Drawing.Point p)
  235. {
  236. return new POINT(p.X, p.Y);
  237. }
  238. public override string ToString()
  239. {
  240. return $"X: {X}, Y: {Y}";
  241. }
  242. }
  243. private static uint PW_RENDERFULLCONTENT = 2;
  244. [DllImport("user32.dll", SetLastError = true)]
  245. [return: MarshalAs(UnmanagedType.Bool)]
  246. private static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);
  247. [DllImport("gdi32.dll")]
  248. private static extern bool MoveToEx(IntPtr hdc, int X, int Y, IntPtr lpPoint);
  249. [DllImport("user32.dll", SetLastError = true)]
  250. private static extern IntPtr GetDC(IntPtr hWnd);
  251. [DllImport("user32.dll", SetLastError = true)]
  252. private static extern IntPtr GetWindowDC(IntPtr hWnd);
  253. [DllImport("user32.dll")]
  254. private static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
  255. [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)]
  256. [return: MarshalAs(UnmanagedType.Bool)]
  257. private static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
  258. public enum TernaryRasterOperations : uint
  259. {
  260. SRCCOPY = 0x00CC0020,
  261. SRCPAINT = 0x00EE0086,
  262. SRCAND = 0x008800C6,
  263. SRCINVERT = 0x00660046,
  264. SRCERASE = 0x00440328,
  265. NOTSRCCOPY = 0x00330008,
  266. NOTSRCERASE = 0x001100A6,
  267. MERGECOPY = 0x00C000CA,
  268. MERGEPAINT = 0x00BB0226,
  269. PATCOPY = 0x00F00021,
  270. PATPAINT = 0x00FB0A09,
  271. PATINVERT = 0x005A0049,
  272. DSTINVERT = 0x00550009,
  273. BLACKNESS = 0x00000042,
  274. WHITENESS = 0x00FF0062,
  275. CAPTUREBLT = 0x40000000 //only if WinVer >= 5.0.0 (see wingdi.h)
  276. }
  277. private const int WM_PRINT = 0x0317;
  278. [DllImport("user32.dll")]
  279. public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
  280. #endregion Under the Hood
  281. }
  282. }