Created
February 2, 2013 18:14
-
-
Save juntalis/4698654 to your computer and use it in GitHub Desktop.
Pinvokes and whatnot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #region Imports | |
| using System; | |
| using System.ComponentModel; | |
| using System.Diagnostics; | |
| using System.Runtime.InteropServices; | |
| using System.Text; | |
| using TickTock.Interop.Properties; | |
| #endregion | |
| #region "Typedefs" | |
| using DWORD = System.UInt32; | |
| using HWND = System.IntPtr; | |
| using System.Threading; | |
| #endregion "Typedefs" | |
| namespace TickTock.Interop.Win32 | |
| { | |
| /// <summary> | |
| /// Managed implementation of the native <see cref="LASTINPUTINFO"/> | |
| /// <see langword="struct"/> . | |
| /// </summary> | |
| internal struct LASTINPUTINFO | |
| { | |
| /// <summary> | |
| /// Get the size of the <c>struct</c>. | |
| /// </summary> | |
| public static readonly DWORD SizeOf = (DWORD)Marshal.SizeOf(typeof(LASTINPUTINFO)); | |
| /// <summary> | |
| /// Must be set to the value of <see cref="SizeOf"/> | |
| /// </summary> | |
| [MarshalAs(UnmanagedType.U4)] | |
| public DWORD cbSize; | |
| /// <summary> | |
| /// Set by <see cref="User32.GetLastInputInfo"/>. Contains the time of the last input | |
| /// event from the current user session. | |
| /// </summary> | |
| [MarshalAs(UnmanagedType.U4)] | |
| public DWORD dwTime; | |
| } | |
| /// <summary> | |
| /// Represents some general information about a given window. | |
| /// </summary> | |
| public struct WindowInfo | |
| { | |
| /// <summary> | |
| /// Window title. | |
| /// </summary> | |
| public string Text { get; set; } | |
| /// <summary> | |
| /// Process ID of window. | |
| /// </summary> | |
| public int ProcessID { get; set; } | |
| /// <summary> | |
| /// Name of the window's process. | |
| /// </summary> | |
| public string ProcessName { get; set; } | |
| } | |
| /// <summary> | |
| /// </summary> | |
| public static class User32 | |
| { | |
| /// <summary> | |
| /// Managed implementation of <see cref="GetLastInputInfo"/> Win32 API. | |
| /// <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms646302(v=vs.85).aspx">See MSDN entry</a>. | |
| /// </summary> | |
| /// <param name="plii"><see cref="LASTINPUTINFO"/> Struct</param> | |
| /// <returns>Success or failure</returns> | |
| [DllImport("user32.dll")] | |
| internal static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); | |
| /// <summary> | |
| /// The GetForegroundWindow function returns a handle to the foreground window. | |
| /// <a href="http://msdn.microsoft.com/en-us/library/ms633505(v=vs.85).aspx">See MSDN entry</a>. | |
| /// </summary> | |
| /// <returns>Window HWND</returns> | |
| [DllImport("user32.dll")] | |
| internal static extern IntPtr GetForegroundWindow(); | |
| /// <summary> | |
| /// Gets window's text length. <a href="http://msdn.microsoft.com/en-us/library/ms633521(v=vs.85).aspx">See MSDN entry</a>. | |
| /// </summary> | |
| /// <param name="hWnd">Handle to the window </param> | |
| /// <returns>Text Length</returns> | |
| [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] | |
| internal static extern int GetWindowTextLength(HWND hWnd); | |
| /// <summary> | |
| /// Gets a window's title. <a href="http://msdn.microsoft.com/en-us/library/ms633520(v=vs.85).aspx">See MSDN entry</a>. | |
| /// </summary> | |
| /// <param name="hWnd">Handle to window</param> | |
| /// <param name="lpString"><see cref="String"/> buffer</param> | |
| /// <param name="nMaxCount">Max string length (From GetWindowTextLength)</param> | |
| /// <returns></returns> | |
| [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
| internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); | |
| /// <summary> | |
| /// Retrieves a handle to the desktop window. The desktop window covers the entire screen. | |
| /// The desktop window is the area on top of which other windows are painted. | |
| /// </summary> | |
| /// <returns>Handle to window</returns> | |
| [DllImport("user32.dll", SetLastError = false)] | |
| internal static extern IntPtr GetDesktopWindow(); | |
| /// <summary> | |
| /// Holds a handle to our desktop window. (To avoid having to make multiple calls | |
| /// to <see cref="GetDesktopWindow"/>. | |
| /// </summary> | |
| internal static readonly IntPtr DesktopWindow = GetDesktopWindow(); | |
| /// <summary> | |
| /// Attempts to get a handle to the foreground window. It will make this | |
| /// attempt, calling <see cref="GetForegroundWindow"/> 3 times, sleeping for | |
| /// 100ms between iterations. If a valid handle is returned before the | |
| /// completion, we'll return that. If, however, the handle returned is NULL, | |
| /// (which occurs in certain cases), we'll loop through all 3 tries, and if | |
| /// still NULL, return <see cref="System.IntPtr.Zero"/>. | |
| /// </summary> | |
| internal static HWND ForegroundWindow | |
| { | |
| get | |
| { | |
| HWND hwnd = IntPtr.Zero; | |
| for (int i = 0; i < 3; i++){ | |
| hwnd = GetForegroundWindow(); | |
| if (hwnd != IntPtr.Zero){ | |
| return hwnd; | |
| } | |
| Thread.Sleep(100); | |
| } | |
| return hwnd; | |
| } | |
| } | |
| /// <summary> | |
| /// Given a window handle, generates a string | |
| /// containing the title text for that window. | |
| /// </summary> | |
| /// <param name="hWnd">Window handle</param> | |
| /// <returns>Window text</returns> | |
| public static string GetWindowText(HWND hWnd) | |
| { | |
| // First, check if the HWND specified is the desktop window. | |
| if (hWnd == DesktopWindow) { | |
| return "Desktop"; | |
| } | |
| int length = GetWindowTextLength(hWnd); | |
| if (length == 0){ | |
| return String.Empty; | |
| } | |
| StringBuilder sb = new StringBuilder(length + 1); | |
| return GetWindowText(hWnd, sb, sb.Capacity) == 0 ? String.Empty : sb.ToString(); | |
| } | |
| /// <summary> | |
| /// Gets the process ID and thread ID for a window. | |
| /// </summary> | |
| /// <param name="hWnd">Window handle</param> | |
| /// <param name="lpdwProcessId">Pointer to a value for the process ID</param> | |
| /// <returns>thread id</returns> | |
| [DllImport("user32.dll", SetLastError = true)] | |
| internal static extern DWORD GetWindowThreadProcessId(HWND hWnd, out DWORD lpdwProcessId); | |
| /// <summary> | |
| /// A <see langword="long"/> representing the user idle time. | |
| /// </summary> | |
| /// <exception cref="Win32Exception">If <see cref="GetLastInputInfo"/> fails, an exception is thrown.</exception> | |
| internal static long LastInputTime | |
| { | |
| get | |
| { | |
| LASTINPUTINFO lastInPut = new LASTINPUTINFO{ cbSize = LASTINPUTINFO.SizeOf }; | |
| if (!GetLastInputInfo(ref lastInPut)){ | |
| int iError = Kernel32.LastError; | |
| throw new Win32Exception( | |
| String.Format(Resources.ErrGetLastInputInfo, iError, Kernel32.ErrorMessage(iError)) | |
| ); | |
| } | |
| return (long)lastInPut.dwTime; | |
| } | |
| } | |
| /// <summary> | |
| /// Self-explanatory. | |
| /// </summary> | |
| /// <param name="hWnd">Handle of Window</param> | |
| /// <returns>PID of Window</returns> | |
| /// <exception cref="Win32Exception"></exception> | |
| internal static int GetWindowProcessId(HWND hWnd) | |
| { | |
| DWORD dwProcess = 0; | |
| if (GetWindowThreadProcessId(hWnd, out dwProcess) == 0){ | |
| throw new Win32Exception(Kernel32.LastError); | |
| } | |
| return (int)dwProcess; | |
| } | |
| /// <summary> | |
| /// Get a process name from its PID | |
| /// </summary> | |
| /// <param name="dwProcess">Process's ID</param> | |
| /// <returns>Process's Name</returns> | |
| internal static string GetProcessName(int dwProcess) | |
| { | |
| return Process.GetProcessById(dwProcess).ProcessName; | |
| } | |
| /// <summary> | |
| /// Get the process name of a window given its handle. | |
| /// </summary> | |
| /// <param name="hWnd">Window handle</param> | |
| /// <returns>Process's name</returns> | |
| internal static string GetWindowProcessName(HWND hWnd) | |
| { | |
| return GetProcessName(GetWindowProcessId(hWnd)); | |
| } | |
| /// <summary> | |
| /// Get Window information from handle. | |
| /// </summary> | |
| /// <param name="hWnd">Window handle</param> | |
| /// <exception cref="ArgumentNullException"> | |
| /// <paramref name="hWnd" /> was <see langword="null"/> | |
| /// </exception> | |
| /// <returns> | |
| /// A <see cref="WindowInfo" /> <see langword="struct" /> containing | |
| /// information on the window pointed to by our <paramref name="hWnd"/> | |
| /// parameter. | |
| /// </returns> | |
| public static WindowInfo GetWindowInfo(HWND hWnd) | |
| { | |
| if (hWnd == IntPtr.Zero){ | |
| throw new ArgumentNullException("hWnd"); | |
| } | |
| WindowInfo info = new WindowInfo(); | |
| if (hWnd == DesktopWindow){ | |
| info.ProcessName = "Desktop"; | |
| info.ProcessID = 0; // Not true, but whatever. | |
| info.Text = "Desktop"; | |
| return info; | |
| } | |
| info.ProcessID = GetWindowProcessId(hWnd); | |
| info.ProcessName = GetProcessName(info.ProcessID); | |
| info.Text = GetWindowText(hWnd); | |
| return info; | |
| } | |
| /// <summary> | |
| /// Pass-through to <see cref="Environment.TickCount" /> | |
| /// </summary> | |
| public static long TickCount | |
| { | |
| get { return Environment.TickCount; } | |
| } | |
| /// <summary> | |
| /// A <see langword="long"/> integer representing the user's idle time | |
| /// in milliseconds. | |
| /// </summary> | |
| public static long IdleTime | |
| { | |
| get { return TickCount - LastInputTime; } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment