Skip to content

Instantly share code, notes, and snippets.

@juntalis
Created February 2, 2013 18:14
Show Gist options
  • Select an option

  • Save juntalis/4698654 to your computer and use it in GitHub Desktop.

Select an option

Save juntalis/4698654 to your computer and use it in GitHub Desktop.
Pinvokes and whatnot
#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