How do I collect all windows handlers in C#.
I need all the windows (not just the parents)
Thanks,
Try the following utility class. Given a handle to a window it will return all of the associated child windows.
public class WindowFinder
{
private class Helper
{
internal List<IntPtr> Windows = new List<IntPtr>();
internal bool ProcessWindow(IntPtr handle, IntPtr parameter)
{
Windows.Add(handle);
return true;
}
}
private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowProc lpEnumFunc, IntPtr lParam);
public static List<IntPtr> GetChildWindows(IntPtr parentWindow)
{
var helper = new Helper();
EnumChildWindows(parentWindow, helper.ProcessWindow, IntPtr.Zero);
return helper.Windows;
}
}
Related
Hi so i am trying to get a focus of application and all i could find online was the SetForegroundWindow method so i tried to implement it but its not setting the focus to the application at all, i also found some articles about it not being reliable so wanned to ask if i did it wrong or if there is a better way to inject key presses to an application, thanks!
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
private void JumpRL(object sender, EventArgs e)
{
Process[] processlist = Process.GetProcesses();
var name = processlist.Where(x => x.ProcessName == "RocketLeague").FirstOrDefault();
SetForegroundWindow(name.MainWindowHandle);
SendKeys.SendWait("{BS}");
}
the process is correct i double checked
So after long online searching i found an article with an example code of switching windows, so i said heck it and went to try and it actualy worked and it switches focus here is the snippet hope it helps
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
public static void SwitchWindow(IntPtr windowHandle)
{
if (GetForegroundWindow() == windowHandle)
return;
IntPtr foregroundWindowHandle = GetForegroundWindow();
uint currentThreadId = GetCurrentThreadId();
uint temp;
uint foregroundThreadId = GetWindowThreadProcessId(foregroundWindowHandle, out temp);
AttachThreadInput(currentThreadId, foregroundThreadId, true);
SetForegroundWindow(windowHandle);
AttachThreadInput(currentThreadId, foregroundThreadId, false);
while (GetForegroundWindow() != windowHandle)
{
}
}
after you have the focus a simple SendKeys.SendWait("<key>") works like a charm
I have the handle for a given window. How can I enumerate its child windows?
Here you have a working solution:
public class WindowHandleInfo
{
private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
private IntPtr _MainHandle;
public WindowHandleInfo(IntPtr handle)
{
this._MainHandle = handle;
}
public List<IntPtr> GetAllChildHandles()
{
List<IntPtr> childHandles = new List<IntPtr>();
GCHandle gcChildhandlesList = GCHandle.Alloc(childHandles);
IntPtr pointerChildHandlesList = GCHandle.ToIntPtr(gcChildhandlesList);
try
{
EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
EnumChildWindows(this._MainHandle, childProc, pointerChildHandlesList);
}
finally
{
gcChildhandlesList.Free();
}
return childHandles;
}
private bool EnumWindow(IntPtr hWnd, IntPtr lParam)
{
GCHandle gcChildhandlesList = GCHandle.FromIntPtr(lParam);
if (gcChildhandlesList == null || gcChildhandlesList.Target == null)
{
return false;
}
List<IntPtr> childHandles = gcChildhandlesList.Target as List<IntPtr>;
childHandles.Add(hWnd);
return true;
}
}
How to consume it:
class Program
{
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
static void Main(string[] args)
{
Process[] anotherApps = Process.GetProcessesByName("AnotherApp");
if (anotherApps.Length == 0) return;
if (anotherApps[0] != null)
{
var allChildWindows = new WindowHandleInfo(anotherApps[0].MainWindowHandle).GetAllChildHandles();
}
}
}
Using:
internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
[DllImport("user32.dll")]
internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);
you will get callbacks on the function you pass in.
I've found the best solution to be Managed WindowsAPI. It had a CrossHair control that could be used to select a window(not part of the question), and a method AllChildWindows to get all child windows which likely wrapped the EnumChildWindows function. Better not to reinvent the wheel.
Use EnumChildWindows, with p/invoke. Here's an interesting link about some of it's behavior: https://blogs.msdn.microsoft.com/oldnewthing/20070116-04/?p=28393
If you don't know the handle of the window, but only it's title, you'll need to use EnumWindows. http://pinvoke.net/default.aspx/user32/EnumWindows.html
Here is a managed alternative to EnumWindows, but you will still need to use EnumChildWindows to find the handle of the child window.
foreach (Process process in Process.GetProcesses())
{
if (process.MainWindowTitle == "Title to find")
{
IntPtr handle = process.MainWindowHandle;
// Use EnumChildWindows on handle ...
}
}
i'm trying to add a new MenuItem using DLL Fucntions imported of the user32.dll using DLLImort to a third party application out of my WPF app.
No I'd like to get the click event of the newly generated MenuItem. Any ideas?
Here's the code so far. I know there are functions of SetWindowHookEx or something else, but I'm stuck.
It's some test code and not bulletproofed..
public partial class MainWindow : Window
{
[DllImport("user32.dll")]
private static extern IntPtr GetMenu(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);
[DllImport("user32.dll")]
private static extern int GetMenuItemCount(IntPtr hMenu);
[DllImport("user32.dll")]
private static extern bool InsertMenuItem(IntPtr hMenu, uint uItem, bool
fByPosition, [In] ref MENUITEMINFO lpmii);
[DllImport("user32.dll")]
private static extern bool DrawMenuBar(IntPtr hWnd);
internal const UInt32 MIIM_FTYPE = 0x00000100;
internal const UInt32 MF_STRING = 0x00000000;
internal const UInt32 MF_OWNERDRAW = 0x00000100;
const uint MF_POPUP = 0x00000010;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern bool AppendMenu(IntPtr hMenu, MenuFlags uFlags, uint uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
static extern IntPtr CreatePopupMenu();
[Flags]
public enum MenuFlags : uint
{
MF_STRING = 0,
MF_BYPOSITION = 0x400,
MF_SEPARATOR = 0x800,
MF_REMOVE = 0x1000,
MF_POPUP = 0x00000010,
}
[StructLayout(LayoutKind.Sequential)]
struct MENUITEMINFO
{
public uint cbSize;
public uint fMask;
public uint fType;
public uint fState;
public uint wID;
public IntPtr hSubMenu;
public IntPtr hbmpChecked;
public IntPtr hbmpUnchecked;
public IntPtr dwItemData;
public string dwTypeData;
public uint cch;
public IntPtr hbmpItem;
// return the size of the structure
public static uint sizeOf
{
get { return (uint)Marshal.SizeOf(typeof(MENUITEMINFO)); }
}
}
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
createMenuEntry();
}
private void createMenuEntry()
{
Process[] proceses = Process.GetProcessesByName("spotify");
Process process = proceses.Where(e => e.MainWindowTitle == "Spotify").First();
IntPtr handle = process.MainWindowHandle;
IntPtr mainMenu = GetMenu(handle);
int mainMenuItemCount = GetMenuItemCount(mainMenu);
AppendMenu(mainMenu, MenuFlags.MF_STRING, 555, "TestEntry");
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
//HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
//source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle messages...
Debug.WriteLine((int)wParam);
if (((int)wParam == 555))
{
MessageBox.Show("Click");
}
return IntPtr.Zero;
}
}
Thanks for any ideas or suggestions in advance.
Your first step is to put down the C# and understand how the native menu API works. Start here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms647553.aspx
I strongly recommend that you create a new C++ project and write a simple program to add a menu and respond to clicks.
The key information is found in the documentation I linked to, with my emphasis:
When the user chooses a command item, the system sends a command message to the window that owns the menu. If the command item is on the window menu, the system sends the WM_SYSCOMMAND message. Otherwise, it sends the WM_COMMAND message.
You need to intercept that message. I suspect that means to need to use a global WH_CALLWNDPROC hook. That's going to need an unmanaged DLL to implement the hook.
I have a C# wrapper for some Win32 operations involving window handles, but I am experiencing an unexpected crash, with no details, when I call a Win32 function.
Interestingly, this whole code sample works fine when the class is constructed (at application init time), but later fails when the same buildCache() method is called.
Here is the relevant code:
public delegate bool CallBack(int hWnd, int lParam);
public class Win32Interop {
private Dictionary<int, string> windowCache = new Dictionary<int, string>();
public Win32Interop() {
buildCache();
}
public void buildCache() {
windowCache.Clear();
CallBack hWndCacher = new CallBack(saveHWndHandler);
EnumWindows(hWndCacher, 0);
}
public void doThings(string title, uint message, bool rebuildCache = false) {
//Use the window title to get its handle
int hWnd = titleToHWnd(title, rebuildCache);
SendMessage(hWnd, message, 0, 0);
}
private bool saveHWndHandler(int hWnd, int lParam) {
if(IsWindow(hWnd) != 0) { / ***** CRASHES HERE ***** /
int length = GetWindowTextLength(hWnd);
StringBuilder title = new StringBuilder(length + 1);
GetWindowText(hWnd, title, title.Capacity);
string formatted = title.ToString().Trim();
windowCache.Add(hWnd, formatted);
}
return true;
}
private int titleToHWnd(string title, bool rebuildCache = false) {
if(rebuildCache)
buildCache();
if(windowCache.ContainsValue(title)) {
return windowCache.FirstOrDefault(x => x.Value.Contains(title)).Key;
} else {
throw new KeyNotFoundException(string.Format("\"{0}\" is not a window title which is available in the cache.", title));
}
}
#region Win32 API Functions
[DllImport("user32.dll")]
private static extern int EnumWindows(CallBack lpEnumFunc, int lParam);
[DllImport("user32.dll")]
private static extern int GetWindowText(int hWnd, StringBuilder lpString, int maxCount);
[DllImport("user32.dll")]
private static extern int GetWindowTextLength(int hWnd);
[DllImport("user32.dll")]
private static extern int IsWindow(int hWnd);
[DllImport("user32.lib")]
private static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
#endregion
}
Inside of the saveHWndHandler() method, I've marked the line were the debugger shows execution stops. Interestingly, there are usually ~300 window handles returned by EnumWindows(), and it always crashes on iteration number 45 or 46. The window handle it crashes on is a reasonable value, such as 12345.
According to MSDN, IsWindow() should return 0, if a window was not associated with the handle, not crash the thread.
Does anyone know why this is happening? There isn't a thrown exception, or any details in the Windows event log.
Thank you.
For those who don't want to figure out the buildCache() process works:
(1.) When buildCache() is called, the dictionary of <HWnd, Title> values is cleared.
(2.) The Win32 function EnumWindows() is called, which calls the saveHWndHandler() method for each window handle.
(3.) saveHWndHandler() will check if the current window handle still exists, the call another Win32 to function to get the window title from the handle.
(4.) The title and window handle are added to the dictionary.
I can't reproduce your issue, but a likely problem is that all of your P/Invoke signatures are wrong. HWND, LPARAM, and WPARAM data types need to at least be mapped to IntPtr in P/Invoke code.
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString,
int nMaxCount);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam,
IntPtr lParam);
You'll need to change your corresponding instance method signatures and usages to match these correct signatures.
I have a situation like this.
I have the window handle of an application. I need to activate it. I tried all these functions but is not working always.(most of the time , it doesn't work the first time and I'll have to manually click on it to activate it. Second attempt onwards it works fine)
The reason why I am doing this is because I have code written in the Form.Activate event of the form which I need to execute.
Application is a single instance application. When a new instance is created , it first checks for the existence of any other process, If found, the handle of old process is passed to the these functions so that user can work on the old form.
Application is called from a different C application.
[DllImport("user32.dll")]
public static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);
[DllImport("user32")]
public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
SetForgroundWindow only works if its process has input focus. This is what I use:
public static void forceSetForegroundWindow( IntPtr hWnd, IntPtr mainThreadId )
{
IntPtr foregroundThreadID = GetWindowThreadProcessId( GetForegroundWindow(), IntPtr.Zero );
if ( foregroundThreadID != mainThreadId )
{
AttachThreadInput( mainThreadId, foregroundThreadID, true );
SetForegroundWindow( hWnd );
AttachThreadInput( mainThreadId, foregroundThreadID, false );
}
else
SetForegroundWindow( hWnd );
}
You need to find the window using something like Window title and then active it as follows:
public class Win32 : IWin32
{
//Import the FindWindow API to find our window
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindowNative(string className, string windowName);
//Import the SetForeground API to activate it
[DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
private static extern IntPtr SetForegroundWindowNative(IntPtr hWnd);
public IntPtr FindWindow(string className, string windowName)
{
return FindWindowNative(className, windowName);
}
public IntPtr SetForegroundWindow(IntPtr hWnd)
{
return SetForegroundWindowNative(hWnd);
}
}
public class SomeClass
{
public void Activate(string title)
{
//Find the window, using the Window Title
IntPtr hWnd = win32.FindWindow(null, title);
if (hWnd.ToInt32() > 0) //If found
{
win32.SetForegroundWindow(hWnd); //Activate it
}
}
}
You have to get the form using FromHandle:
f = Control.FromHandle(handle)
then you can can call Activate on the result:
f.Activate()