无法获得窗口句柄?

问题描述 投票:3回答:1

我一直在搜索,试图找到我的困境的答案,但似乎无法找到一个有效的答案。我正在尝试用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。没有其他方法可以获得窗口句柄吗?提前致谢!

c# linux mono xlib
1个回答
1
投票

是的,我知道这是我之前的问题,但我现在正在回答这个问题,因为在我自己找到解决方案之后,我一直忘记回答它。我最初使用@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

© www.soinside.com 2019 - 2024. All rights reserved.