Hi I looked into this guy question and got some of my answer but I would like to instead of resizing explorer I would like to resize discord or firefox for instance
private void windowsPos(string name, Rect pos){
foreach (SHDocVw.InternetExplorer window in new SHDocVw.ShellWindows()){
if (Path.GetFileNameWithoutExtension(window.FullName).ToLowerInvariant() == name){
window.Left = pos.Left;
window.Top = pos.Top;
window.Width = pos.Width;
window.Height = pos.Height;
}
}
}
But this works only for explorer I tried other exe but it works only for explorer ... can someone help me adapt this code to my requirements ?
Thank you #zezba9000 & #NetMage your answsers were the ones that worked ... I went on PInvoke - EnumWindows to get the general idea of how it works and the used Reed's answer to get to this code :
public class SearchData{
public string Title;
public IntPtr hWnd;
}
private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
private void test(){
IntPtr hwnd = SearchForWindow("Discord");
SetWindowPos(hwnd, 0, 50, 175, 1000, 750, 0x0040);
}
public IntPtr SearchForWindow(string title){
SearchData sd = new SearchData { Title = title };
EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
return sd.hWnd;
}
public bool EnumProc(IntPtr hWnd, ref SearchData data){
StringBuilder sb = new StringBuilder(1024);
GetWindowText(hWnd, sb, sb.Capacity);
if (sb.ToString().Contains(data.Title)){
data.hWnd = hWnd;
return false;
}
else return true;
}
Also #Jimi I tried your approach but I could not work with it because it could not find Automation in the System.Windows namespace
Related
The goal
I developed a keyboard in Unity3D (C#) and want it to pop up when the users click on "EDIT" type control such as a address bar or an input field. Therefore, I need to detect when an "EDIT" control is clicked.
What I've tried
Currently I use SetWinEventHook and listen to event EVENT_OBJECT_FOCUS to get the handle of the object which gets the focus. After that, I use GetClassName to see if the focused object is an "EDIT" control which displays a flashing caret when clicked. However, take Google Chrome as an example, I always get Chrome_WidgetWin_1 whether I click the address bar or the plain text of the page. After doing some googling I found this blog post What makes RealGetWindowClass so much more real than GetClassName? saying that RealGetWindowClass can get the base class which I think it will be something like "EDIT" or "COMBOBOX" listed here. Things were not going so well. I tried using RealGetWindowClass and still get the same result Chrome_WidgetWin_1.
The problem
Why do GetClassName and RealGetWindowClass return the same value? How should I make RealGetWindowClass return the base class?
The code
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWinEventHook(int eventMin, int eventMax, IntPtr hmodWinEventProc, WinEventProc lpfnWinEventProc, int idProcess, int idThread, int dwflags);
[DllImport("user32.dll", SetLastError = true)]
private static extern int UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RealGetWindowClass(IntPtr hwnd, [Out] StringBuilder pszType, uint cchType);
private delegate void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
private const int WINEVENT_SKIPOWNPROCESS = 2;
private IntPtr windowEventHook;
private const int EVENT_OBJECT_FOCUS = 0x8005;
private void Start()
{
if (windowEventHook == IntPtr.Zero)
{
windowEventHook = SetWinEventHook(
EVENT_OBJECT_FOCUS,
EVENT_OBJECT_FOCUS,
IntPtr.Zero,
WindowEventCallback,
0,
0,
WINEVENT_SKIPOWNPROCESS);
if (windowEventHook == IntPtr.Zero)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}
private void OnDestroy()
{
UnhookWinEvent(windowEventHook);
}
private void WindowEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
UnityEngine.Debug.Log($"[EventType]: {(EventEnum)eventType} [Class Name]: {GetClassName(hWnd)} [Real Class]: {RealGetWindowClassM(hWnd)}");
// Will print out the same log whether I click an address bar or plain text.
// [EventType]: EVENT_OBJECT_FOCUS [Class Name]: Chrome_WidgetWin_1 [Real Class]: Chrome_WidgetWin_1
}
private string GetClassName(IntPtr hWnd)
{
StringBuilder className = new StringBuilder(256);
GetClassName(hWnd, className, className.Capacity);
return className.ToString();
}
private string RealGetWindowClassM(IntPtr hWnd)
{
StringBuilder className = new StringBuilder(256);
RealGetWindowClass(hWnd, className, (UInt32)className.Capacity);
return className.ToString();
}
I have list of open Applications. To get this list i have used following code
internal static class NativeMethods
{
public static readonly Int32 GWL_STYLE = -16;
public static readonly UInt64 WS_VISIBLE = 0x10000000L;
public static readonly UInt64 WS_BORDER = 0x00800000L;
public static readonly UInt64 DESIRED_WS = WS_BORDER | WS_VISIBLE;
public delegate Boolean EnumWindowsCallback(IntPtr hwnd, Int32 lParam);
public static List<WindowWrapper> GetAllWindows()
{
List<WindowWrapper> windows = new List<WindowWrapper>();
StringBuilder buffer = new StringBuilder(100);
EnumWindows(delegate(IntPtr hwnd, Int32 lParam)
{
if ((GetWindowLongA(hwnd, GWL_STYLE) & DESIRED_WS) == DESIRED_WS)
{
GetWindowText(hwnd, buffer, buffer.Capacity);
WindowWrapper wnd = new WindowWrapper();
wnd.handle = hwnd;
wnd.title = buffer.ToString();
windows.Add(wnd);
}
return true;
}, 0);
return windows;
}
[DllImport("user32.dll")]
static extern Int32 EnumWindows(EnumWindowsCallback lpEnumFunc, Int32 lParam);
[DllImport("user32.dll")]
public static extern void GetWindowText(IntPtr hWnd, StringBuilder lpString, Int32 nMaxCount);
[DllImport("user32.dll")]
static extern UInt64 GetWindowLongA(IntPtr hWnd, Int32 nIndex);
}
public class WindowWrapper : IWin32Window
{
internal IntPtr handle;
internal String title;
public IntPtr Handle
{
get { return handle; }
}
public String Title
{
get { return title; }
}
}
to call this i used following code
foreach (var wnd in NativeMethods.GetAllWindows())
{
string caption = wnd.title;
string handle = wnd.Handle
// Add this caption and handle to list
}
Now, User will select any of the opened window from the list and my task is to read caption of the selected window, get handle of process and maximize/minimize or close window. How can I do this.
You can use findwindowbycaption to get the handle then maximize or minimize with showwindow
private const int SW_MAXIMIZE = 3;
private const int SW_MINIMIZE = 6;
// more here: http://www.pinvoke.net/default.aspx/user32.showwindow
[DllImport("user32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
Then in your code you use this:
IntPtr hwnd = FindWindowByCaption(IntPtr.Zero, "The window title");
ShowWindow(hwnd, SW_MAXIMIZE);
Although it seems you already have the window handle by using EnumWindows in that case you would only need:
ShowWindow(windows[i].handle, SW_MAXIMIZE);
i is the index of the window.
to close the window you will use:
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DestroyWindow(IntPtr hwnd);
in the code:
DestroyWindow(hwnd) //or DestroyWindow(windows[i].handle)
this is the unmanaged version of system.windows.forms.form.close()
or you can use:
Process [] proc Process.GetProcessesByName("process name");
proc[0].Kill();
or you can use:
static uint WM_CLOSE = 0x0010;
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
in code:
PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
You may use native method ShowWindow with SW_MAXIMIZE, SW_MINIMIZE for ncmdShow
Take a look at http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
private const int SW_MAXIMIZE = 3;
private const int SW_MINIMIZE = 6;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
// in your code
ShowWindow(wnd.Handle, SW_MAXIMIZE);
you can use ShowWindowAsync
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
ShowWindowAsync(wnd.Handle, SW_SHOWMINIMIZED );
and it's better and to use
var openWindows = Process.GetProcesses().Where(process=> String.IsNullOrEmpty(process.MainWindowTitle)==false);
to get opened windows
I have test MainWindowTitle in Porcess and it helps to search on window given it's caption.
var handles = Process.GetProcesses().Where(x => x.MainWindowTitle == "Untitled - Notepad").Select(y=>y.Handle).ToList();
Im trying to create a program where I can send some process id of a process (that may be firefox, ie, notepad etc) to a method that scrolls window of the process.
I have been trying with GetScrollBarInfo and SetScrollPos which I found at pinvoke without any success. Im not sure if this is the right way or not. I started playing with GetScrollBarInfo, but it doesn't seem to work.
I tried the code found at http://www.pinvoke.net/default.aspx/user32.getscrollbarinfo
[StructLayout(LayoutKind.Sequential)]
public struct SCROLLBARINFO
{
public int cbSize;
public Rectangle rcScrollBar;
public int dxyLineButton;
public int xyThumbTop;
public int xyThumbBottom;
public int reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public int[] rgstate;
}
private const uint OBJID_HSCROLL = 0xFFFFFFFA;
private const uint OBJID_VSCROLL = 0xFFFFFFFB;
private const uint OBJID_CLIENT = 0xFFFFFFFC;
private int Scroll(int ProcessID)
{
IntPtr handle = Process.GetProcessById(ProcessID).MainWindowHandle;
SCROLLBARINFO psbi = new SCROLLBARINFO();
psbi.cbSize = Marshal.SizeOf(psbi);
int nResult = GetScrollBarInfo(handle, OBJID_CLIENT, ref psbi);
if (nResult == 0)
{
int nLatError = Marshal.GetLastWin32Error();
}
}
GetLastWin32Error() returns errorcode 122 which means "The data area passed to a system call is too small", according to http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
Im not sure what I do wrong. How can I solve this?
You could send a WM_MOUSEWHEEL message to do what you want. For example, to scroll down once in a new notepad window using C++:
HWND hwnd = FindWindowEx(FindWindow(NULL, "Untitled - Notepad"), NULL, "Edit", NULL);
RECT r;
GetClientRect(hwnd, &r);
SendMessage(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA * -1), MAKELPARAM(r.right / 2, r.bottom / 2));
To adapt that to C#, you could do something such as this:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, ref Point lParam);
private void ScrollWindow(IntPtr hwnd, Point p, int scrolls = -1)
{
SendMessage(hwnd, WM_MOUSEWHEEL, (WHEEL_DELTA * scrolls) << 16, ref p);
}
Which could be used to scroll down once in a new notepad window like this:
//Imports
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
...
//Actual code
IntPtr hwnd = FindWindowEx(FindWindow(null, "Untitled - Notepad"), IntPtr.Zero, "Edit", null);
Point p = new Point(0, 0);
ScrollWindow(hwnd, p);
Some programs will require the lParam sent to be a point that's actually above the scrolled area, while others such as notepad will not.
If you're trying to scroll the window of another process, you need to, in effect, simulate clicks on the scroll bar or key presses. The cleanest way to do that is to use UI Automation, which has both .NET and native interfaces.
By asking for the scrollbar info, you're simply getting information about how the scrollbar is displayed. That's not going to give you a way to scroll the window content. You have to get the target application to scroll the content by making it think the user is operating the scrollbar.
http://forums.codeguru.com/showthread.php?446352-How-to-scroll-active-window-SendMessage&p=1686041#post1686041
Final Code
class Program
{
[DllImport("user32.dll")]
static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui);
[DllImport("user32.dll")]
public static extern int SetScrollPos(IntPtr hWnd, System.Windows.Forms.Orientation nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
public struct GUITHREADINFO
{
public int cbSize;
public int flags;
public IntPtr hwndActive;
public IntPtr hwndFocus;
public IntPtr hwndCapture;
public IntPtr hwndMenuOwner;
public IntPtr hwndMoveSize;
public IntPtr hwndCaret;
public System.Drawing.Rectangle rcCaret;
}
const Int32 WM_VSCROLL = 0x0115;
const Int32 SB_LINERIGHT = 1;
static void Main(string[] args)
{
//create process in focus
Process.Start("notepad++", "Source.cpp");
Thread.Sleep(1000);
GUITHREADINFO threadInfo = new GUITHREADINFO();
threadInfo.cbSize = Marshal.SizeOf(threadInfo);
GetGUIThreadInfo(0, ref threadInfo);
SendMessage(threadInfo.hwndFocus, WM_VSCROLL, SB_LINERIGHT, 0);
//SetScrollPos not work. Change only scrollbar without scroll window
//SetScrollPos(threadInfo.hwndFocus, System.Windows.Forms.Orientation.Vertical, 10, true);
}
}
I am using 2 Windows API exported functions from c#.NET 4.0.
private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";
I am searching for windows titles of Excel main windows' child windows (Excel has an MDI window of class XLMAIN containing 0, 1 or more child windows with EXCEL7 window class).
The goal is to find if a an excel workbook is being opened in any instances of Excel application. I did it by finding all XLMAIN IntPtr (pointers) and traversing children until I get a IntPtr with EXCEL7 window class at which point I can read child windows title and determine if a file is opened.
Basically this works on Windows XP, but not on Windows 7. I didn't try in Windows Vista.
What has changed? Can someone debug the issue since I don't have Windows 7.
Thanks
Rad
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ExcelChildWindowsTitle
{
public static void Main(string[] args)
{
//XLMAIN/EXCELDESK/EXCEL7 as seen by Spy++ VS 2010 utility
//IntPtr hWnd = WndSearcher.SearchForWindow("XLMAIN", "EXCEL7", "icui-20110331.xls", ref workbookTitle);
//bool excelProofFound = WindowTitleSearcher.SearchForWindow("XLMAIN", "EXCEL7", "testfileopenedinEXCEL.xls", ref workbookTitle);
bool excelProofFound = WindowTitleSearcher.SearchForWindow("icui-20110331.xls");
if (excelProofFound)
Console.Write(":)))))))) Proof File opened in an Excel process;");
else
{
Console.Write(":|Proof File not found");
}
}
public static class WindowTitleSearcher
{
private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";
public static bool SearchForWindow(string title)
{
SearchData sd = new SearchData { Wndclass = WINDOW_EXCEL7, ChildWndclass = CHILDWINDOW_XLMAIN, ChildTitle = title, WorkbookTitle = String.Empty};
EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
return (int)sd.hWnd > 0;
}
private static bool EnumProc(IntPtr hWnd, ref SearchData data)
{
const bool directOnly = false;
// Check classname and title
// This is different from FindWindow() in that the code below allows partial matches
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hWnd, sb1, sb1.Capacity);
Debug.WriteLine(sb1.ToString());
if (sb1.ToString().StartsWith(data.Wndclass))
{
RecursiveEnumChildWindows(hWnd, directOnly, ref data);
if ((int)data.hWnd > 0)
{
// Found the wnd, halt enumeration
return false;
}
}
return true;
}
private static void RecursiveEnumChildWindows(IntPtr parentHwnd, bool directOnly, ref SearchData data)
{
EnumChildWindows(parentHwnd, delegate(IntPtr hwnd, ref SearchData data1)
{
bool add = true;
if (directOnly)
{
add = GetParent(hwnd) == parentHwnd;
}
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hwnd, sb1, sb1.Capacity);
Debug.WriteLine("Child:" + sb1.ToString());
if (add)
{
if (sb1.ToString().StartsWith(data1.ChildWndclass))
{
sb1 = new StringBuilder(1024);
//Window Caption
GetWindowText(hwnd, sb1, sb1.Capacity);
if (sb1.ToString().Contains(data1.ChildTitle))
{
data1.hWnd = hwnd;
data1.WorkbookTitle = sb1.ToString();
return false; // Found the wnd, halt enumeration
}
}
}
return true;
}, ref data);
}
private struct SearchData
{
// You can put any vars in here...
public string Wndclass;
public string ChildWndclass;
public string ChildTitle;
public IntPtr hWnd;
public string WorkbookTitle;
}
# region Windows API declarations
private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);
//private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, [MarshalAsAttribute(UnmanagedType.Struct)] ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, ref SearchData data);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
private static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
# endregion
}
}
Why use hacks like this when MS Office has documented automation support?
You can use .NET, the older COM/OLE automation interfaces or the super old DDE interface.
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ExcelChildWindowsTitle
{
class Program
{
static void Main(string[] args)
{
//XLMAIN/EXCELDESK/EXCEL7 as seen by Spy++ VS 2010 utility
//IntPtr hWnd = WndSearcher.SearchForWindow("XLMAIN", "EXCEL7", "icui-20110331.xls", ref workbookTitle);
//bool excelProofFound = WindowTitleSearcher.SearchForWindow("XLMAIN", "EXCEL7", "testfileopenedinEXCEL.xls", ref workbookTitle);
bool excelProofFound = WindowTitleSearcher.SearchForWindow("file name here");
if (excelProofFound)
Console.Write(":)))))))) Proof File opened in an Excel process;");
else
{
Console.Write(":|Proof File not found");
}
}
public static class WindowTitleSearcher
{
private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";
public static bool SearchForWindow(string title)
{
SearchData sd = new SearchData { Wndclass = WINDOW_EXCEL7, ChildWndclass = CHILDWINDOW_XLMAIN, ChildTitle = title, WorkbookTitle = String.Empty };
EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
return (int)sd.hWnd > 0;
}
private static bool EnumProc(IntPtr hWnd, ref SearchData data)
{
const bool directOnly = false;
// Check classname and title
// This is different from FindWindow() in that the code below allows partial matches
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hWnd, sb1, sb1.Capacity);
Debug.WriteLine(sb1.ToString());
if (sb1.ToString().StartsWith(data.Wndclass))
{
RecursiveEnumChildWindows(hWnd, directOnly, ref data);
if ((int)data.hWnd > 0)
{
// Found the wnd, halt enumeration
return false;
}
}
return true;
}
private static void RecursiveEnumChildWindows(IntPtr parentHwnd, bool directOnly, ref SearchData data)
{
EnumChildWindows(parentHwnd, delegate(IntPtr hwnd, ref SearchData data1)
{
bool add = true;
if (directOnly)
{
add = GetParent(hwnd) == parentHwnd;
}
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hwnd, sb1, sb1.Capacity);
Debug.WriteLine("Child:" + sb1.ToString());
if (add)
{
if (sb1.ToString().StartsWith(data1.ChildWndclass))
{
sb1 = new StringBuilder(1024);
//Window Caption
GetWindowText(hwnd, sb1, sb1.Capacity);
if (sb1.ToString().Contains(data1.ChildTitle))
{
data1.hWnd = hwnd;
data1.WorkbookTitle = sb1.ToString();
return false; // Found the wnd, halt enumeration
}
}
}
return true;
}, ref data);
}
private struct SearchData
{
// You can put any vars in here...
public string Wndclass;
public string ChildWndclass;
public string ChildTitle;
public IntPtr hWnd;
public string WorkbookTitle;
}
# region Windows API declarations
private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);
//private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, [MarshalAsAttribute(UnmanagedType.Struct)] ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, ref SearchData data);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
private static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
# endregion
}
}
}
/////////////////////Work good on Windows 10 64 bit
I want to bring another application into the foreground, however, I only have a partial name of the window. Back in the day, I'd hook into the EnumWindows API and look for what I needed.
Is there a way to do this better in C#? An example would be great.
This should do the job:
[DllImport("user32.dll", EntryPoint="SystemParametersInfo")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, uint pvParam, uint fWinIni);
[DllImport("user32.dll", EntryPoint="SetForegroundWindow")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll", EntryPoint="ShowWindowAsync")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
private const int WS_SHOWNORMAL = 1;
private const int SW_SHOWMAXIMIZED = 3;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
private struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public System.Drawing.Point ptMinPosition;
public System.Drawing.Point ptMaxPosition;
public System.Drawing.Rectangle rcNormalPosition;
}
Process[] processes = Process.GetProcesses();
foreach(Process p in processes){
if(p.MainWindowTitle.Contains("nice_title")){
WINDOWPLACEMENT wp = new WINDOWPLACEMENT();
placement.length = Marshal.SizeOf(placement);
GetWindowPlacement(p.MainWindowHandle, ref placement);
int proposedPlacement = wp.showCmd;
if (wp.showCmd == SW_SHOWMINIMIZED)
proposedPlacement = SW_SHOWMAXIMIZED;
SystemParametersInfo( (uint) 0x2001, 0, 0, 0x0002 | 0x0001);
ShowWindowAsync(p.MainWindowHandle, proposedPlacement);
SetForegroundWindow(p.MainWindowHandle);
SystemParametersInfo( (uint) 0x2001, 200000, 200000, 0x0002 | 0x0001);
}
}