gpt4 book ai didi

c# - 无法获取窗口句柄?

转载 作者:太空狗 更新时间:2023-10-29 11:17:33 24 4
gpt4 key购买 nike

我到处搜索,试图找到解决我的困境的答案,但似乎找不到有效的答案。我正在尝试用 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);
}
}

( Source )

这尤其令人沮丧,因为似乎别无选择。我正在尝试像这样捕获一个窗口句柄:

[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);
}

注意:代替“myPid”的是一个正确的进程 ID。将“myPid”替换为有效的进程 ID。是的,我确实确保替换的“myPid”是一个有效的进程 ID,并且我的代码没有抛出任何错误,表明我使用的任何进程 ID 都是无效的。

这不会使我的应用程序崩溃,但几乎每次我调用 XRaiseWindow 时它都会打印:

X11 Error encountered: 
Error: BadWindow (invalid Window parameter)
Request: 12 (0)
Resource ID: 0x0
Serial: 121
Hwnd: <null>
Control: <null>

这显然是因为 Process.MainWindowHandle 返回 IntPtr.Zero。没有其他方法可以获取窗口句柄吗?提前致谢!

最佳答案

是的,我知道我很久以前就问过这个问题,但我现在正在回答这个问题,因为在我自己找到解决方案后,我一直忘记回答这个问题。我最初使用@SushiHangover 的解决方案但并不是很喜欢它,因为我觉得依赖外部程序 (xwininfo) 是一个修补程序,最终只是添加了另一个依赖项。希望这可以帮助其他使用 Mono 的 C# 开发人员。此代码最初是为 .NET Framework 2.0 编写的。它并不花哨,也没有很好地记录下来。我的解决方案是自己使用 Xlib 本地枚举窗口,并返回标题与描述的标题匹配的所有窗口。

在 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#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);
}
}

在 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)所以我对使用互操作自己实现功能犹豫不决。如果你最终像我一样更多地使用 Xlib 那么考虑使用 tronche作为 Xlib API 引用。它在 C 中,但我发现它很容易转换为 C# 中的 PInvokable 函数和可编码结构。也有一些好的注释需要考虑。另一个有助于翻译的好资源是直接使用源代码查找低级类型的定义,以帮助找到 C# 等效项。像这样的东西应该对你有很大帮助:http://refspecs.linuxbase.org/LSB_4.0.0/LSB-Desktop-generic/LSB-Desktop-generic/libx11-ddefs.html

关于c# - 无法获取窗口句柄?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42449050/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com