I want to know how to bring forward a particular window.
SetForegroundWindow works when the window is not minimized!! but when a minimize the window, SetForegroundWindow doesn't work...
this my code:
int IdRemoto = int.Parse(textBoxID.Text);
Process[] processlist = Process.GetProcessesByName("AA_v3.3");
foreach (Process process in processlist)
{
if (!String.IsNullOrEmpty(process.MainWindowTitle))
{
if (IdRemoto.ToString() == process.MainWindowTitle)
SetForegroundWindow(process.MainWindowHandle);
}
}
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
You can check to see if the window is minimized using the IsIconic() API, then use ShowWindow() to restore it:
public const int SW_RESTORE = 9;
[DllImport("user32.dll")]
public static extern bool IsIconic(IntPtr handle);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr handle);
private void BringToForeground(IntPtr extHandle)
{
if (IsIconic(extHandle))
{
ShowWindow(extHandle, SW_RESTORE);
}
SetForegroundWindow(extHandle);
}
You can use ShowWindow combined with what you already have, here is your example with a little modification:
int IdRemoto = int.Parse(textBoxID.Text);
Process[] processlist = Process.GetProcessesByName("AA_v3.3");
foreach (Process process in processlist)
{
if (!String.IsNullOrEmpty(process.MainWindowTitle))
{
if (IdRemoto.ToString() == process.MainWindowTitle)
{
ShowWindow(process.MainWindowHandle, 9);
SetForegroundWindow(process.MainWindowHandle);
}
}
}
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWind, int nCmdShow);
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 developed an add-on for SAP Business One, as a C# Windows Forms application.
In this add-on, using LoadLibraryEx, I load a native unmanaged DLL (correct me if I'm wrong) written in C++.
The add-on calls a method of the DLL, in this way:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int _MyDllMethod();
//...
//load library
var handle = LoadLibraryEx(libPath, IntPtr.Zero, 0x00000008 /*LOAD_WITH_ALTERED_SEARCH_PATH*/);
//invoke method
Type delegateFunType = typeof(_MyDllMethod);
IntPtr funAddr = GetProcAddress(handle, delegateFunType.Name);
var fun = Convert.ChangeType(Marshal.GetDelegateForFunctionPointer(funAddr, delegateFunType), delegateFunType);
int result = fun.Invoke(); //now a window appears
This method opens a window with which the user interacts.
Everything working fine, except that such window starts minimized in the task bar, while I need it to appear in the forground as the active window. How can I acieve this?
Finally I found this hack: launching a parallel thread that looks for the window that will be opened by the DLL and bring it to the foreground with Windows API functions:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int _MyDllMethod();
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("User32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr handle);
[DllImport("User32.dll")]
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
private const int ALT = 0xA4;
private const int EXTENDEDKEY = 0x1;
private const int KEYUP = 0x2;
private const int SW_RESTORE = 9;
//...
//launch a parallel thread that looks for library window
//and brings it to the foreground
ThreadPool.QueueUserWorkItem(delegate {
bool windowFound = false;
int attempts = 0;
while (!windowFound && attempts < 10)
{
attempts++;
//check frequently
Thread.Sleep(200);
//look for the window using its class name
IntPtr handle = FindWindow("DllWindowClassName", null);
//check it is a running process
if (handle != IntPtr.Zero)
{
bool success = false;
//if window is minimized to icon
if (IsIconic(handle))
{
//then show it
success = ShowWindow(handle, SW_RESTORE);
}
//bring window to front
success = SetForegroundWindow(handle);
//once done, this thread can terminate
if (success)
{
windowFound = true;
}
else
{
//in case of failure, try this hack
//simulate a key press and release (hack for SetForegroundWindow to work)
keybd_event((byte)ALT, 0x45, EXTENDEDKEY | 0, 0);
keybd_event((byte)ALT, 0x45, EXTENDEDKEY | KEYUP, 0);
//bring window to front
success = SetForegroundWindow(handle);
//once done, this thread can terminate
if (success)
{
windowFound = true;
}
}
}
}
}, null);
//load library
var handle = LoadLibraryEx(libPath, IntPtr.Zero, 0x00000008 /*LOAD_WITH_ALTERED_SEARCH_PATH*/);
//invoke method
Type delegateFunType = typeof(_MyDllMethod);
IntPtr funAddr = GetProcAddress(handle, delegateFunType.Name);
var fun = Convert.ChangeType(Marshal.GetDelegateForFunctionPointer(funAddr, delegateFunType), delegateFunType);
int result = fun.Invoke(); //now a window appears
You can discover window class name using FindWindow, passing window title, and then with GetClassName. Class name is more reliable than the title, which can change with the language and in the time.
My code is very simple:
using Microsoft.VisualBasic;
namespace HelloWorld {
class MyClass {
static void Main(string[] args) {
Interaction.AppActivate(6156); // the PID of notepad++
}
}
}
When I execute this program, nothing happens. I would expect 6156 (PID from Task Manager) aka Notepad++ to get focused. What's wrong here?
I'm trying to find the equivalent to Pythons pywin32 code of shell = win32com.client.Dispatch("WScript.Shell") and shell.AppActivate(6156)
The Interaction.AppActivate code will not work if the app is minimized.
Use the following code to active the app:
public const int SW_RESTORE = 9;
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
static extern public bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void Main(string[] args)
{
var process = Process.GetProcessById(18036);
ShowWindow(process.MainWindowHandle, SW_RESTORE);
SetForegroundWindow(process.MainWindowHandle);
}
This works fine for me.
static void Main(string[] args)
{
var process = Process.GetProcessById(13004);//the pid
if (process == null) return;
SwitchToThisWindow(process.MainWindowHandle, true);
}
[DllImport("user32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool turnOn);
What I'm trying to do is activate another application and send a key input to it to trigger a button. However this code doesn't seem to work. It looks like it can find the application but it does not activate it, and does not send the key.
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
private void debugButton_Click(object sender, EventArgs e)
{
//GetProcess by Class
IntPtr rightNowHandle = FindWindow("WindowsForms10.Window.8.app.0.24dc298_r17_ad2", null);
//Get Handle by Process
Process proc = Process.GetProcessesByName("RightNow.CX")[0];
IntPtr ptrFF = proc.MainWindowHandle;
//Get a handle for the Calculator Application main window
if (rightNowHandle == IntPtr.Zero)
{
MessageBox.Show("Could Not Find Right Now");
return;
}
SetForegroundWindow(rightNowHandle); //Activate Handle By Class
//SetForegroundWindow(ptrFF); //Activate Handle By Process
SendKeys.SendWait("{F1}");
}
And here is what I pull with Window Spy
Any help would be greatly appreciated. Thanks.
Figured out my issue.
SetForegroundWindow does not show the application if it's minimized, which is what I was anticipating.
Next I used Windows Input Simulator, to send the input instead of SendKeys.
Here's the code I ended up using.
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
private const int SW_RESTORE = 9;
private void debugButton_Click(object sender, EventArgs e)
{
//GetProcess by Class
IntPtr rightNowHandle = FindWindow("WindowsForms10.Window.8.app.0.24dc298_r17_ad2", null);
//Get Handle by Process
Process proc = Process.GetProcessesByName("RightNow.CX")[0];
IntPtr ptrFF = proc.MainWindowHandle;
//Get a handle for the Calculator Application main window
if (rightNowHandle == IntPtr.Zero)
{
MessageBox.Show("Could Not Find Right Now");
return;
}
SetForegroundWindow(ptrFF); //Activate Handle By Process
ShowWindow(ptrFF, SW_RESTORE); //Maximizes Window in case it was minimized.
//SetForegroundWindow(rightNowHandle); //Activate Handle By Class
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.LMENU, VirtualKeyCode.VK_A); //Send Left Alt + A
}
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()