PageRenderTime 521ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Visual Studio 2013/Source/wpf/src/UIAutomation/Win32Providers/MS/Internal/AutomationProxies/Misc.cs

https://github.com/tforsberg/z
C# | 1298 lines | 888 code | 219 blank | 191 comment | 167 complexity | 069eff079837835ae7ff313a55fee2c4 MD5 | raw file
  1. //---------------------------------------------------------------------------
  2. //
  3. // <copyright file="Misc.cs" company="Microsoft">
  4. // Copyright (C) Microsoft Corporation. All rights reserved.
  5. // </copyright>
  6. //
  7. //
  8. // Description: Miscellaneous helper routines
  9. //
  10. // History:
  11. // 12/06/2004 : Created [....]
  12. //
  13. //---------------------------------------------------------------------------
  14. // PRESHARP: In order to avoid generating warnings about unkown message numbers and unknown pragmas.
  15. #pragma warning disable 1634, 1691
  16. using Microsoft.Win32.SafeHandles;
  17. using MS.Win32;
  18. using System;
  19. using System.Collections;
  20. using System.ComponentModel;
  21. using System.Runtime.CompilerServices;
  22. using System.Runtime.InteropServices;
  23. using System.Security.Permissions;
  24. using System.Text;
  25. using System.Windows.Automation;
  26. using System.Windows.Automation.Provider;
  27. using System.Windows;
  28. using System.Windows.Input;
  29. using System.Diagnostics;
  30. using NativeMethodsSetLastError = MS.Internal.UIAutomationClientSideProviders.NativeMethodsSetLastError;
  31. namespace MS.Internal.AutomationProxies
  32. {
  33. static class Misc
  34. {
  35. //------------------------------------------------------
  36. //
  37. // Internal Methods
  38. //
  39. //------------------------------------------------------
  40. #region Internal Methods
  41. //
  42. // HrGetWindowShortcut()
  43. //
  44. internal static string AccessKey(string s)
  45. {
  46. // Get the index of the shortcut
  47. int iPosShortCut = s.IndexOf('&');
  48. // Did we found an & or is it at the end of the string
  49. if (iPosShortCut < 0 || iPosShortCut + 1 >= s.Length)
  50. {
  51. return null;
  52. }
  53. // Build the result string
  54. return ST.Get(STID.KeyAlt) + "+" + s[iPosShortCut + 1];
  55. }
  56. // Extend an existing RunTimeID by one element
  57. internal static int[] AppendToRuntimeId(int[] baseID, int id)
  58. {
  59. // For the base case, where parent is a hwnd, baseID will be null,
  60. // so use AppendRuntimeId instead. UIA will then glue that to the ID
  61. // of the parent HWND.
  62. if(baseID == null)
  63. baseID = new int[] { AutomationInteropProvider.AppendRuntimeId };
  64. int len = baseID.Length;
  65. int[] newID = new int[len + 1];
  66. baseID.CopyTo(newID, 0);
  67. newID[len] = id;
  68. return newID;
  69. }
  70. internal static double[] RectArrayToDoubleArray(Rect[] rectArray)
  71. {
  72. if (rectArray == null)
  73. return null;
  74. double[] doubles = new double[rectArray.Length * 4];
  75. int scan = 0;
  76. for (int i = 0; i < rectArray.Length; i++)
  77. {
  78. doubles[scan++] = rectArray[i].X;
  79. doubles[scan++] = rectArray[i].Y;
  80. doubles[scan++] = rectArray[i].Width;
  81. doubles[scan++] = rectArray[i].Height;
  82. }
  83. return doubles;
  84. }
  85. // Ensure a window and all its parents are enabled.
  86. // If not, throw ElementNotEnabledException.
  87. internal static void CheckEnabled(IntPtr hwnd)
  88. {
  89. if (!IsEnabled(hwnd))
  90. {
  91. throw new ElementNotEnabledException();
  92. }
  93. }
  94. // Checks to see if the process owning the hwnd is currently in menu mode
  95. // and takes steps to exit menu mode if it is
  96. internal static void ClearMenuMode()
  97. {
  98. // Check if we're in menu mode with helper method.
  99. if (InMenuMode())
  100. {
  101. // If we are, send an alt keypress to escape
  102. Input.SendKeyboardInput(Key.LeftAlt, true);
  103. Input.SendKeyboardInput(Key.LeftAlt, false);
  104. // Wait for a few milliseconds for this operation to be completed
  105. long dwTicks = (long)Environment.TickCount;
  106. // Wait until the action has been completed
  107. while (InMenuMode() && ((long)Environment.TickCount - dwTicks) < MenuTimeOut)
  108. {
  109. // Sleep the shortest amount of time possible while still guaranteeing that some sleep occurs
  110. System.Threading.Thread.Sleep(1);
  111. }
  112. }
  113. }
  114. internal static bool CloseHandle(IntPtr processHandle)
  115. {
  116. bool result = UnsafeNativeMethods.CloseHandle(processHandle);
  117. int lastWin32Error = Marshal.GetLastWin32Error();
  118. if (!result)
  119. {
  120. ThrowWin32ExceptionsIfError(lastWin32Error);
  121. }
  122. return result;
  123. }
  124. // Compares 2 raw elements and returns true if equal, false otherwise
  125. internal static bool Compare(ProxySimple el1, ProxySimple el2)
  126. {
  127. int[] a1 = el1.GetRuntimeId();
  128. int[] a2 = el2.GetRuntimeId();
  129. int l = a1.Length;
  130. if (l != a2.Length)
  131. return false;
  132. for (int i = 0; i < l; i++)
  133. {
  134. if (a1[i] != a2[i])
  135. {
  136. return false;
  137. }
  138. }
  139. return true;
  140. }
  141. internal static IntPtr DispatchMessage(ref NativeMethods.MSG msg)
  142. {
  143. // From the Windows SDK documentation:
  144. // The return value specifies the value returned by the window procedure.
  145. // Although its meaning depends on the message being dispatched, the return
  146. // value generally is ignored.
  147. #pragma warning suppress 6031, 6523
  148. return UnsafeNativeMethods.DispatchMessage(ref msg);
  149. }
  150. internal unsafe static bool EnumChildWindows(IntPtr hwnd, NativeMethods.EnumChildrenCallbackVoid lpEnumFunc, void* lParam)
  151. {
  152. bool result = UnsafeNativeMethods.EnumChildWindows(hwnd, lpEnumFunc, lParam);
  153. int lastWin32Error = Marshal.GetLastWin32Error();
  154. if (!result)
  155. {
  156. ThrowWin32ExceptionsIfError(lastWin32Error);
  157. }
  158. return result;
  159. }
  160. internal static IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string wndName)
  161. {
  162. IntPtr result = NativeMethodsSetLastError.FindWindowEx(hwndParent, hwndChildAfter, className, wndName);
  163. int lastWin32Error = Marshal.GetLastWin32Error();
  164. if (result == IntPtr.Zero)
  165. {
  166. ThrowWin32ExceptionsIfError(lastWin32Error);
  167. }
  168. return result;
  169. }
  170. internal static string GetClassName(IntPtr hwnd)
  171. {
  172. StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH + 1);
  173. int result = UnsafeNativeMethods.GetClassName(hwnd, sb, NativeMethods.MAX_PATH);
  174. int lastWin32Error = Marshal.GetLastWin32Error();
  175. if (result == 0)
  176. {
  177. ThrowWin32ExceptionsIfError(lastWin32Error);
  178. return "";
  179. }
  180. return sb.ToString();
  181. }
  182. // Get the name of a control and conditionally strip mnemonic.
  183. // label is the hwnd of the control that is funtioning as the label. Use GetLabelhwnd to find this.
  184. // If stripMnemonic is true, amperstrands characters will be stripped out.
  185. internal static string GetControlName(IntPtr label, bool stripMnemonic)
  186. {
  187. if (label == IntPtr.Zero)
  188. {
  189. return null;
  190. }
  191. StringBuilder sb = new StringBuilder(MaxLengthNameProperty);
  192. int result = NativeMethodsSetLastError.GetWindowText(label, sb, MaxLengthNameProperty);
  193. int lastWin32Error = Marshal.GetLastWin32Error();
  194. if (result == 0)
  195. {
  196. ThrowWin32ExceptionsIfError(lastWin32Error);
  197. return null;
  198. }
  199. return stripMnemonic ? StripMnemonic(sb.ToString()) : sb.ToString();
  200. }
  201. internal static bool GetClientRectInScreenCoordinates(IntPtr hwnd, ref NativeMethods.Win32Rect rc)
  202. {
  203. rc = NativeMethods.Win32Rect.Empty;
  204. if (!GetClientRect(hwnd, ref rc))
  205. {
  206. return false;
  207. }
  208. NativeMethods.Win32Point leftTop = new NativeMethods.Win32Point(rc.left, rc.top);
  209. if (!MapWindowPoints(hwnd, IntPtr.Zero, ref leftTop, 1))
  210. {
  211. return false;
  212. }
  213. NativeMethods.Win32Point rightBottom = new NativeMethods.Win32Point(rc.right, rc.bottom);
  214. if (!MapWindowPoints(hwnd, IntPtr.Zero, ref rightBottom, 1))
  215. {
  216. return false;
  217. }
  218. rc = new NativeMethods.Win32Rect(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y);
  219. return true;
  220. }
  221. internal static bool GetClientRect(IntPtr hwnd, ref NativeMethods.Win32Rect rc)
  222. {
  223. bool result = UnsafeNativeMethods.GetClientRect(hwnd, ref rc);
  224. int lastWin32Error = Marshal.GetLastWin32Error();
  225. if (!result)
  226. {
  227. ThrowWin32ExceptionsIfError(lastWin32Error);
  228. }
  229. // When the control is right to left GetClentRect() will return a rectangle with left > right.
  230. // Normalize thesee rectangle back to left to right.
  231. rc.Normalize(IsLayoutRTL(hwnd));
  232. return result;
  233. }
  234. internal static bool GetComboBoxInfo(IntPtr hwnd, ref NativeMethods.COMBOBOXINFO cbi)
  235. {
  236. bool result = UnsafeNativeMethods.GetComboBoxInfo(hwnd, ref cbi);
  237. int lastWin32Error = Marshal.GetLastWin32Error();
  238. if (!result)
  239. {
  240. ThrowWin32ExceptionsIfError(lastWin32Error);
  241. }
  242. return result;
  243. }
  244. internal static bool GetCursorPos(ref NativeMethods.Win32Point pt)
  245. {
  246. // Vista and beyond use GetPhysicalCursorPos which handles DPI issues
  247. bool result = (System.Environment.OSVersion.Version.Major >= 6) ? UnsafeNativeMethods.GetPhysicalCursorPos(ref pt)
  248. : UnsafeNativeMethods.GetCursorPos(ref pt);
  249. int lastWin32Error = Marshal.GetLastWin32Error();
  250. if (!result)
  251. {
  252. ThrowWin32ExceptionsIfError(lastWin32Error);
  253. }
  254. return result;
  255. }
  256. internal static IntPtr GetDC(IntPtr hwnd)
  257. {
  258. IntPtr hdc = UnsafeNativeMethods.GetDC(hwnd);
  259. int lastWin32Error = Marshal.GetLastWin32Error();
  260. if (hdc == IntPtr.Zero)
  261. {
  262. ThrowWin32ExceptionsIfError(lastWin32Error);
  263. }
  264. return hdc;
  265. }
  266. internal static IntPtr GetFocusedWindow()
  267. {
  268. NativeMethods.GUITHREADINFO gui;
  269. return ProxyGetGUIThreadInfo(0, out gui) ? gui.hwndFocus : IntPtr.Zero;
  270. }
  271. internal static string GetItemToolTipText(IntPtr hwnd, IntPtr hwndToolTip, int item)
  272. {
  273. if (hwndToolTip != IntPtr.Zero)
  274. {
  275. // We've found the tooltip window, so we won't need to scan for it.
  276. // Got a tooltip window - use it.
  277. NativeMethods.TOOLINFO tool = new NativeMethods.TOOLINFO();
  278. tool.Init(Marshal.SizeOf(typeof(NativeMethods.TOOLINFO)));
  279. tool.hwnd = hwnd;
  280. tool.uId = item;
  281. return XSendMessage.GetItemText(hwndToolTip, tool);
  282. }
  283. else
  284. {
  285. // Control doesn't know its tooltip window - instead scan for one...
  286. // Enum the top-level windows owned by this thread...
  287. uint processId;
  288. uint threadId = GetWindowThreadProcessId(hwnd, out processId);
  289. UnsafeNativeMethods.ENUMTOOLTIPWINDOWINFO info = new UnsafeNativeMethods.ENUMTOOLTIPWINDOWINFO();
  290. info.hwnd = hwnd;
  291. info.id = item;
  292. info.name = "";
  293. UnsafeNativeMethods.EnumThreadWndProc enumToolTipWindows = new UnsafeNativeMethods.EnumThreadWndProc(EnumToolTipWindows);
  294. GCHandle gch = GCHandle.Alloc(enumToolTipWindows);
  295. UnsafeNativeMethods.EnumThreadWindows(threadId, enumToolTipWindows, ref info);
  296. gch.Free();
  297. return info.name;
  298. }
  299. }
  300. // --------------------------------------------------------------------------
  301. //
  302. // GetLabelhwnd()
  303. //
  304. // This walks backwards among peer windows to find a static field. It stops
  305. // if it gets to the front or hits a group/tabstop, just like the dialog
  306. // manager does.
  307. //
  308. // Ported from OleAcc\Client.CPP
  309. // --------------------------------------------------------------------------
  310. internal static IntPtr GetLabelhwnd(IntPtr hwnd)
  311. {
  312. // Sanity check
  313. if (!UnsafeNativeMethods.IsWindow(hwnd))
  314. {
  315. return IntPtr.Zero;
  316. }
  317. // Only get labels for child windows - not top-level windows or desktop
  318. IntPtr hwndParent = Misc.GetParent(hwnd);
  319. if (hwndParent == IntPtr.Zero || hwndParent == UnsafeNativeMethods.GetDesktopWindow())
  320. {
  321. return IntPtr.Zero;
  322. }
  323. IntPtr peer = hwnd;
  324. // If GetWindow fails we're going to exit, no need to call Marshal.GetLastWin32Error
  325. #pragma warning suppress 56523
  326. while ((peer = NativeMethodsSetLastError.GetWindow(peer, NativeMethods.GW_HWNDPREV)) != IntPtr.Zero)
  327. {
  328. //
  329. // Is this a static dude?
  330. //
  331. int code = Misc.ProxySendMessageInt(peer, NativeMethods.WM_GETDLGCODE, IntPtr.Zero, IntPtr.Zero);
  332. if ((code & NativeMethods.DLGC_STATIC) == NativeMethods.DLGC_STATIC)
  333. {
  334. //
  335. // Great, we've found our label.
  336. //
  337. return peer;
  338. }
  339. //
  340. // Skip invisible controls.
  341. // Note that we do this after checking if its a static, so that we give invisible statics a chance.
  342. // Using invisible statics is an easy workaround to add names to controls without changing the visual UI.
  343. //
  344. // If GetWindowLong fails we're going to exit, no need to call Marshal.GetLastWin32Error
  345. #pragma warning suppress 56523
  346. int error = 0;
  347. int style = UnsafeNativeMethods.GetWindowLong(peer, NativeMethods.GWL_STYLE, out error);
  348. if ((style & NativeMethods.WS_VISIBLE) != 0)
  349. continue;
  350. //
  351. // Is this a tabstop or group? If so, bail out now.
  352. //
  353. if ((style & (NativeMethods.WS_GROUP | NativeMethods.WS_TABSTOP)) != 0)
  354. break;
  355. }
  356. // Failed to find a suitable peer
  357. return IntPtr.Zero;
  358. }
  359. internal static bool GetMenuBarInfo(IntPtr hwnd, int idObject, uint item, ref NativeMethods.MENUBARINFO mbi)
  360. {
  361. bool result = NativeMethodsSetLastError.GetMenuBarInfo(hwnd, idObject, item, ref mbi);
  362. int lastWin32Error = Marshal.GetLastWin32Error();
  363. if (!result)
  364. {
  365. ThrowWin32ExceptionsIfError(lastWin32Error);
  366. }
  367. return result;
  368. }
  369. internal static int GetMenuItemCount(IntPtr hmenu)
  370. {
  371. int count = UnsafeNativeMethods.GetMenuItemCount(hmenu);
  372. int lastWin32Error = Marshal.GetLastWin32Error();
  373. if (count == -1)
  374. {
  375. ThrowWin32ExceptionsIfError(lastWin32Error);
  376. }
  377. return count;
  378. }
  379. internal static bool GetMenuItemInfo(IntPtr hmenu, int item, bool byPosition, ref NativeMethods.MENUITEMINFO menuItemInfo)
  380. {
  381. bool result = UnsafeNativeMethods.GetMenuItemInfo(hmenu, item, byPosition, ref menuItemInfo);
  382. int lastWin32Error = Marshal.GetLastWin32Error();
  383. if (!result)
  384. {
  385. ThrowWin32ExceptionsIfError(lastWin32Error);
  386. }
  387. return result;
  388. }
  389. internal static bool GetMenuItemRect(IntPtr hwnd, IntPtr hmenu, int item, out NativeMethods.Win32Rect rc)
  390. {
  391. bool result = UnsafeNativeMethods.GetMenuItemRect(hwnd, hmenu, item, out rc);
  392. int lastWin32Error = Marshal.GetLastWin32Error();
  393. if (!result)
  394. {
  395. ThrowWin32ExceptionsIfError(lastWin32Error);
  396. }
  397. return result;
  398. }
  399. internal static bool GetMessage(ref NativeMethods.MSG msg, IntPtr hwnd, int msgFilterMin, int msgFilterMax)
  400. {
  401. int result = UnsafeNativeMethods.GetMessage(ref msg, hwnd, msgFilterMin, msgFilterMax);
  402. int lastWin32Error = Marshal.GetLastWin32Error();
  403. bool success = (result != 0 && result != -1);
  404. if (!success)
  405. {
  406. ThrowWin32ExceptionsIfError(lastWin32Error);
  407. }
  408. return success;
  409. }
  410. internal static int GetObjectW(IntPtr hObject, int size, ref NativeMethods.LOGFONT lf)
  411. {
  412. int result = UnsafeNativeMethods.GetObjectW(hObject, size, ref lf);
  413. int lastWin32Error = Marshal.GetLastWin32Error();
  414. if (result == 0)
  415. {
  416. ThrowWin32ExceptionsIfError(lastWin32Error);
  417. }
  418. return result;
  419. }
  420. internal static IntPtr GetParent(IntPtr hwnd)
  421. {
  422. IntPtr hwndParent = NativeMethodsSetLastError.GetAncestor(hwnd, NativeMethods.GA_PARENT);
  423. int lastWin32Error = Marshal.GetLastWin32Error();
  424. if (hwndParent == IntPtr.Zero)
  425. {
  426. ThrowWin32ExceptionsIfError(lastWin32Error);
  427. }
  428. return hwndParent;
  429. }
  430. internal static bool GetScrollBarInfo(IntPtr hwnd, int fnBar, ref NativeMethods.ScrollBarInfo sbi)
  431. {
  432. bool result = UnsafeNativeMethods.GetScrollBarInfo(hwnd, fnBar, ref sbi);
  433. int lastWin32Error = Marshal.GetLastWin32Error();
  434. if (!result)
  435. {
  436. ThrowWin32ExceptionsIfError(lastWin32Error);
  437. }
  438. return result;
  439. }
  440. internal static bool GetScrollInfo(IntPtr hwnd, int fnBar, ref NativeMethods.ScrollInfo si)
  441. {
  442. bool result = UnsafeNativeMethods.GetScrollInfo(hwnd, fnBar, ref si);
  443. int lastWin32Error = Marshal.GetLastWin32Error();
  444. if (!result)
  445. {
  446. // 1447 ERROR_NO_SCROLLBARS The window does not have scroll bars.
  447. // If GetScrollInfo() fails with ERROR_NO_SCROLLBARS then there is no scroll information
  448. // to get. Just return false saying that GetScrollInfo() could not get the information
  449. if (lastWin32Error == 1447)
  450. {
  451. return false;
  452. }
  453. ThrowWin32ExceptionsIfError(lastWin32Error);
  454. }
  455. return result;
  456. }
  457. internal static int GetTextExtentPoint32(IntPtr hdc, string text, int length, out NativeMethods.SIZE size)
  458. {
  459. int result = NativeMethodsSetLastError.GetTextExtentPoint32(hdc, text, length, out size);
  460. int lastWin32Error = Marshal.GetLastWin32Error();
  461. if (result == 0)
  462. {
  463. ThrowWin32ExceptionsIfError(lastWin32Error);
  464. }
  465. return result;
  466. }
  467. // Calls a message that retrieves a string, but doesn't take a length argument, in a relatively safe manner.
  468. // Attempts to rapidly resize in hopes of crashing UI Automation should just crash whatever is rapidly resizing.
  469. // Param "hwnd" the Window Handle
  470. // Param "uMsg" the Windows Message
  471. // Param "wParam" the Windows wParam
  472. // Param "maxLength" the size of the string
  473. internal static unsafe string GetUnsafeText(IntPtr hwnd, int uMsg, IntPtr wParam, int maxLength)
  474. {
  475. uint pageSize = GetPageSize();
  476. IntPtr memAddr = IntPtr.Zero; // Ptr to remote mem
  477. // calculate the size needed for the string
  478. uint cbSize = (uint)((maxLength + 1) * sizeof(char));
  479. // resize it to include enough pages for the string, and an extra guarding page, and one extra page to account for shifts.
  480. cbSize = ((cbSize / pageSize) + 3) * pageSize;
  481. try
  482. {
  483. // Allocate the space
  484. memAddr = VirtualAlloc(IntPtr.Zero, new UIntPtr(cbSize), UnsafeNativeMethods.MEM_COMMIT, UnsafeNativeMethods.PAGE_READWRITE);
  485. // Allocate the Final page as No Access, so any attempt to write to it will GPF
  486. VirtualAlloc(new IntPtr((byte *)memAddr.ToPointer() + cbSize - pageSize), new UIntPtr(pageSize), UnsafeNativeMethods.MEM_COMMIT, UnsafeNativeMethods.PAGE_NOACCESS);
  487. // Send the message...
  488. if (ProxySendMessage(hwnd, uMsg, wParam, memAddr) == IntPtr.Zero)
  489. {
  490. return "";
  491. }
  492. String str = new string((char*)memAddr.ToPointer(), 0, maxLength);
  493. // Note: lots of "old world" strings are null terminated
  494. // Leaving the null termination in the System.String may lead
  495. // to some issues when used with the StringBuilder
  496. int nullTermination = str.IndexOf('\0');
  497. if (-1 != nullTermination)
  498. {
  499. // We need to strip null terminated char and everything behind it from the str
  500. str = str.Remove(nullTermination, maxLength - nullTermination);
  501. }
  502. return str;
  503. }
  504. finally
  505. {
  506. // Free the memory
  507. if (memAddr != IntPtr.Zero)
  508. {
  509. VirtualFree(memAddr, UIntPtr.Zero, UnsafeNativeMethods.MEM_RELEASE);
  510. }
  511. }
  512. }
  513. internal static IntPtr GetWindow(IntPtr hwnd, int cmd)
  514. {
  515. IntPtr resultHwnd = NativeMethodsSetLastError.GetWindow(hwnd, cmd);
  516. int lastWin32Error = Marshal.GetLastWin32Error();
  517. if (resultHwnd == IntPtr.Zero)
  518. {
  519. ThrowWin32ExceptionsIfError(lastWin32Error);
  520. }
  521. return resultHwnd;
  522. }
  523. // Gets the extended style of the window
  524. internal static int GetWindowExStyle(IntPtr hwnd)
  525. {
  526. int lastWin32Error = 0;
  527. int exstyle = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_EXSTYLE, out lastWin32Error);
  528. if (exstyle == 0)
  529. {
  530. ThrowWin32ExceptionsIfError(lastWin32Error);
  531. }
  532. return exstyle;
  533. }
  534. // Gets the id of the window
  535. internal static int GetWindowId(IntPtr hwnd)
  536. {
  537. int lastWin32Error = 0;
  538. int id = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_ID, out lastWin32Error);
  539. if (id == 0)
  540. {
  541. ThrowWin32ExceptionsIfError(lastWin32Error);
  542. }
  543. return id;
  544. }
  545. // Gets the parent of the window
  546. internal static IntPtr GetWindowParent(IntPtr hwnd)
  547. {
  548. // NOTE: This may have issues in 64-bit.
  549. int lastWin32Error = 0;
  550. int result = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_HWNDPARENT, out lastWin32Error);
  551. if (result == 0)
  552. {
  553. ThrowWin32ExceptionsIfError(lastWin32Error);
  554. }
  555. return (IntPtr)result;
  556. }
  557. internal static bool GetWindowRect(IntPtr hwnd, ref NativeMethods.Win32Rect rc)
  558. {
  559. bool result = UnsafeNativeMethods.GetWindowRect(hwnd, ref rc);
  560. int lastWin32Error = Marshal.GetLastWin32Error();
  561. if (!result)
  562. {
  563. ThrowWin32ExceptionsIfError(lastWin32Error);
  564. }
  565. return result;
  566. }
  567. // Gets the style of the window
  568. internal static int GetWindowStyle(IntPtr hwnd)
  569. {
  570. int lastWin32Error = 0;
  571. int style = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_STYLE, out lastWin32Error);
  572. if (style == 0)
  573. {
  574. ThrowWin32ExceptionsIfError(lastWin32Error);
  575. }
  576. return style;
  577. }
  578. internal static uint GetWindowThreadProcessId(IntPtr hwnd, out uint processId)
  579. {
  580. // GetWindowThreadProcessId does use SetLastError(). So a call to GetLastError() would be meanless.
  581. // Disabling the PreSharp warning.
  582. #pragma warning suppress 6523
  583. uint threadId = UnsafeNativeMethods.GetWindowThreadProcessId(hwnd, out processId);
  584. if (threadId == 0)
  585. {
  586. throw new ElementNotAvailableException();
  587. }
  588. return threadId;
  589. }
  590. internal static short GlobalAddAtom(string atomName)
  591. {
  592. short atom = UnsafeNativeMethods.GlobalAddAtom(atomName);
  593. int lastWin32Error = Marshal.GetLastWin32Error();
  594. if (atom == 0)
  595. {
  596. ThrowWin32ExceptionsIfError(lastWin32Error);
  597. }
  598. return atom;
  599. }
  600. internal static short GlobalDeleteAtom(short atom)
  601. {
  602. short result = NativeMethodsSetLastError.GlobalDeleteAtom(atom);
  603. ThrowWin32ExceptionsIfError(Marshal.GetLastWin32Error());
  604. return result;
  605. }
  606. // detect if we're in the menu mode
  607. internal static bool InMenuMode()
  608. {
  609. NativeMethods.GUITHREADINFO gui;
  610. return (ProxyGetGUIThreadInfo(0, out gui) && (IsBitSet(gui.dwFlags, NativeMethods.GUI_INMENUMODE)));
  611. }
  612. internal static bool IsBitSet(int flags, int bit)
  613. {
  614. return (flags & bit) == bit;
  615. }
  616. // Check if window is really enabled, taking parent state into account.
  617. internal static bool IsEnabled(IntPtr hwnd)
  618. {
  619. // Navigate up parent chain. If any ancestor window is
  620. // not enabled, then that has the effect of disabling this window.
  621. // All ancestor windows must be enabled for this window to be enabled.
  622. for (; ; )
  623. {
  624. if (!SafeNativeMethods.IsWindowEnabled(hwnd))
  625. {
  626. return false;
  627. }
  628. hwnd = NativeMethodsSetLastError.GetAncestor(hwnd, NativeMethods.GA_PARENT);
  629. if (hwnd == IntPtr.Zero)
  630. {
  631. return true;
  632. }
  633. }
  634. }
  635. internal static bool IsControlRTL(IntPtr hwnd)
  636. {
  637. int exStyle = GetWindowExStyle(hwnd);
  638. return IsBitSet(exStyle, NativeMethods.WS_EX_LAYOUTRTL) || IsBitSet(exStyle, NativeMethods.WS_EX_RTLREADING);
  639. }
  640. internal static bool IsLayoutRTL(IntPtr hwnd)
  641. {
  642. return IsBitSet(GetWindowExStyle(hwnd), NativeMethods.WS_EX_LAYOUTRTL);
  643. }
  644. internal static bool IsReadingRTL(IntPtr hwnd)
  645. {
  646. return IsBitSet(GetWindowExStyle(hwnd), NativeMethods.WS_EX_RTLREADING);
  647. }
  648. internal static bool IntersectRect(ref NativeMethods.Win32Rect rcDest, ref NativeMethods.Win32Rect rc1, ref NativeMethods.Win32Rect rc2)
  649. {
  650. bool result = SafeNativeMethods.IntersectRect(ref rcDest, ref rc1, ref rc2);
  651. int lastWin32Error = Marshal.GetLastWin32Error();
  652. if (!result)
  653. {
  654. ThrowWin32ExceptionsIfError(lastWin32Error);
  655. }
  656. return result;
  657. }
  658. // Call IsCriticalException w/in a catch-all-exception handler to allow critical exceptions
  659. // to be thrown (this is copied from exception handling code in [....] but feel free to
  660. // add new critical exceptions). Usage:
  661. // try
  662. // {
  663. // Somecode();
  664. // }
  665. // catch (Exception e)
  666. // {
  667. // if (Misc.IsCriticalException(e))
  668. // throw;
  669. // // ignore non-critical errors from external code
  670. // }
  671. internal static bool IsCriticalException(Exception e)
  672. {
  673. return e is NullReferenceException || e is StackOverflowException || e is OutOfMemoryException || e is System.Threading.ThreadAbortException;
  674. }
  675. // this is to determine is an item is visible. The assumption is that the items here are not hwnds
  676. // and that they are clipped by there parent. For example this is called by the WindowsListBox.
  677. // In that case the hwnd is the list box and the itemRect would be a list item this code checks to see
  678. // if the item is scrolled out of view.
  679. static internal bool IsItemVisible(IntPtr hwnd, ref NativeMethods.Win32Rect itemRect)
  680. {
  681. NativeMethods.Win32Rect clientRect = new NativeMethods.Win32Rect(0, 0, 0, 0);
  682. if (!GetClientRectInScreenCoordinates(hwnd, ref clientRect))
  683. return false;
  684. NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
  685. // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
  686. // does not modify clientRect or itemRect
  687. return IntersectRect(ref intersection, ref clientRect, ref itemRect);
  688. }
  689. static internal bool IsItemVisible(ref NativeMethods.Win32Rect parentRect, ref NativeMethods.Win32Rect itemRect)
  690. {
  691. NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
  692. // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
  693. // does not modify clientRect or itemRect
  694. return IntersectRect(ref intersection, ref parentRect, ref itemRect);
  695. }
  696. static internal bool IsItemVisible(ref NativeMethods.Win32Rect parentRect, ref Rect itemRect)
  697. {
  698. NativeMethods.Win32Rect itemRc = new NativeMethods.Win32Rect(itemRect);
  699. NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
  700. // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
  701. // does not modify clientRect or itemRect
  702. return IntersectRect(ref intersection, ref parentRect, ref itemRc);
  703. }
  704. static internal bool IsItemVisible(ref Rect parentRect, ref NativeMethods.Win32Rect itemRect)
  705. {
  706. NativeMethods.Win32Rect parentRc = new NativeMethods.Win32Rect(parentRect);
  707. NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
  708. // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
  709. // does not modify clientRect or itemRect
  710. return IntersectRect(ref intersection, ref parentRc, ref itemRect);
  711. }
  712. static internal bool IsItemVisible(ref Rect parentRect, ref Rect itemRect)
  713. {
  714. NativeMethods.Win32Rect itemRc = new NativeMethods.Win32Rect(itemRect);
  715. NativeMethods.Win32Rect parentRc = new NativeMethods.Win32Rect(parentRect);
  716. NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
  717. // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
  718. // does not modify clientRect or itemRect
  719. return IntersectRect(ref intersection, ref parentRc, ref itemRc);
  720. }
  721. internal static bool IsProgmanWindow(IntPtr hwnd)
  722. {
  723. while (hwnd != IntPtr.Zero)
  724. {
  725. if (GetClassName(hwnd).CompareTo("Progman") == 0)
  726. {
  727. return true;
  728. }
  729. hwnd = NativeMethodsSetLastError.GetAncestor(hwnd, NativeMethods.GA_PARENT);
  730. }
  731. return false;
  732. }
  733. internal static bool IsWow64Process(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, out bool Wow64Process)
  734. {
  735. bool result = UnsafeNativeMethods.IsWow64Process(hProcess, out Wow64Process);
  736. int lastWin32Error = Marshal.GetLastWin32Error();
  737. if (!result)
  738. {
  739. ThrowWin32ExceptionsIfError(lastWin32Error);
  740. }
  741. return result;
  742. }
  743. // wrapper for MapWindowPoints
  744. internal static bool MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, ref NativeMethods.Win32Rect rect, int cPoints)
  745. {
  746. int mappingOffset = NativeMethodsSetLastError.MapWindowPoints(hWndFrom, hWndTo, ref rect, cPoints);
  747. int lastWin32Error = Marshal.GetLastWin32Error();
  748. if (mappingOffset == 0)
  749. {
  750. // When mapping points to/from Progman and its children MapWindowPoints may fail with error code 1400
  751. // Invalid Window Handle. Since Progman is the desktop no mapping is need.
  752. if ((IsProgmanWindow(hWndFrom) && hWndTo == IntPtr.Zero) ||
  753. (hWndFrom == IntPtr.Zero && IsProgmanWindow(hWndTo)))
  754. {
  755. lastWin32Error = 0;
  756. }
  757. ThrowWin32ExceptionsIfError(lastWin32Error);
  758. // If the coordinates is at the origin a zero return is valid.
  759. // Use GetLastError() to check that. Error code 0 is "Operation completed successfull".
  760. return lastWin32Error == 0;
  761. }
  762. return true;
  763. }
  764. // wrapper for MapWindowPoints
  765. internal static bool MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, ref NativeMethods.Win32Point pt, int cPoints)
  766. {
  767. int mappingOffset = NativeMethodsSetLastError.MapWindowPoints(hWndFrom, hWndTo, ref pt, cPoints);
  768. int lastWin32Error = Marshal.GetLastWin32Error();
  769. if (mappingOffset == 0)
  770. {
  771. // When mapping points to/from Progman and its children MapWindowPoints may fail with error code 1400
  772. // Invalid Window Handle. Since Progman is the desktop no mapping is need.
  773. if ((IsProgmanWindow(hWndFrom) && hWndTo == IntPtr.Zero) ||
  774. (hWndFrom == IntPtr.Zero && IsProgmanWindow(hWndTo)))
  775. {
  776. lastWin32Error = 0;
  777. }
  778. ThrowWin32ExceptionsIfError(lastWin32Error);
  779. // If the coordinates is at the origin a zero return is valid.
  780. // Use GetLastError() to check that. Error code 0 is "Operation completed successfull".
  781. return lastWin32Error == 0;
  782. }
  783. return true;
  784. }
  785. // Move the mouse to the x, y location and perfoms a mouse clik
  786. // The mouse is then brough back to the original location.
  787. internal static void MouseClick(int x, int y)
  788. {
  789. MouseClick(x, y, false);
  790. }
  791. // Move the mouse to the x, y location and perfoms either
  792. // a single of double clik depending on the fDoubleClick parameter
  793. // The mouse is then brough back to the original location.
  794. internal static void MouseClick(int x, int y, bool fDoubleClick)
  795. {
  796. NativeMethods.Win32Point ptPrevious = new NativeMethods.Win32Point();
  797. bool fSetOldCursorPos = GetCursorPos(ref ptPrevious);
  798. bool mouseSwapped = UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_SWAPBUTTON) != 0;
  799. Input.SendMouseInput(x, y, 0, SendMouseInputFlags.Move | SendMouseInputFlags.Absolute);
  800. Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightDown : SendMouseInputFlags.LeftDown);
  801. Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightUp : SendMouseInputFlags.LeftUp);
  802. if (fDoubleClick)
  803. {
  804. Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightDown : SendMouseInputFlags.LeftDown);
  805. Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightUp : SendMouseInputFlags.LeftUp);
  806. }
  807. // toolbar items don't have time to proccess the mouse click if we move it back too soon
  808. // so wait a small amount of time to give them a chance. A value of 10 made this work
  809. // on a 2gig dual proc machine so 50 should cover a slower machine.
  810. System.Threading.Thread.Sleep(50);
  811. // Set back the mouse position where it was
  812. if (fSetOldCursorPos)
  813. {
  814. Input.SendMouseInput(ptPrevious.x, ptPrevious.y, 0, SendMouseInputFlags.Move | SendMouseInputFlags.Absolute);
  815. }
  816. }
  817. [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
  818. internal static int MsgWaitForMultipleObjects(SafeWaitHandle handle, bool waitAll, int milliseconds, int wakeMask)
  819. {
  820. int terminationEvent, lastWin32Error;
  821. if (handle == null)
  822. {
  823. terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(0, null, waitAll, milliseconds, wakeMask);
  824. lastWin32Error = Marshal.GetLastWin32Error();
  825. }
  826. else
  827. {
  828. RuntimeHelpers.PrepareConstrainedRegions();
  829. bool fRelease = false;
  830. try
  831. {
  832. handle.DangerousAddRef(ref fRelease);
  833. IntPtr[] handles = { handle.DangerousGetHandle() };
  834. terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(1, handles, waitAll, milliseconds, wakeMask);
  835. lastWin32Error = Marshal.GetLastWin32Error();
  836. }
  837. finally
  838. {
  839. if (fRelease)
  840. {
  841. handle.DangerousRelease();
  842. }
  843. }
  844. }
  845. if (terminationEvent == NativeMethods.WAIT_FAILED)
  846. {
  847. ThrowWin32ExceptionsIfError(lastWin32Error);
  848. }
  849. return terminationEvent;
  850. }
  851. internal static IntPtr OpenProcess(int flags, bool inherit, uint processId, IntPtr hwnd)
  852. {
  853. IntPtr processHandle = UnsafeNativeMethods.OpenProcess(flags, inherit, processId);
  854. int lastWin32Error = Marshal.GetLastWin32Error();
  855. // If we fail due to permission issues, if we're on vista, try the hooking technique
  856. // to access the process instead.
  857. if (processHandle == IntPtr.Zero
  858. && lastWin32Error == 5/*ERROR_ACCESS_DENIED*/
  859. && System.Environment.OSVersion.Version.Major >= 6)
  860. {
  861. try
  862. {
  863. processHandle = UnsafeNativeMethods.GetProcessHandleFromHwnd(hwnd);
  864. lastWin32Error = Marshal.GetLastWin32Error();
  865. }
  866. catch(EntryPointNotFoundException)
  867. {
  868. // Ignore; until OLEACC propogates into Vista builds, the entry point may not be present.
  869. }
  870. }
  871. if (processHandle == IntPtr.Zero)
  872. {
  873. ThrowWin32ExceptionsIfError(lastWin32Error);
  874. }
  875. return processHandle;
  876. }
  877. // wrapper for PostMessage
  878. internal static void PostMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
  879. {
  880. bool result = UnsafeNativeMethods.PostMessage(hwnd, msg, wParam, lParam);
  881. int lastWin32Error = Marshal.GetLastWin32Error();
  882. if (!result)
  883. {
  884. ThrowWin32ExceptionsIfError(lastWin32Error);
  885. }
  886. }
  887. // Returns the Win32 Class Name for an hwnd
  888. internal static string ProxyGetClassName(IntPtr hwnd)
  889. {
  890. const int OBJID_QUERYCLASSNAMEIDX = unchecked(unchecked((int)0xFFFFFFF4));
  891. const int QUERYCLASSNAME_BASE = 65536;
  892. // Call ProxySendMessage ignoring the timeout
  893. //
  894. int index = ProxySendMessageInt(hwnd, NativeMethods.WM_GETOBJECT, IntPtr.Zero, (IntPtr)OBJID_QUERYCLASSNAMEIDX, true);
  895. if (index >= QUERYCLASSNAME_BASE && index - QUERYCLASSNAME_BASE < _asClassNames.Length)
  896. {
  897. return _asClassNames[index - QUERYCLASSNAME_BASE];
  898. }
  899. else
  900. {
  901. return RealGetWindowClass(hwnd);
  902. }
  903. }
  904. // wrapper for GetGuiThreadInfo
  905. internal static bool ProxyGetGUIThreadInfo(uint idThread, out NativeMethods.GUITHREADINFO gui)
  906. {
  907. gui = new NativeMethods.GUITHREADINFO();
  908. gui.cbSize = Marshal.SizeOf(gui.GetType());
  909. bool result = UnsafeNativeMethods.GetGUIThreadInfo(idThread, ref gui);
  910. int lastWin32Error = Marshal.GetLastWin32Error();
  911. if (!result)
  912. {
  913. // If the focused thread is on another [secure] desktop, GetGUIThreadInfo
  914. // will fail with ERROR_ACCESS_DENIED - don't throw an exception for that case,
  915. // instead treat as a failure. Callers will treat this as though no window has
  916. // focus.
  917. if (lastWin32Error == 5 /*ERROR_ACCESS_DENIED*/)
  918. return false;
  919. ThrowWin32ExceptionsIfError(lastWin32Error);
  920. }
  921. #if _NEED_DEBUG_OUTPUT
  922. bool fCaretBlink = (gui.dwFlags & NativeMethods.GUI_CARETBLINKING) != 0;
  923. bool fMoveSize = (gui.dwFlags & NativeMethods.GUI_INMOVESIZE) != 0;
  924. bool fMenuMode = (gui.dwFlags & NativeMethods.GUI_INMENUMODE) != 0;
  925. bool fSystemMenuMode = (gui.dwFlags & NativeMethods.GUI_SYSTEMMENUMODE) != 0;
  926. bool fPopupMenuMode = (gui.dwFlags & NativeMethods.GUI_POPUPMENUMODE) != 0;
  927. StringBuilder sbFlag = new StringBuilder(NativeMethods.MAX_PATH);
  928. if (fCaretBlink)
  929. {
  930. sbFlag.Append("GUI_CARETBLINKING");
  931. }
  932. if (fMoveSize)
  933. {
  934. sbFlag.Append(sbFlag.Length > 0 ? " | GUI_INMOVESIZE" : "GUI_INMOVESIZE");
  935. }
  936. if (fMenuMode)
  937. {
  938. sbFlag.Append(sbFlag.Length > 0 ? " | GUI_INMENUMODE" : "GUI_INMENUMODE");
  939. }
  940. if (fSystemMenuMode)
  941. {
  942. sbFlag.Append(sbFlag.Length > 0 ? " | GUI_SYSTEMMENUMODE" : "GUI_SYSTEMMENUMODE");
  943. }
  944. if (fPopupMenuMode)
  945. {
  946. sbFlag.Append(sbFlag.Length > 0 ? " | GUI_POPUPMENUMODE" : "GUI_POPUPMENUMODE");
  947. }
  948. StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH);
  949. sb.Append("GUITHREADINFO \n\r{");
  950. sb.AppendFormat("\n\r\tcbSize = {0}", gui.cbSize);
  951. sb.AppendFormat("\n\r\tdwFlags = {0}", gui.dwFlags);
  952. if (sbFlag.Length > 0)
  953. {
  954. sb.Append(" (");
  955. sb.Append(sbFlag);
  956. sb.Append(")");
  957. }
  958. sb.AppendFormat("\n\r\thwndActive = 0x{0:x8}", gui.hwndActive.ToInt32());
  959. sb.AppendFormat("\n\r\thwndFocus = 0x{0:x8}", gui.hwndFocus.ToInt32());
  960. sb.AppendFormat("\n\r\thwndCapture = 0x{0:x8}", gui.hwndCapture.ToInt32());
  961. sb.AppendFormat("\n\r\thwndMenuOwner = 0x{0:x8}", gui.hwndMenuOwner.ToInt32());
  962. sb.AppendFormat("\n\r\thwndMoveSize = 0x{0:x8}", gui.hwndMoveSize.ToInt32());
  963. sb.AppendFormat("\n\r\thwndCaret = 0x{0:x8}", gui.hwndCaret.ToInt32());
  964. sb.AppendFormat("\n\r\trc = ({0}, {1}, {2}, {3})", gui.rc.left, gui.rc.top, gui.rc.right, gui.rc.bottom);
  965. sb.Append("\n\r}");
  966. System.Diagnostics.Debug.WriteLine(sb.ToString());
  967. #endif
  968. return result;
  969. }
  970. // The name text based on the WM_GETTEXT message. The text is truncated to a predefined character
  971. // length.
  972. internal static string ProxyGetText(IntPtr hwnd)
  973. {
  974. return ProxyGetText(hwnd, MaxLengthNameProperty);
  975. }
  976. internal static string ProxyGetText(IntPtr hwnd, int length)
  977. {
  978. // if the length is zero don't bother asking for the text.
  979. if (length == 0)
  980. {
  981. return "";
  982. }
  983. // Length passes to SendMessage includes terminating NUL
  984. StringBuilder str = new StringBuilder(length + 1);
  985. // Send the message...
  986. ProxySendMessage(hwnd, NativeMethods.WM_GETTEXT, (IntPtr)str.Capacity, str);
  987. // We don't try to decifer between a zero length string and an error
  988. return str.ToString();
  989. }
  990. // wrapper for GetTitleBarInfo
  991. internal static bool ProxyGetTitleBarInfo(IntPtr hwnd, out UnsafeNativeMethods.TITLEBARINFO ti)
  992. {
  993. ti = new UnsafeNativeMethods.TITLEBARINFO();
  994. ti.cbSize = Marshal.SizeOf(ti.GetType());
  995. bool result = UnsafeNativeMethods.GetTitleBarInfo(hwnd, ref ti);
  996. int lastWin32Error = Marshal.GetLastWin32Error();
  997. if (!result)
  998. {
  999. ThrowWin32ExceptionsIfError(lastWin32Error);
  1000. return false;
  1001. }
  1002. return true;
  1003. }
  1004. internal static bool ProxyGetTitleBarInfoEx(IntPtr hwnd, out UnsafeNativeMethods.TITLEBARINFOEX ti)
  1005. {
  1006. ti = new UnsafeNativeMethods.TITLEBARINFOEX();
  1007. ti.cbSize = Marshal.SizeOf(ti.GetType());
  1008. IntPtr result;
  1009. IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, NativeMethods.WM_GETTITLEBARINFOEX, IntPtr.Zero, ref ti, _sendMessageFlags, _sendMessageTimeoutValue, out result);
  1010. int lastWin32Error = Marshal.GetLastWin32Error();
  1011. if (resultSendMessage == IntPtr.Zero)
  1012. {
  1013. //Window owner failed to process the message WM_GETTITLEBARINFOEX
  1014. EvaluateSendMessageTimeoutError(lastWin32Error);
  1015. }
  1016. return true;
  1017. }
  1018. // Return the bounding rects for titlebar items or null if they are invisible or offscreen
  1019. internal static Rect [] GetTitlebarRects(IntPtr hwnd)
  1020. {
  1021. // Vista and beyond
  1022. if (System.Environment.OSVersion.Version.Major >= 6)
  1023. {
  1024. return GetTitlebarRectsEx(hwnd);
  1025. }
  1026. // Up through XP
  1027. return GetTitlebarRectsXP(hwnd);
  1028. }
  1029. internal static Rect GetTitleBarRect(IntPtr hwnd)
  1030. {
  1031. UnsafeNativeMethods.TITLEBARINFO ti;
  1032. if (!Misc.ProxyGetTitleBarInfo(hwnd, out ti) || ti.rcTitleBar.IsEmpty)
  1033. {
  1034. return Rect.Empty;
  1035. }
  1036. NativeMethods.MENUBARINFO mbi;
  1037. bool retValue = WindowsMenu.GetMenuBarInfo(hwnd, NativeMethods.OBJID_SYSMENU, 0, out mbi);
  1038. int left = 0;
  1039. int right = 0;
  1040. if(Misc.IsControlRTL(hwnd))
  1041. {
  1042. // Possible that there is no menu
  1043. left = ti.rcTitleBar.left;
  1044. right = (!retValue || mbi.rcBar.IsEmpty) ? ti.rcTitleBar.right : mbi.rcBar.right;
  1045. }
  1046. else
  1047. {
  1048. // Possible that there is no menu
  1049. left = (!retValue || mbi.rcBar.IsEmpty) ? ti.rcTitleBar.left : mbi.rcBar.left;
  1050. right = ti.rcTitleBar.right;
  1051. }
  1052. return new Rect(left, ti.rcTitleBar.top, right - left, ti.rcTitleBar.bottom - ti.rcTitleBar.top);
  1053. }
  1054. internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
  1055. {
  1056. IntPtr result;
  1057. IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, wParam, lParam, _sendMessageFlags, _sendMessageTimeoutValue, out result);
  1058. int lastWin32Error = Marshal.GetLastWin32Error();
  1059. if (resultSendMessage == IntPtr.Zero)
  1060. {
  1061. EvaluateSendMessageTimeoutError(lastWin32Error);
  1062. }
  1063. return result;
  1064. }
  1065. // On a 64-bit platform, the value of the IntPtr is too large to represent as a 32-bit signed integer.
  1066. // An int is a System.Int32. When an explicit cast of IntPtr to int is done on a 64-bit platform an
  1067. // OverflowException will occur when the IntPtr value exceeds the range of int. In cases where using
  1068. // SendMessage to get back int (e.g. an item index or an enum value), this version safely truncates
  1069. // from IntPtr to int.
  1070. internal static int ProxySendMessageInt(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
  1071. {
  1072. IntPtr result = ProxySendMessage(hwnd, msg, wParam, lParam);
  1073. return unchecked((int)(long)result);
  1074. }
  1075. // Same as above but does not throw on timeout
  1076. // @
  1077. internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool ignoreTimeout)
  1078. {
  1079. In