/// <summary> /// Finds the specified control in a list of controls. /// Returns 0-based index, or -1 if not found. /// The <see cref="Result"/> property will be the control. /// </summary> /// <param name="a">List of controls, for example returned by <see cref="GetWnd.Children"/>.</param> /// <param name="wParent">Direct or indirect parent window. Used only for flag DirectChild.</param> public int FindInList(IEnumerable <AWnd> a, AWnd wParent = default) { using var k = new _WndList(a); return(_FindInList(wParent, k)); }
/// <summary> /// Finds all matching child controls, like <see cref="ChildAll"/>. /// Returns array containing 0 or more control handles as AWnd. /// </summary> /// <param name="wParent">Direct or indirect parent window. Can be top-level window or control.</param> /// <exception cref="AuWndException">Invalid wParent.</exception> public AWnd[] FindAll(AWnd wParent) { return(_FindAll(new _WndList(_AllChildren(wParent)), wParent)); }
public void Clear() { wFocus = default; }
/// <summary> /// Sets the value of the progress indicator displayed on the taskbar button. /// Calls <msdn>ITaskbarList3.SetProgressValue</msdn>. /// </summary> /// <param name="w">Button's window.</param> /// <param name="progressValue">Progress indicator value, 0 to progressTotal.</param> /// <param name="progressTotal">Max progress indicator value.</param> public static void SetProgressValue(AWnd w, int progressValue, int progressTotal = 100) { _TaskbarButton.taskbarInstance.SetProgressValue(w, progressValue, progressTotal); }
/// <summary> /// Finds accessible object (AO) in window w. /// The same as <see cref="Find(AWnd)"/>, but waits until the AO is found or the given time expires. /// </summary> /// <param name="secondsTimeout">Timeout, seconds. Can be 0 (infinite), >0 (exception) or <0 (no exception). More info: [](xref:wait_timeout).</param> /// <param name="w">Window or control that contains the AO.</param> /// <returns>Returns true. On timeout returns false if <i>secondsTimeout</i> is negative; else exception.</returns> /// <exception cref="TimeoutException"><i>secondsTimeout</i> time has expired (if > 0).</exception> /// <exception cref="Exception">Exceptions of <see cref="Find(AWnd)"/>.</exception> public bool Wait(double secondsTimeout, AWnd w) { return(_FindOrWait(w, secondsTimeout, true)); }
public _OwnerControl(AWnd control, ITBOwnerObject ioo) { c = control; oo = ioo; }
/// <summary> /// Sets font. /// </summary> /// <param name="w"></param> /// <param name="font">Native font handle. If default(IntPtr), sets font that is used by most windows and controls on this computer. Usually it is Segoe UI, 9.</param> /// <remarks> /// Sends <msdn>WM_SETFONT</msdn> message. /// </remarks> public static void SetFont(AWnd w, IntPtr font = default) { w.Send(Api.WM_SETFONT, font != default ? font : Util.NativeFont_.RegularCached.Handle); }
//FUTURE: test when this process is not DPI-aware: // Coordinate-related API on Win7 high DPI. // AO location on Win10 with different DPI of monitors. /// <summary> /// Gets visible top-level window or control from point. /// </summary> /// <param name="p"> /// Coordinates. /// Tip: To specify coordinates relative to the right, bottom, work area or a non-primary screen, use <see cref="Coord.Normalize"/>, like in the example. /// </param> /// <param name="flags"></param> /// <remarks> /// Alternatively can be used API <msdn>WindowFromPoint</msdn>, <msdn>ChildWindowFromPointEx</msdn> or <msdn>RealChildWindowFromPoint</msdn>, but all they have various limitations and are not very useful in automation scripts. /// This function gets non-transparent controls that are behind (in the Z order) transparent controls (group button, tab control etc); supports more control types than <msdn>RealChildWindowFromPoint</msdn>. Also does not skip disabled controls. All this is not true with flag Raw. /// This function is not very fast, probably 0.3 - 1 ms. /// </remarks> /// <example> /// Find window at 100 200. /// <code><![CDATA[ /// var w = AWnd.FromXY((100, 200), WXYFlags.NeedWindow); /// AOutput.Write(w); /// ]]></code> /// /// Find window or control at 50 from left and 100 from bottom of the work area. /// <code><![CDATA[ /// var w = AWnd.FromXY(Coord.Normalize(50, Coord.Reverse(100), true)); /// AOutput.Write(w); /// ]]></code> /// </example> public static AWnd FromXY(POINT p, WXYFlags flags = 0) { bool needW = 0 != (flags & WXYFlags.NeedWindow); bool needC = 0 != (flags & WXYFlags.NeedControl); if (needW && needC) { throw new ArgumentException("", "flags"); } AWnd w; if (needW) { w = Api.RealChildWindowFromPoint(Api.GetDesktopWindow(), p); //much faster than WindowFromPoint if (!w.HasExStyle(WS2.TRANSPARENT | WS2.LAYERED)) { return(w); //fast. Windows that have both these styles are mouse-transparent. } return(Api.WindowFromPoint(p).Window); //ChildWindowFromPointEx would be faster, but less reliable //info: //WindowFromPoint is the most reliable. It skips really transparent top-level windows (TL). Unfortunately it skips disabled controls (but not TL). //ChildWindowFromPointEx with CWP_SKIPINVISIBLE|CWP_SKIPTRANSPARENT skips all with WS_EX_TRANSPARENT, although without WS_EX_LAYERED they aren't actually transparent. //RealChildWindowFromPoint does not skip transparent TL. It works like ChildWindowFromPointEx(CWP_SKIPINVISIBLE). //None of the above API prefers a really visible control that is under a transparent part of a sibling control. RealChildWindowFromPoint does it only for group buttons, but not for tab controls etc. //All API skip windows that have a hole etc in window region at that point. //None of the API uses WM_NCHITTEST+HTTRANSPARENT. Tested only with TL of other processes. //AccessibleObjectFromPoint.get_Parent in most cases gets the most correct window/control, but it is dirty, unreliable and often very slow, because sends WM_GETOBJECT etc. //speed: //RealChildWindowFromPoint is the fastest. //ChildWindowFromPointEx is slower. //WindowFromPoint is 4 times slower; .Window does not make significantly slower. //AccessibleObjectFromPoint.get_Parent often is of RealChildWindowFromPoint speed, but often much slower than all others. //IUIAutomation.FromPoint very slow. Getting window handle from it is not easy, > 0.5 ms. } w = Api.WindowFromPoint(p); if (w.Is0) { return(w); } if (0 != (flags & WXYFlags.Raw)) { if (needW) { w = w.Window; } else if (needC && w == w.Window) { w = default; } return(w); } AWnd t = w.Get.DirectParent; //need parent because need to call realchildwindowfrompoint on it, else for group box would go through the slow way of detecting transparen control if (!t.Is0) { w = t; } t = w._ChildFromXY(p, false, true); if (t.Is0) { t = w; } if (needC && t == w) { return(default);
/// <summary> /// Creates native/unmanaged window. /// </summary> /// <exception cref="AuException">Failed to create window. Unlikely.</exception> /// <remarks> /// Calls API <msdn>CreateWindowEx</msdn>. /// Later call <see cref="DestroyWindow"/> or <see cref="Close"/>. /// </remarks> /// <seealso cref="RegisterWindowClass"/> public static AWnd CreateWindow(string className, string name = null, WS style = 0, WS2 exStyle = 0, int x = 0, int y = 0, int width = 0, int height = 0, AWnd parent = default, LPARAM controlId = default, IntPtr hInstance = default, LPARAM param = default) { var w = Api.CreateWindowEx(exStyle, className, name, style, x, y, width, height, parent, controlId, hInstance, param); if (w.Is0) { throw new AuException(0); } return(w); }
/// <summary> /// Destroys a native window of this thread. /// Calls API <msdn>DestroyWindow</msdn>. /// Returns false if failed. Supports <see cref="ALastError"/>. /// </summary> /// <seealso cref="Close"/> public static bool DestroyWindow(AWnd w) { return(Api.DestroyWindow(w)); }
/// <summary> /// Creates native/unmanaged window of a class registered with <see cref="RegisterWindowClass"/> with null <i>wndProc</i>, and sets its window procedure. /// </summary> /// <exception cref="ArgumentException">The class is not registered with <see cref="RegisterWindowClass"/>, or registered with non-null <i>wndProc</i>.</exception> /// <exception cref="AuException">Failed to create window. Unlikely.</exception> /// <remarks> /// Calls API <msdn>CreateWindowEx</msdn>. /// Protects the <i>wndProc</i> delegate from GC. /// Later call <see cref="DestroyWindow"/> or <see cref="Close"/>. /// </remarks> public static AWnd CreateWindow(Native.WNDPROC wndProc, string className, string name = null, WS style = 0, WS2 exStyle = 0, int x = 0, int y = 0, int width = 0, int height = 0, AWnd parent = default, LPARAM controlId = default, IntPtr hInstance = default, LPARAM param = default) { var a = t_windows ??= new List <(AWnd w, Native.WNDPROC p)>(); for (int i = a.Count; --i >= 0;) { if (!a[i].w.IsAlive) { a.RemoveAt(i); } } lock (s_classes) { if (!s_classes.TryGetValue(className, out var wp) || wp != null) { throw new ArgumentException("Window class must be registered with RegisterWindowClass with null wndProc"); } } AWnd w; //need to cubclass the new window. But not after CreateWindowEx, because wndProc must receive all messages. #if CW_CBT //slightly slower and dirtier. Invented before Core, to support multiple appdomains. using (AHookWin.ThreadCbt(c => { //let CBT hook subclass before any messages if (c.code == HookData.CbtEvent.CREATEWND) { //note: unhook as soon as possible. Else possible exception etc. // If eg hook proc uses 'lock' and that 'lock' must wait, // our hook proc is called again and again while waiting, until 'lock' throws exception. // In STA thread 'lock' dispatches messages, but I don't know why hook proc is called multiple times for same event. c.hook.Unhook(); var ww = (AWnd)c.wParam; Debug.Assert(ww.ClassNameIs(className)); ww.SetWindowLong(Native.GWL.WNDPROC, Marshal.GetFunctionPointerForDelegate(wndProc)); } else { Debug.Assert(false); } return(false); })) { w = Api.CreateWindowEx(exStyle, className, name, style, x, y, width, height, parent, controlId, hInstance, param); } #else t_cwProc = wndProc; //let _DefWndProc subclass on first message try { w = Api.CreateWindowEx(exStyle, className, name, style, x, y, width, height, parent, controlId, hInstance, param); } finally { t_cwProc = null; } //if CreateWindowEx failed and _CWProc not called #endif if (w.Is0) { throw new AuException(0); } a.Add((w, wndProc)); return(w); }
/// <summary> /// Deletes taskbar button. /// Calls <msdn>ITaskbarList.DeleteTab</msdn>. /// </summary> /// <param name="w">Button's window.</param> public static void Delete(AWnd w) { _TaskbarButton.taskbarInstance.DeleteTab(w); }
/// <summary> /// Adds taskbar button. /// Calls <msdn>ITaskbarList.AddTab</msdn>. /// </summary> /// <param name="w">Button's window.</param> public static void Add(AWnd w) { _TaskbarButton.taskbarInstance.AddTab(w); //info: succeeds without HrInit(), tested on Win10 and 7. //info: always returns 0, even if w is 0. Did not test ITaskbarList3 methods. }
/// <summary> /// Finds all matching controls in a list of controls. /// Returns array containing 0 or more control handles as AWnd. /// </summary> /// <param name="a">List of controls, for example returned by <see cref="GetWnd.Children"/>.</param> /// <param name="wParent">Direct or indirect parent window. Used only for flag DirectChild.</param> public AWnd[] FindAllInList(IEnumerable <AWnd> a, AWnd wParent = default) { return(_FindAll(new _WndList(a), wParent)); }
//rejected. Rarely used. Easy to send message. ///// <summary> ///// Sets native font handle. ///// Sends message API <msdn>WM_SETFONT</msdn> with lParam 1. ///// Does not copy the font; don't dispose it while the window is alive. ///// Use this function only with windows of current process. ///// </summary> //public static void SetFontHandle(AWnd w, IntPtr fontHandle) //{ // w.Send(Api.WM_SETFONT, fontHandle, 1); //} ///// <summary> ///// Gets native font handle. ///// Sends message API <msdn>WM_GETFONT</msdn>. ///// Does not copy the font; don't need to dispose. ///// Use this function only with windows of current process. ///// </summary> //public static IntPtr GetFontHandle(AWnd w) //{ // return w.Send(Api.WM_GETFONT); //} ///// <summary> ///// Sets native icon handle. ///// Sends message API <msdn>WM_SETICON</msdn>. ///// Does not copy the icon; don't dispose it while the window is alive. ///// Use this function only with windows of current process. ///// </summary> ///// <seealso cref="AIcon"/> //public static void SetIconHandle(AWnd w, IntPtr iconHandle, bool size32 = false) //{ // w.Send(Api.WM_SETICON, size32, iconHandle); //} /// <summary> /// Calls API <msdn>GetClassLongPtr</msdn>. /// </summary> /// <remarks> /// Supports <see cref="ALastError"/>. /// For index can be used constants from <see cref="Native.GCL"/>. All values are the same in 32-bit and 64-bit process. /// In 32-bit process actually calls <b>GetClassLong</b>, because <b>GetClassLongPtr</b> is unavailable. /// </remarks> public static LPARAM GetClassLong(AWnd w, int index) => Api.GetClassLongPtr(w, index);
/// <summary> /// Returns index of matching element or -1. /// Returns -1 if using getAll. /// </summary> /// <param name="wParent">Parent window. Can be default(AWnd) if inList is true and no DirectChild flag and not using winforms name.</param> /// <param name="a">List of AWnd. Does not dispose it.</param> /// <param name="getAll">If not null, calls it for all matching and returns -1.</param> int _FindInList(AWnd wParent, _WndList a, Action <AWnd> getAll = null) { Result = default; if (a.Type == _WndList.ListType.None) { return(-1); } bool inList = a.Type != _WndList.ListType.ArrayBuilder; int skipCount = _skipCount; try { //will need to dispose something for (int index = 0; a.Next(out AWnd w); index++) { if (w.Is0) { continue; } if (inList) //else the enum function did this { if (!_flags.Has(WCFlags.HiddenToo)) { if (!w.IsVisibleIn_(wParent)) { continue; } } if (_flags.Has(WCFlags.DirectChild) && !wParent.Is0) { if (w.ParentGWL_ != wParent) { continue; } } } if (_nameIs == _NameIs.id) { if (w.ControlId != _id) { continue; } } if (_className != null) { if (!_className.Match(w.ClassName)) { continue; } } if (_name != null) { string s; switch (_nameIs) { case _NameIs.text: s = w.ControlText; break; //case _NameIs.label: // s = w.NameLabel; // break; case _NameIs.accName: s = w.NameAcc; break; case _NameIs.wfName: if (_wfControls == null) { try { _wfControls = new AWinFormsControlNames(wParent.Is0 ? w : wParent); } catch (AuWndException) { //invalid parent window return(-1); } catch (AuException e) { //probably process of higher UAC integrity level AWarning.Write($"Failed to get .NET control names. {e.Message}"); return(-1); } } s = _wfControls.GetControlName(w); break; default: Debug.Assert(_nameIs == _NameIs.name); s = w.Name; break; } if (!_name.Match(s)) { continue; } } if (_also != null && !_also(w)) { continue; } if (getAll != null) { getAll(w); continue; } if (skipCount-- > 0) { continue; } Result = w; return(index); } } finally { if (_wfControls != null) { _wfControls.Dispose(); _wfControls = null; } } return(-1); }
/// <summary> /// Gets window border width. /// </summary> public static int BorderWidth(AWnd w) { w.GetWindowInfo_(out var x); return(x.cxWindowBorders); }
/// <summary> /// Finds accessible object (AO) in window w, like <see cref="AAcc.Find"/>. /// Returns true if found. The <see cref="Result"/> property will be the found AO. /// </summary> /// <param name="w">Window or control that contains the AO.</param> /// <exception cref="ArgumentException"> /// - <i>role</i> is "" or invalid. /// - <i>name</i> is invalid wildcard expression (<c>"**options "</c> or regular expression). /// - <i>prop</i> has invalid format or contains unknown property names or invalid wildcard expressions. /// - flag <see cref="AFFlags.UIA"/> when searching in web page (role prefix "web:" etc). /// </exception> /// <exception cref="AuWndException">Invalid window.</exception> /// <exception cref="AuException">Failed. For example, window of a higher [](xref:uac) integrity level process.</exception> public bool Find(AWnd w) { return(_FindOrWait(w, 0, false)); }
/// <summary> /// Shows the toolbar and attaches to a window. /// </summary> /// <param name="ownerWindow">Window or control. Can belong to any process.</param> /// <param name="clientArea">Let the toolbar position be relative to the client area of the window.</param> /// <exception cref="InvalidOperationException"><b>Show</b> already called.</exception> /// <exception cref="ArgumentException"><b>ownerWindow</b> is 0.</exception> /// <remarks> /// The toolbar will be above the window in the Z order; moved when the window moved or resized; hidden when the window hidden, cloaked or minimized; destroyed when the window destroyed. /// </remarks> public void Show(AWnd ownerWindow, bool clientArea = false) { _followClientArea = clientArea; _Show(true, ownerWindow, null, default); }
bool _FindOrWait(AWnd w, double secondsTimeout, bool isWaitFunc) { w.ThrowIfInvalid(); return(_Find(w, default, secondsTimeout, isWaitFunc));
/// <summary> /// Shows the toolbar and attaches to an object in a window. /// </summary> /// <param name="ownerWindow">Window that contains the object. Can be control. Can belong to any process.</param> /// <param name="oo">A variable of a user-defined class that implements <see cref="ITBOwnerObject"/> interface. It provides object location, visibility, etc.</param> /// <exception cref="InvalidOperationException"><b>Show</b> already called.</exception> /// <exception cref="ArgumentException"><b>ownerWindow</b> is 0.</exception> /// <remarks> /// The toolbar will be above the window in the Z order; moved when the object or window moved or resized; hidden when the object or window hidden, cloaked or minimized; destroyed when the object or window destroyed. /// </remarks> public void Show(AWnd ownerWindow, ITBOwnerObject oo) => _Show(true, ownerWindow, oo, default);
//public readonly int thread; public _OwnerWindow(AWnd window) { w = window; //thread = w.ThreadId; a = new List <AToolbar>(); }
/// <summary> /// Finds the specified child control, like <see cref="AWnd.Child"/>. /// Returns true if found. /// The <see cref="Result"/> property will be the control. /// </summary> /// <param name="wParent">Direct or indirect parent window. Can be top-level window or control.</param> /// <exception cref="AuWndException">Invalid wParent.</exception> public bool Find(AWnd wParent) { using var k = new _WndList(_AllChildren(wParent)); return(_FindInList(wParent, k) >= 0); }
/// public GetWnd(AWnd wThis) => _w = wThis;
/// <summary> /// Sets the state of the progress indicator displayed on the taskbar button. /// Calls <msdn>ITaskbarList3.SetProgressState</msdn>. /// </summary> /// <param name="w">Button's window.</param> /// <param name="state">Progress indicator state and color.</param> public static void SetProgressState(AWnd w, TBProgressState state) { _TaskbarButton.taskbarInstance.SetProgressState(w, state); }