/* Copyright (c) Citrix Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Threading; using System.Windows.Forms; namespace XenAdmin.Core { /// /// Encapsulates window functions that aren't in the framework. /// internal class Win32Window : IWin32Window { private readonly IntPtr _handle; /// /// Initializes a new instance of the class. /// /// The window handle. public Win32Window(IntPtr handle) { _handle = handle; } /// /// Extract the window handle /// public IntPtr Handle { get { return _handle; } } /// /// Posts WM_CLOSE. /// public void Close() { const int WM_CLOSE = 0x10; PostMessage(WM_CLOSE, 0, 0); } /// /// Return true if this window is null /// public bool IsNull { get { return _handle == IntPtr.Zero; } } /// /// The children of this window /// public ReadOnlyCollection Children { get { List windows = new List(); EnumChildWindows(_handle, delegate(IntPtr window, int i) { windows.Add(new Win32Window(window)); return true; }, 0); return new ReadOnlyCollection(windows); } } public ReadOnlyCollection DirectChildren { get { List windows = new List(); foreach (Win32Window w in Children) { if (w.Parent._handle.ToInt32() == _handle.ToInt32()) { windows.Add(w); } } return new ReadOnlyCollection(windows); } } /// /// Gets the first window that has the specified window text. /// /// The text that the window must have. /// The first window that has the specified window text. public static Win32Window GetWindowWithText(string text) { return GetWindowWithText(text, w => true); } /// /// Gets the first window that has the specified window text and matches the specified Predicate. /// /// The text that the window must have. /// The Predicate that the window must match. /// The first window that has the specified window text and matches the specified Predicate. public static Win32Window GetWindowWithText(string text, Predicate match) { Util.ThrowIfParameterNull(match, "match"); Thread.Sleep(100); foreach (Win32Window window in TopLevelWindows) { if (window.Text == text && match(window)) { return window; } } return null; } /// /// Gets a value indicating whether a form of the specified type is currently visible in this process. /// public static bool ModalDialogIsVisible() { int currentProcess = Process.GetCurrentProcess().Id; IntPtr mainWindowHandle = Process.GetCurrentProcess().MainWindowHandle; bool output = false; EnumWindows(delegate(IntPtr handle, int i) { Win32Window w = new Win32Window(handle); if (w.ProcessId == currentProcess) { Form f = Form.FromHandle(w.Handle) as Form; if (f != null && w.Handle != mainWindowHandle && f.GetType().Namespace.StartsWith("XenAdmin")) { output = true; return false; } } return true; }, 0); return output; } /// /// All top level windows /// public static ReadOnlyCollection TopLevelWindows { get { List windows = new List(); EnumWindows(delegate(IntPtr handle, int i) { windows.Add(new Win32Window(handle)); return true; }, 0); return new ReadOnlyCollection(windows); } } /// /// Return all windows of the current thread. /// public static ReadOnlyCollection GetThreadWindows() { return GetThreadWindows(GetCurrentThreadId()); } /// /// Return all windows of a given thread /// /// The thread id public static ReadOnlyCollection GetThreadWindows(int threadId) { List windows = new List(); EnumThreadWindows(threadId, delegate(IntPtr window, int i) { windows.Add(new Win32Window(window)); return true; }, 0); return new ReadOnlyCollection(windows); } /// /// The deskop window /// public static Win32Window DesktopWindow { get { return new Win32Window(GetDesktopWindow()); } } /// /// The current foreground window /// public static Win32Window ForegroundWindow { get { return new Win32Window(GetForegroundWindow()); } } /// /// Bring a window to the top /// public void BringWindowToTop() { BringWindowToTop(_handle); } public void SetForegroundWindow() { SetForegroundWindow(_handle); } public void OpenIcon() { OpenIcon(_handle); } /// /// Find a child of this window /// /// Name of the class, or null /// Name of the window, or null /// public Win32Window FindChild(string className, string windowName) { return new Win32Window(FindWindowEx(_handle, IntPtr.Zero, className, windowName)); } /// /// Find a window by name or class /// /// Name of the class, or null /// Name of the window, or null /// public static Win32Window FindWindow(string className, string windowName) { return new Win32Window(FindWindowEx(IntPtr.Zero, IntPtr.Zero, className, windowName)); } /// /// Tests whether one window is a child of another /// /// Parent window /// Window to test /// public static bool IsChild(Win32Window parent, Win32Window window) { return IsChild(parent._handle, window._handle); } /// /// Send a windows message to this window /// /// /// /// /// public int SendMessage(int message, int wparam, int lparam) { return SendMessage(_handle, message, wparam, lparam); } /// /// Post a windows message to this window /// /// /// /// /// public int PostMessage(int message, int wparam, int lparam) { return PostMessage(_handle, message, wparam, lparam); } /// /// Get the parent of this window. Null if this is a top-level window /// public Win32Window Parent { get { return new Win32Window(GetParent(_handle)); } } /// /// Get the last (topmost) active popup /// public Win32Window LastActivePopup { get { IntPtr popup = GetLastActivePopup(_handle); if (popup == _handle) return new Win32Window(IntPtr.Zero); else return new Win32Window(popup); } } /// /// The text in this window /// public string Text { get { int length = GetWindowTextLength(_handle); StringBuilder sb = new StringBuilder(length + 1); GetWindowText(_handle, sb, sb.Capacity); return sb.ToString(); } set { SetWindowText(_handle, value); } } public string WindowClass { get { StringBuilder sb = new StringBuilder(1000); GetClassName(_handle, sb, sb.Capacity); return sb.ToString(); } } /// /// Get a long value for this window. See GetWindowLong() /// /// /// public int GetWindowLong(int index) { return GetWindowLong(_handle, index); } /// /// Set a long value for this window. See SetWindowLong() /// /// /// /// public int SetWindowLong(int index, int value) { return SetWindowLong(_handle, index, value); } /// /// The id of the thread that owns this window /// public int ThreadId { get { return GetWindowThreadProcessId(_handle, IntPtr.Zero); } } /// /// The id of the process that owns this window /// public int ProcessId { get { int processId = 0; GetWindowThreadProcessId(_handle, ref processId); return processId; } } /// /// Whether the window is minimized /// public bool Minimized { get { return IsIconic(_handle); } set { const int SC_MINIMIZE = 0xF020; const int WM_SYSCOMMAND = 0x0112; PostMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0); } } /// /// Whether the window is maximized /// public bool Maximized { get { return IsZoomed(_handle); } } public bool MoveWindow(int X, int Y, int width, int height, bool repaint) { return MoveWindow(_handle, X, Y, width, height, repaint); } public Win32Window NextWindow { get { IntPtr h = GetNextWindow(_handle, 2); if (h == IntPtr.Zero) return null; return new Win32Window(h); } } /// /// Gets a value indicating whether there are pending message in the message queue. /// /// true if the are messages pending; otherwise, false. public bool MessagesPending { get { NativeMessage msg = new NativeMessage(); return PeekMessage(out msg, _handle, 0, 0, 0); } } /// /// Turn this window into a tool window, so it doesn't show up in the Alt-tab list... /// /// private const int GWL_EXSTYLE = -20; private const int WS_EX_TOOLWINDOW = 0x00000080; public void MakeToolWindow() { int windowStyle = GetWindowLong(GWL_EXSTYLE); SetWindowLong(GWL_EXSTYLE, windowStyle | WS_EX_TOOLWINDOW); } [DllImport("user32.dll")] private static extern bool BringWindowToTop(IntPtr window); [DllImport("user32.dll")] private static extern bool CloseWindow(IntPtr window); [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr window); [DllImport("user32.dll")] private static extern bool OpenIcon(IntPtr window); [DllImport("user32.dll")] private static extern IntPtr FindWindowEx(IntPtr parent, IntPtr childAfter, string className, string windowName); [DllImport("user32.dll", EntryPoint = "FindWindow")] private static extern IntPtr FindWindowWin32(string className, string windowName); [DllImport("user32.dll")] private static extern int SendMessage(IntPtr window, int message, int wparam, int lparam); [DllImport("user32.dll")] private static extern int PostMessage(IntPtr window, int message, int wparam, int lparam); [DllImport("user32.dll")] private static extern IntPtr GetParent(IntPtr window); [DllImport("user32.dll")] private static extern IntPtr GetDesktopWindow(); [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] private static extern IntPtr GetLastActivePopup(IntPtr window); [DllImport("user32.dll")] private static extern int GetWindowText(IntPtr window, [In][Out] StringBuilder text, int copyCount); [DllImport("user32.dll")] private static extern bool SetWindowText(IntPtr window, string text); [DllImport("user32.dll")] private static extern int GetWindowTextLength(IntPtr window); [DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr window, int index, int value); [DllImport("user32.dll")] private static extern int GetWindowLong(IntPtr window, int index); [DllImport("user32.dll")] private static extern int GetClassName(IntPtr window, [In][Out] StringBuilder text, int copyCount); private delegate bool EnumWindowsProc(IntPtr window, int i); [DllImport("user32.dll")] private static extern bool EnumChildWindows(IntPtr window, EnumWindowsProc callback, int i); [DllImport("user32.dll")] private static extern bool EnumThreadWindows(int threadId, EnumWindowsProc callback, int i); [DllImport("user32.dll")] private static extern bool EnumWindows(EnumWindowsProc callback, int i); [DllImport("user32.dll")] private static extern int GetWindowThreadProcessId(IntPtr window, ref int processId); [DllImport("user32.dll")] private static extern int GetWindowThreadProcessId(IntPtr window, IntPtr ptr); [DllImport("user32.dll")] private static extern bool IsChild(IntPtr parent, IntPtr window); [DllImport("user32.dll")] private static extern bool IsIconic(IntPtr window); [DllImport("user32.dll")] private static extern bool IsZoomed(IntPtr window); [DllImport("user32.dll")] private static extern IntPtr GetWindowDC(IntPtr hwnd); [DllImport("user32.dll")] private static extern int ReleaseDC(IntPtr hwnd, IntPtr dc); [DllImport("user32.dll")] private static extern bool MoveWindow(IntPtr hwnd, int X, int Y, int width, int height, bool repaint); [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindow", SetLastError = true)] private static extern IntPtr GetNextWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.U4)] int wFlag); [DllImport("user32.dll")] private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] private static extern int GetCurrentThreadId(); /// /// The PeekMessage function dispatches incoming sent messages, checks the thread message queue for a posted message, /// and retrieves the message (if any exist). /// /// Pointer to an MSG structure that receives message information. /// Handle to the window whose messages are to be retrieved. The window must belong to the current thread. /// Specifies the value of the first message in the range of messages to be examined. /// Specifies the value of the last message in the range of messages to be examined. /// Specifies how messages are handled. /// If a message is available, the return value is nonzero. If no messages are available, the return value is zero. [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool PeekMessage(out NativeMessage message, IntPtr handle, uint filterMin, uint filterMax, uint removeMsg); [StructLayout(LayoutKind.Sequential)] private struct NativeMessage { public IntPtr handle; public uint msg; public IntPtr wParam; public IntPtr lParam; public uint time; public System.Drawing.Point p; } } }