C# 如何从另一个进程而不是子控件获取子窗口?
我的任务是找到一种方法,使另一个应用程序显示在其他窗口的顶部(始终在顶部)。我可以使用RetrieveProcesses()函数获取具有窗口标题的进程。一旦用户选择要修改的进程,我的应用程序将调用MakeProcessOnTop或MakeProcessNormal。这两个函数都修改主应用程序的窗口。在我添加修改其子项之前,这是正确的 然后我发现这在子窗口上不起作用(就像outlook中的电子邮件),所以我开始寻找处理子窗口的方法。以下代码的编写方式最终会弄乱子窗口。如何获取子窗口而不是子控件的句柄指针C# 如何从另一个进程而不是子控件获取子窗口?,c#,user32,interopservices,C#,User32,Interopservices,我的任务是找到一种方法,使另一个应用程序显示在其他窗口的顶部(始终在顶部)。我可以使用RetrieveProcesses()函数获取具有窗口标题的进程。一旦用户选择要修改的进程,我的应用程序将调用MakeProcessOnTop或MakeProcessNormal。这两个函数都修改主应用程序的窗口。在我添加修改其子项之前,这是正确的 然后我发现这在子窗口上不起作用(就像outlook中的电子邮件),所以我开始寻找处理子窗口的方法。以下代码的编写方式最终会弄乱子窗口。如何获取子窗口而不是子控件的句
public static class ProcessManagement
{
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetFocus(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
static readonly IntPtr HWND_TOP = new IntPtr(0);
static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
public static IEnumerable<Process> RetrieveProcesses()
{
List<Process> returnList = new List<Process>();
Process[] processArray = Process.GetProcesses();
foreach (Process p in processArray)
{
if (!String.IsNullOrEmpty(p.MainWindowTitle))
{
returnList.Add(p);
}
}
return returnList;
}
public static IntPtr GetProcessWindowHandle(int processId)
{
Process p = Process.GetProcessById(processId: processId);
return p.MainWindowHandle;
}
public static List<IntPtr> GetProcessChildWindowHandles(IntPtr parent)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
EnumWindowsProc childProc = new EnumWindowsProc(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
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);
// You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
public static bool MakeProcessOnTop(IntPtr targetWindowHandle, bool targetChildren = true)
{
bool bReturn = true;
if (!ShowWindow(targetWindowHandle, ShowWindowCommands.Minimize))
{
bReturn = false;
}
if (!ShowWindow(targetWindowHandle, ShowWindowCommands.Restore))
{
bReturn = false;
}
if (!ShowWindow(targetWindowHandle, ShowWindowCommands.ShowNoActivate))
{
bReturn = false;
}
if (!SetWindowPos(targetWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE))
{
bReturn = false;
}
if (targetChildren)
{
List<IntPtr> childProcesses = GetProcessChildWindowHandles(targetWindowHandle);
foreach(IntPtr iPtr in childProcesses)
{
MakeProcessOnTop(iPtr, false);
}
}
return bReturn;
}
public static bool MakeProcessNormal(IntPtr targetWindowHandle, bool targetChildren = true)
{
bool bReturn = true;
if (!ShowWindow(targetWindowHandle, ShowWindowCommands.Minimize))
{
bReturn = false;
}
if (!ShowWindow(targetWindowHandle, ShowWindowCommands.Restore))
{
bReturn = false;
}
if (!ShowWindow(targetWindowHandle, ShowWindowCommands.ShowNoActivate))
{
bReturn = false;
}
if (!SetWindowPos(targetWindowHandle, HWND_NOTOPMOST, 0, 0, 0, 0, SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE))
{
bReturn = false;
}
if (targetChildren)
{
List<IntPtr> childProcesses = GetProcessChildWindowHandles(targetWindowHandle);
foreach (IntPtr iPtr in childProcesses)
{
MakeProcessNormal(iPtr, false);
}
}
return bReturn;
}
}
公共静态类进程管理
{
[DllImport(“user32.dll”,SetLastError=true)]
静态外部bool SetWindowPos(IntPtr hWnd、IntPtr hwninsertafter、intx、inty、intcx、intcy、SetWindowPosFlags uFlags);
[DllImport(“user32.dll”,SetLastError=true)]
静态外部IntPtr SetFocus(IntPtr hWnd);
[DllImport(“user32.dll”)]
[返回:Marshallas(UnmanagedType.Bool)]
静态外部bool ShowWindow(IntPtr hWnd、ShowWindowCommands nCmdShow);
[DllImport(“user32.dll”)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部bool EnumChildWindows(IntPtr hwndpresent、EnumWindowsProc lpEnumFunc、IntPtr lParam);
静态只读IntPtr HWND_TOPMOST=新IntPtr(-1);
静态只读IntPtr HWND_NOTOPMOST=新的IntPtr(-2);
静态只读IntPtr HWND_TOP=新IntPtr(0);
静态只读IntPtr HWND_BOTTOM=新IntPtr(1);
公共静态IEnumerable RetrieveProcess()
{
List returnList=新列表();
Process[]processArray=Process.getprocesss();
foreach(processArray中的进程p)
{
如果(!String.IsNullOrEmpty(p.MainWindowTitle))
{
返回列表。添加(p);
}
}
退货清单;
}
公共静态IntPtr GetProcessWindowHandle(int processId)
{
processp=Process.GetProcessById(processId:processId);
返回p.main窗口句柄;
}
公共静态列表GetProcessChildWindowHandles(IntPtr父级)
{
列表结果=新列表();
GCHandle listHandle=GCHandle.Alloc(结果);
尝试
{
EnumWindowsProc childProc=新的EnumWindowsProc(EnumWindow);
EnumChildWindows(父、childProc、GCHandle.ToIntPtr(listHandle));
}
最后
{
if(listHandle.IsAllocated)
Free();
}
返回结果;
}
私有静态布尔枚举窗口(IntPtr句柄、IntPtr指针)
{
GCHandle gch=GCHandle.FromIntPtr(指针);
列表=gch。目标为列表;
if(list==null)
{
抛出新的InvalidCastException(“GCHandle目标无法强制转换为列表”);
}
列表。添加(句柄);
//您可以对此进行修改以检查是否要取消该操作,然后在此处返回null
返回true;
}
公共静态bool MakeProcessOnTop(IntPtr targetWindowHandle,bool targetChildren=true)
{
bool-bReturn=true;
如果(!ShowWindow(targetWindowHandle,ShowWindowCommands.Minimize))
{
bReturn=false;
}
如果(!ShowWindow(targetWindowHandle,ShowWindowCommands.Restore))
{
bReturn=false;
}
如果(!ShowWindow(targetWindowWhandle、ShowWindowCommands.ShowNoActivate))
{
bReturn=false;
}
如果(!SetWindowPos(targetWindowWhandle,HWND_TOPMOST,0,0,0,SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE))
{
bReturn=false;
}
if(目标儿童)
{
List childProcesses=GetProcessChildWindowHandles(targetWindowHandle);
foreach(子进程中的IntPtr iPtr)
{
MakeProcessOnTop(iPtr,false);
}
}
回程;
}
公共静态bool MakeProcessNormal(IntPtr targetWindowHandle,bool targetChildren=true)
{
bool-bReturn=true;
如果(!ShowWindow(targetWindowHandle,ShowWindowCommands.Minimize))
{
bReturn=false;
}
如果(!ShowWindow(targetWindowHandle,ShowWindowCommands.Restore))
{
bReturn=false;
}
如果(!ShowWindow(targetWindowWhandle、ShowWindowCommands.ShowNoActivate))
{
bReturn=false;
}
如果(!SetWindowPos(targetWindowWhandle,HWND_NOTOPMOST,0,0,0,SetWindowPosFlags.SWP_noactive | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE))
{
bReturn=false;
}
if(目标儿童)
{
List childProcesses=GetProcessChildWindowHandles(targetWindowHandle);
foreach(子进程中的IntPtr iPtr)
{
MakeProcessNormal(iPtr,false);
}
}
回程;
}
}
始终在顶部仅对顶级窗口或可能的MDI子窗口有意义
您可以通过操纵Z顺序来提升子窗口,但没有明确定义如何将其放回原位。始终在顶部仅对顶级窗口或可能的MDI子窗口有意义
您可以通过操纵Z顺序来引发子窗口,但它没有很好地定义如何将其放回。您查看过这些帖子吗?我尝试过EnumThreadWindows,但没有成功。您查看过这些帖子吗?我尝试过EnumThreadWindows,但没有成功。我也尝试过使用EnumThreadWindows,因此我将假设我尝试做的事情没有得到很好的支持,可能没有意义。我尝试也使用EnumThreadWindows,但没有成功,所以我