【问题标题】:Bring a window to foreground without window handle在没有窗口句柄的情况下将窗口置于前台
【发布时间】:2015-04-03 21:58:45
【问题描述】:

我有一个 Windows CE 嵌入式 6.0 应用程序,它在后台打开另一个应用程序,我想把另一个应用程序放在前面。我首先使用第三方应用程序的 MainWindowHandle 尝试了 SetParent,但它没有用。然后我再次在同一个 MainWindowHandle 上尝试了 SetActiveWindow,但它没有用。这让我相信 MainWindowHandle 搞砸了,当我在控制台上打印它时,它总是 0。这让我想到了我的第一个问题:应用程序的开发人员是否有可能忘记提及 MainWindow 是什么?还是在 .NET 中自动分配?

其次,既然这种方法失败了,我尝试 EnumWindows,然后获取每个窗口的 ID 并将其与我知道的所需程序的进程 ID 匹配。这给了我一个异常 0x80131515 说“EnumWindows”不受支持。我已经从 CoreDll 导入了 EnumWindows 就好了。第二个问题:这个错误的原因可能是什么?我做错了什么?

对不起!下面是一些代码(假设 VCProcess 已经启动):

    [DllImport("coredll.dll")]
static extern int EnumWindows(CallbackDef callback, int lParam);

    [DllImport("coredll.dll")]
    static extern int GetWindowThreadProcessId(IntPtr hWnd, int pid);

    static void Main()
    {
        callBackPtr = new CallBackPtr(Report);  
        EnumWindows(callBackPtr, 0);
    }

    public static bool Report(int hwnd, int lParam)
    {
        int pid = 0;
        GetWindowThreadProcessId(hWnd, pid);
        if (pid == VCProcessId)
        {
            SetForegroundWindow(hWnd);
        }
        MessageBox.show("Window handle is "+hwnd);
        return true;
    }

【问题讨论】:

  • 问题缺少一些重要的东西:代码。

标签: c# .net windows windows-ce compact-framework2.0


【解决方案1】:

您的 OEM 不得包含对 EnumWindows 的支持。你可以试试FindWindow

我可能会 P/Invoke SetForegroundWindow 来执行此操作。如果应用程序在后台,SetActiveWindow 将不起作用。

-保罗赫


编辑

P/Invoking EnumWindows 不能抛出 System.NotSupportedException(除非你在代码中抛出它)并且 GetLastError() 不会返回 HRESULT COR_E_NOTSUPPORTED。你的代码有问题。

【讨论】:

  • 我怀疑 EnumWindows 可以从操作系统中省略。我想看看实际的调用代码。
  • 我也不这么认为,但 MSDN 页面中有一条说明表明它可以。 “……有些设备可能不支持这个 API。” (除非他们仅仅因为在所有 WCE API 上都坚持该免责声明)msdn.microsoft.com/en-us/library/ms960376.aspx
  • 是的,这就是包罗万象的免责声明。我会采取严重的内核黑客来删除它,无论如何删除它可能会破坏 Shell。
  • FindWindow 结合 SetForegroundWindow 为我工作。我会将此标记为答案。谢谢:)
【解决方案2】:

在遇到同样的问题并解决后,我正在回答这个问题。

虽然 OEM 可能不会将操作系统的某些部分作为 WindowsCE 的一部分包含在内(这是其模块化架构的本质),但像 EnumWindows 这样的调用或大多数其他低级别调用也是如此,本质上是操作系统的一部分,删除它们会很疯狂。

我实际上收到了来自 Microsoft 工程师 (!) 的一条消息,指出问题在于回调的定义方式。虽然我尝试了不同的方法(委托、intPtr 与 int 等),但他给出了以下答案,实际上在 WindowsCE 5/6 中适用于不同设备:

"[“来自 .Net/C# 应用程序的 EnumWindows 调用导致 NotSupportedException 0x80131515”错误,因为它仅支持整数返回类型:I2、I4 等。这适用于所有回调方法,并且可能因调用而异正在使用]"

所以不要像你一样定义你的回调(我也尝试过委托、WinProcs 和其他失败的方法),将其定义为:

[DllImport("coredll.dll")]
[return: MarshalAs(UnmanagedType.I4)]
private static extern int EnumWindows(IntPtr callPtr, int param);

效果很好!!

以下是我实现这种方法的工作代码,并且可以在运行 PocketPC/WindowsCE 等的不同设备中完美运行:

public delegate int CallBackPtr(int hwnd, int param);

[DllImport("coredll.dll")]
[return: MarshalAs(UnmanagedType.I4)]
private static extern int EnumWindows(IntPtr callPtr, int param);

private static List<IntPtr> windows = new List<IntPtr>();

private static int CallBackMethod(int hwnd, int param)
{
    windows.Add(new IntPtr(hwnd));
    return 1;   
}

private static void GetAllWindowsHandles()
{
   // using a delegate does NOT work.
   //EnumWindows(delegate(IntPtr wnd, IntPtr param)
   //{
   //    windows.Add(wnd);
   //    return true;
   //}, IntPtr.Zero);

   CallBackPtr callbackPtr = CallBackMethod;
   IntPtr cb = Marshal.GetFunctionPointerForDelegate(callbackPtr);
   EnumWindows(cb, 0);
}

CJ。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-28
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多