I'm trying to get the name of the current focused window. Thanks to my research, I have this code :
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
private static bool IsFocused(string name)
{
StringBuilder buffer = new StringBuilder(256);
if (GetWindowText(GetForegroundWindow(), buffer, buffer.Length + 1) > 0)
{
if (buffer.ToString() == name)
{
return true;
}
}
return false;
}
I've checked, the handle returned by GetForegoundWindow() is the correct one. But GetWindowText() always returns a null or negative value.
You need to get the length of the text
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern int GetWindowTextLength(IntPtr hWnd);
private static bool IsFocused(string name)
{
var handle = GetForegroundWindow();
var length = GetWindowTextLength(handle);
var builder = new StringBuilder(length + 1);
GetWindowText(handle, builder, builder.Capacity);
return builder.ToString() == name;
}
Related
Here's the code I'm using:
private void Button_Click(object sender, RoutedEventArgs e) {
SendMessage(GetDesktopWindow(), LVM_ARRANGE, LVA_SNAPTOGRID, 0);
}
public const uint LVM_ARRANGE = 0x1000 + 22;
public const int LVA_SNAPTOGRID = 0x0005;
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
Nothing happens when I run it. Code is borrowed from https://www.codeproject.com/Messages/1168961/Re-Auto-Arrange-desktop-icons.aspx
Tried different Windows versions too.
This code worked for me. Note that it doesn't appear to change the options, so although it arranges to the grid for me the View->Align Icons To Grid is still unchecked. The issue is outlined here: How do I get the window handle of the desktop?
Your problem results from a fairly widespread confusion over what the
desktop window actually is. The GetDesktopWindow function does
precisely what it's documented to do: it returns a handle to the
desktop window. This, however, is not the same window that contains
the desktop icons.
So I used the answer here: Get handle to desktop / shell window but with replacing or adding methods and p/invoke calls until I had everything necessary because that link only gives method calls and not the dll imports (I may have left some superfluous stuff in here).
static void Main()
{
SendMessage(GetDesktopWindow(DesktopWindow.SysListView32), LVM_ARRANGE, LVA_SNAPTOGRID, 0);
Console.ReadLine();
}
public const int LVM_ARRANGE = 4118;
public const int LVA_SNAPTOGRID = 5;
[DllImport("user32.dll")]
static extern IntPtr GetShellWindow();
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowTextLength(IntPtr hWnd);
public enum DesktopWindow
{
ProgMan,
SHELLDLL_DefViewParent,
SHELLDLL_DefView,
SysListView32
}
public static IntPtr GetDesktopWindow(DesktopWindow desktopWindow)
{
IntPtr _ProgMan = GetShellWindow();
IntPtr _SHELLDLL_DefViewParent = _ProgMan;
IntPtr _SHELLDLL_DefView = FindWindowEx(_ProgMan, IntPtr.Zero, "SHELLDLL_DefView", null);
IntPtr _SysListView32 = FindWindowEx(_SHELLDLL_DefView, IntPtr.Zero, "SysListView32", "FolderView");
if (_SHELLDLL_DefView == IntPtr.Zero)
{
EnumWindows((hwnd, lParam) =>
{
if (GetWindowText(hwnd) == "WorkerW")
{
IntPtr child = FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", null);
if (child != IntPtr.Zero)
{
_SHELLDLL_DefViewParent = hwnd;
_SHELLDLL_DefView = child;
_SysListView32 = FindWindowEx(child, IntPtr.Zero, "SysListView32", "FolderView"); ;
return false;
}
}
return true;
}, IntPtr.Zero);
}
switch (desktopWindow)
{
case DesktopWindow.ProgMan:
return _ProgMan;
case DesktopWindow.SHELLDLL_DefViewParent:
return _SHELLDLL_DefViewParent;
case DesktopWindow.SHELLDLL_DefView:
return _SHELLDLL_DefView;
case DesktopWindow.SysListView32:
return _SysListView32;
default:
return IntPtr.Zero;
}
}
public static string GetWindowText(IntPtr hWnd)
{
int size = GetWindowTextLength(hWnd);
if (size > 0)
{
var builder = new StringBuilder(size + 1);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
return String.Empty;
}
I am trying to get a list of all the open IE tab titles or search for a specific tab title.
I've been using this but does not work for every tab for some reason:
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
IntPtr explorerHandle = FindWindow("IEFrame", "Google - Internet Explorer");
// Verify that we found the Window.
if (explorerHandle == IntPtr.Zero)
{
MessageBox.Show("Didn't find an instance of IE");
return;
}
I am particularly looking for tabs which have "This page can’t be displayed" in the title.
Any suggestions?
The last time I needed to do something like that I used this code: (It's working !)
[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static public extern IntPtr GetClassName(IntPtr hWnd, System.Text.StringBuilder lpClassName, int nMaxCount);
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
list.Add(handle);
return true;
}
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
Win32Callback childProc = new Win32Callback(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
public static string GetWinClass(IntPtr hwnd)
{
if (hwnd == IntPtr.Zero)
return null;
StringBuilder classname = new StringBuilder(100);
IntPtr result = GetClassName(hwnd, classname, classname.Capacity);
if (result != IntPtr.Zero)
return classname.ToString();
return null;
}
public static IEnumerable<IntPtr> EnumAllWindows(IntPtr hwnd, string childClassName)
{
List<IntPtr> children = GetChildWindows(hwnd);
if (children == null)
yield break;
foreach (IntPtr child in children)
{
if (GetWinClass(child) == childClassName)
yield return child;
foreach (var childchild in EnumAllWindows(child, childClassName))
yield return childchild;
}
}
And to use it :
IntPtr handle = FindWindow("IEFrame", "Google");
var hwndChilds = EnumAllWindows(handle, "Frame Tab");
hwndChilds is a list of IntPtr to all of Frame Tab.
EDIT :
I complete my answer with the next steps to get the title of your tabs.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [Out] StringBuilder lParam);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetParent(IntPtr hWnd);
public static string GetWindowTextRaw(IntPtr hwnd)
{
uint WM_GETTEXT = 0x000D;
uint WM_GETTEXTLENGTH = 0x000E;
// Allocate correct string length first
int length = (int)SendMessage(hwnd, WM_GETTEXTLENGTH, IntPtr.Zero, null);
StringBuilder sb = new StringBuilder(length + 1);
SendMessage(hwnd, WM_GETTEXT, (IntPtr)sb.Capacity, sb);
return sb.ToString();
}
You can test it with :
static void Main(string[] args)
{
IntPtr handle = FindWindow("IEFrame", "Google");
var hwndChild = EnumAllWindows(handle, "Frame Tab");
foreach (var intPtr in hwndChild)
{
var ptr = GetParent(intPtr);
var text = GetWindowTextRaw(ptr);
Console.WriteLine(text);
}
Console.ReadLine();
}
and the result :
If you need more explanations don't hesitate to ask.
You can find all pInvoke signatures on http://www.pinvoke.net/
Have a great day !
I'd like to check, if any screen hosts application in fullscreen mode. I have solution only for one screen which is code copied from here: [WPF] [C#] How-to : Detect if another application is running in full screen mode. This solution is based on
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
which gathers only active window handle. The problem is, I have two screens. I've searched many sites but none of them answers my question. It is not about capturing screenshot, which is simple and doesn't rely on P/Invoke.
Is this possible?
No ready-to-use solution here, but let's see..
Get list of all displayed windows and check positions and sizes of those windows - possible, lots of tools does it, many articles on that, I'll skip this one. Then, you can call MonitorFromWindow for each or some windows and compare window dimensions&position against monitor info. If windowpos ~= 0,0 and windowsize ~= monitorresolution you could assume that this window is in fullscreen mode.
On the other hand, if already having a list of all HWNDs, then why not just Query the window for its placement and check the WINDOWPLACEMENT.showCmd for SW_MAXIMIZE/SW_SHOWMAXIMIZED flags. That won't tell you which monitor is it, but should tell you at least if the window is maximized and if it's enough for you..
I don't know how fast/slow would it be to do it like that, but, yes, it seems possible.
You could use EnumWindows in conjunction with Screen.FromHandle. And maybe GetWindowRect() for calculations.
Something like (pseudo-code!):
//------------------------------
//this sample code is taken from http://pinvoke.net/default.aspx/user32/EnumWindows.html
public delegate bool EnumedWindow(IntPtr handleWindow, ArrayList handles);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindows(EnumedWindow lpEnumFunc, ArrayList lParam);
public static ArrayList GetWindows()
{
ArrayList windowHandles = new ArrayList();
EnumedWindow callBackPtr = GetWindowHandle;
EnumWindows(callBackPtr, windowHandles);
return windowHandles;
}
private static bool GetWindowHandle(IntPtr windowHandle, ArrayList windowHandles)
{
windowHandles.Add(windowHandle);
return true;
}
//------------------------------
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, [In,Out] ref Rect rect);
[StructLayout(LayoutKind.Sequential)]
private struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
static void Main() {
foreach(IntPtr handle in GetWindows())
{
Screen scr = Screen.FromHandle(handle);
if(IsFullscreen(handle, scr))
{
// the window is fullscreen...
}
}
}
private bool IsFullscreen(IntPtr wndHandle, Screen screen)
{
Rect r = new Rect();
GetWindowRect(wndHandle, ref r);
return new Rectangle(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top)
.Contains(screen.Bounds);
}
I wrote piece of code which is working:
namespace EnumWnd
{
using System;
using System.Runtime.InteropServices;
using System.Text;
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal struct MonitorInfoEx
{
public int cbSize;
public Rect rcMonitor;
public Rect rcWork;
public UInt32 dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szDeviceName;
}
internal class Program
{
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
protected static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport("user32.dll")]
protected static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("User32")]
public static extern IntPtr MonitorFromWindow(IntPtr hWnd, int dwFlags);
[DllImport("user32", EntryPoint = "GetMonitorInfo", CharSet = CharSet.Auto,
SetLastError = true)]
internal static extern bool GetMonitorInfoEx(IntPtr hMonitor, ref MonitorInfoEx lpmi);
protected static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
{
const int MONITOR_DEFAULTTOPRIMARY = 1;
var mi = new MonitorInfoEx();
mi.cbSize = Marshal.SizeOf(mi);
GetMonitorInfoEx(MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY), ref mi);
Rect appBounds;
GetWindowRect(hWnd, out appBounds);
int size = GetWindowTextLength(hWnd);
if (size++ > 0 && IsWindowVisible(hWnd))
{
var sb = new StringBuilder(size);
GetWindowText(hWnd, sb, size);
if (sb.Length > 20)
{
sb.Remove(20, sb.Length - 20);
}
int windowHeight = appBounds.Right - appBounds.Left;
int windowWidth = appBounds.Bottom - appBounds.Top;
int monitorHeight = mi.rcMonitor.Right - mi.rcMonitor.Left;
int monitorWidth = mi.rcMonitor.Bottom - mi.rcMonitor.Top;
bool fullScreen = (windowHeight == monitorHeight) && (windowWidth == monitorWidth);
sb.AppendFormat(" Wnd:({0} | {1}) Mtr:({2} | {3} | Name: {4}) - {5}", windowWidth, windowHeight, monitorWidth, monitorHeight, mi.szDeviceName, fullScreen);
Console.WriteLine(sb.ToString());
}
return true;
}
private static void Main()
{
while (true)
{
EnumWindows(EnumTheWindows, IntPtr.Zero);
Console.ReadKey();
Console.Clear();
}
}
protected delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
}
}
Thanks for #SamAxe and #quetzalcoatl for providing me useful tips.
I need to check what window the user currently has selected, and do stuff if they have a specific program selected.
I haven't used the GetForegroundWindow function before, and can't find any information on how to use it in this manner.
I simply need an if comparing the current window to see if its a specific program. However the GetForegroundWindow function doesn't give back a string or int it seems. So mainly I don't know how to find out the value of the program window I want to compare it to.
I currently have the code to get the current window:
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
IntPtr selectedWindow = GetForegroundWindow();
I need to be able to apply it as follows ideally:
If (selectedWindow!="SpecificProgram")
{
<Do this stuff>
}
I'm hoping the GetForegroundWindow value/object is unique to each program and doesn't function in some way that each specific program/window has different values each-time.
I'm also doing this as part of a windows form though I doubt it matters.
-Thanks for any help
Edit: This way works, and uses the tile of the current window, which makes it perfect for checking if the window is right easily:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
private string GetActiveWindowTitle()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
return Buff.ToString();
}
return null;
}
and then I can just do:
if (GetActiveWindowTitle()=="Name of Window")
{
DoStuff.jpg
}
It has some code but it works:
#region Retrieve list of windows
[DllImport("user32")]
private static extern int GetWindowLongA(IntPtr hWnd, int index);
[DllImport("USER32.DLL")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("USER32.DLL")]
private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
private const int GWL_STYLE = -16;
private const ulong WS_VISIBLE = 0x10000000L;
private const ulong WS_BORDER = 0x00800000L;
private const ulong TARGETWINDOW = WS_BORDER | WS_VISIBLE;
internal class Window
{
public string Title;
public IntPtr Handle;
public override string ToString()
{
return Title;
}
}
private List<Window> windows;
private void GetWindows()
{
windows = new List<Window>();
EnumWindows(Callback, 0);
}
private bool Callback(IntPtr hwnd, int lParam)
{
if (this.Handle != hwnd && (GetWindowLongA(hwnd, GWL_STYLE) & TARGETWINDOW) == TARGETWINDOW)
{
StringBuilder sb = new StringBuilder(100);
GetWindowText(hwnd, sb, sb.Capacity);
Window t = new Window();
t.Handle = hwnd;
t.Title = sb.ToString();
windows.Add(t);
}
return true; //continue enumeration
}
#endregion
And to check user window:
IntPtr selectedWindow = GetForegroundWindow();
GetWindows();
for (i = 0; i < windows.Count; i++)
{
if(selectedWindow == windows[i].Handle && windows[i].Title == "Program Title X")
{
//Do stuff
break;
}
}
Valter
When left single click on the clock in the taskbar on Windows 7 (maybe Vista too) a popup opens showing calender and clock(s) (thus not the date and time adjust window). How do I open this window myself (preferred in C#)?
I was hoping timedate.cpl would call this, but this opens the date and time adjust window.
To show the clock you need to send the appropriate window message to the tray window. This can be done using the Windows API function SendMessage:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
class ShowCalendar
{
private delegate bool EnumChildCallback(IntPtr hwnd,
ref IntPtr lParam);
[DllImport("User32.dll")]
private static extern bool EnumChildWindows(IntPtr hWndParent,
EnumChildCallback lpEnumFunc,
ref IntPtr lParam);
[DllImport("User32.dll")]
private static extern int GetClassName(IntPtr hWnd,
StringBuilder lpClassName,
int nMaxCount);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd,
UInt32 Msg,
IntPtr wParam,
IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent,
IntPtr hwndChildAfter,
string lpszClass,
string lpszWindow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd,
out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private static readonly string TrayWndClassName = "Shell_TrayWnd";
private static readonly string TrayNotifyWndClassName = "TrayNotifyWnd";
private static readonly string ClockWndClassName = "TrayClockWClass";
private static readonly uint WM_NCLBUTTONDOWN = 0x00A1;
private static readonly uint HTCAPTION = 2;
private static bool EnumChildProc(IntPtr hwndChild, ref IntPtr lParam)
{
StringBuilder className = new StringBuilder(128);
GetClassName(hwndChild, className, 128);
if (className.ToString() == ClockWndClassName)
{
lParam = hwndChild;
return false;
}
return true;
}
static void Main(string[] args)
{
IntPtr hWndTray = FindWindow(TrayWndClassName, string.Empty);
if (hWndTray == IntPtr.Zero)
{
throw new Win32Exception();
}
IntPtr hWndTrayNotify = FindWindowEx(hWndTray,
IntPtr.Zero,
TrayNotifyWndClassName,
string.Empty);
if (hWndTrayNotify == IntPtr.Zero)
{
throw new Win32Exception();
}
// search clock window
EnumChildCallback cb = new EnumChildCallback(EnumChildProc);
IntPtr hWndClock = IntPtr.Zero;
EnumChildWindows(hWndTray, cb, ref hWndClock);
if (hWndClock == IntPtr.Zero)
{
throw new Win32Exception();
}
// get clock window position
RECT rect;
if (!GetWindowRect(hWndClock, out rect))
{
throw new Win32Exception();
}
// send click, lParam contains window position
IntPtr wParam = new IntPtr(HTCAPTION);
IntPtr lParam = new IntPtr(rect.Top << 16 | rect.Left);
SendMessage(hWndTray, WM_NCLBUTTONDOWN, wParam, lParam);
}
}