是的,我知道我之前问过这个问题已经很久了,但我现在回答它是因为我在找到解决方案后一直忘记回答它。我最初使用了@SushiHangover的解决方案,但并不是很喜欢它,因为我觉得依赖外部程序(xwininfo)是一个临时的解决方法,并最终增加了另一个依赖项。希望这能帮助其他使用Mono的C#开发人员。这段代码最初是为.NET Framework 2.0编写的。它不太花哨,文档也不是很好。我的解决方案只是通过自己本地枚举窗口并返回所有标题与描述相匹配的窗口。
在X11Wrapper.cs中:
using System;
using System.Runtime.InteropServices;
namespace Program.PInvoke.Xlib {
public static class X11Wrapper {
public const string SOName = "libX11.so";
[DllImport(SOName)]
// See: https://tronche.com/gui/x/xlib/display/display-macros.html
public static extern IntPtr XDefaultRootWindow(IntPtr display);
[DllImport(SOName)]
// See: https://tronche.com/gui/x/xlib/window-information/XQueryTree.html
public static extern int XQueryTree(IntPtr display, IntPtr w,
out IntPtr root_return, out IntPtr parent_return,
out IntPtr[] children_return, out int nchildren_return);
[DllImport(SOName)]
// See: https://tronche.com/gui/x/xlib/ICC/client-to-window-manager/XFetchName.html
public static extern int XFetchName(IntPtr display, IntPtr w,
out string window_name_return);
}
}
在Linux.Utilities.cs文件中:
using Program.PInvoke.Xlib;
namespace Program {
public static partial class Utilities {
public static bool IsUnix {
get {
return Environment.OSVersion.
Platform == PlatformID.Unix;
}
}
private static IntPtr[] FindChildWindows(IntPtr display, IntPtr window,
string title, ref List<IntPtr> windows) {
IntPtr rootWindow;
IntPtr parentWindow;
IntPtr[] childWindows = new IntPtr[0];
int childWindowsLength;
X11Wrapper.XQueryTree(display, window,
out rootWindow, out parentWindow,
out childWindows, out childWindowsLength);
childWindows = new IntPtr[childWindowsLength];
X11Wrapper.XQueryTree(display, window,
out rootWindow, out parentWindow,
out childWindows, out childWindowsLength);
string windowFetchedTitle;
X11Wrapper.XFetchName(display, window, out windowFetchedTitle);
if(title == windowFetchedTitle &&
!windows.Contains(window)) {
windows.Add(window);
}
for(int childWindowsIndexer = 0;
childWindowsIndexer < childWindows.Length;
childWindowsIndexer++) {
IntPtr childWindow = childWindows[childWindowsIndexer];
string childWindowFetchedTitle;
X11Wrapper.XFetchName(display, childWindow,
out childWindowFetchedTitle);
if(title == childWindowFetchedTitle &&
!windows.Contains(childWindow)) {
windows.Add(childWindow);
}
FindChildWindows(display, childWindow, title, ref windows);
}
windows.TrimExcess();
return windows.ToArray();
}
public static IntPtr[] FindWindows(IntPtr display, string title) {
List<IntPtr> windows = new List<IntPtr>();
return FindChildWindows(display,
X11Wrapper.XDefaultRootWindow(display),
title,
ref windows);
}
}
}
注:我最初表示我不是C开发人员(事情已经改变,我学会了C),因此我对使用Interop自己实现功能感到犹豫。如果您像我一样更多地使用Xlib,则可以考虑使用tronche作为Xlib API参考。它是用C编写的,但我发现将其翻译为可PInvoke函数和可封送结构在C#中相当容易。还有一些要考虑的好注意事项。另一个帮助翻译的好资源是直接使用源代码查找低级类型的定义,以帮助找到C#等效项。类似这样的东西应该会大大帮助您:http://refspecs.linuxbase.org/LSB_4.0.0/LSB-Desktop-generic/LSB-Desktop-generic/libx11-ddefs.html
process.MainWindowHandle
对于 Xlib 来说没有意义,从进程 ID 开始,您需要遍历窗口树以找到要提升的窗口。您可以查看xwininfo
的C
源代码来了解如何实现... - SushiHangoverApplicationHandle = (IntPtr)0x000000;
时,它可以正常工作。但这是一种硬编码的解决方案。我在网上看到了一些枚举窗口的代码,但同样,我不是C或C++程序员。 - video_errorxwininfo
并解析stdout以获取所需的窗口ID,我已经多次这样做来获取整个窗口树或仅一个(通过名称选项)...虽然不如API“干净”,但它“可行”;-) - SushiHangover