我一直在搜索,试图找到我的困境的答案,但似乎无法找到一个有效的答案。我正在尝试用Xlib编写一些等效的user32.dll代码,以便我可以支持Linux用户。我当然在运行Linux,所以我使用的是Mono。当我甚至无法从Process类中获取窗口句柄时出现问题,因为它甚至从未实现过:
[MonoTODO]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[MonitoringDescription ("The handle of the main window of the process.")]
public IntPtr MainWindowHandle {
get {
return((IntPtr)0);
}
}
(Qazxswpoi)
这尤其令人沮丧,因为似乎没有其他选择。我试图像这样抓住一个窗口手柄:
Source
注意:代替“myPid”是一个正确的进程ID。将“myPid”替换为有效的进程ID。是的,我确实确保替换的“myPid”是一个有效的进程ID,我的代码没有抛出任何错误,表明我使用的任何进程ID都是无效的。
这不会导致我的应用程序崩溃,但几乎每次我调用XRaiseWindow它都会打印:
[DllImport("libX11")]
private static extern IntPtr XOpenDisplay(IntPtr display);
[DllImport("libX11")]
private static extern int XRaiseWindow(IntPtr display, IntPtr window);
private IntPtr ApplicationHandle;
private IntPtr Display;
private void TestXlib() {
Process process = Process.GetProcessById(myPid);
ApplicationHandle = process.MainWindowHandle;
Display = XOpenDisplay(IntPtr.Zero);
XRaiseWindow(Display, ApplicationHandle);
}
这显然是因为Process.MainWindowHandle返回IntPtr.Zero。没有其他方法可以获得窗口句柄吗?提前致谢!
是的,我知道这是我之前的问题,但我现在正在回答这个问题,因为在我自己找到解决方案之后,我一直忘记回答它。我最初使用@SushiHangover的解决方案,但并不喜欢它,因为我觉得依赖外部程序(X11 Error encountered:
Error: BadWindow (invalid Window parameter)
Request: 12 (0)
Resource ID: 0x0
Serial: 121
Hwnd: <null>
Control: <null>
)是一个修补程序,最终只是添加了另一个依赖项。希望这有助于其他使用Mono的C#开发人员。此代码最初是为.NET Framework 2.0编写的。它不是花哨的,也没有真正记录好。我的解决方案只是本身使用Xlib枚举窗口并返回标题与所描述标题匹配的所有窗口。
在X11Wrapper.cs中:
xwininfo
在Linux.Utilities.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#DefaultRootWindow
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);
}
}
脚注:我最初声明我不是C开发人员(事情发生了变化,我学习了C)所以我对使用互操作自己实现功能犹豫不决。如果你最终使用Xlib,那么就像我一样,考虑使用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);
}
}
}
作为Xlib API参考。它在C中,但我发现在C#中转换为PInvokable函数和marshable结构非常容易。还要考虑一些好的注意事项。另一个帮助翻译的好资源是直接使用源来查找低级类型的定义,以帮助找到C#等价物。这样的事情应该对你很有帮助:tronche