1

我遇到了 SetWindowPos 无法可靠地将外部进程窗口置于 z 顺序顶部的问题。我可以将窗户放在前面,例如:

     NativeMethods.SetWindowPos(hwnd, new IntPtr(-1), Left, Top, Width, Height, 0x10);
     NativeMethods.SetWindowPos(hwnd, new IntPtr(-2), Left, Top, Width, Height, 0x10);

虽然它不是 100% 的时间。经过一番阅读,我发现了一些东西。

SetWindowPos 文档状态:

    To use SetWindowPos to bring a window to the top, the process that owns the window must have SetForegroundWindow permission.

MSDN 上的一篇文章然后指出

    A process that is started with UIAccess rights has the following abilities:
    * Set the foreground window.

AllowSetForeground 提及

    The calling process must already be able to set the foreground window

我已经签署了我的 .exe 并启用了 UIAccess,以便我可以在清单中设置前景窗口:

     <requestedExecutionLevel  level="highestAvailable" uiAccess="true" />

我的程序启动,我收到 UAC 提示请求许可。然后我测试 UIAccess、管理员权限和 TokenElevationType。前 2 个返回 true,第 3 个返回 TokenElevationTypeFull。尽管我的新代码仍然遇到同样的问题。

我的代码是:

    uint processid=0;
    NativeMethods.GetWindowThreadProcessId(hwnd, out processid);
    NativeMethods.AllowSetForegroundWindow((int)processid);
    NativeMethods.SetWindowPos(hwnd, IntPtr.Zero, Left, Top, Width, Height, 0x10);
    NativeMethods.RedrawWindow(hwnd, IntPtr.Zero, IntPtr.Zero, NativeMethods.RedrawWindowFlags.Erase | NativeMethods.RedrawWindowFlags.Invalidate | NativeMethods.RedrawWindowFlags.NoChildren);
    NativeMethods.RedrawWindow(hwnd, IntPtr.Zero, IntPtr.Zero, NativeMethods.RedrawWindowFlags.Erase | NativeMethods.RedrawWindowFlags.Invalidate | NativeMethods.RedrawWindowFlags.UpdateNow | NativeMethods.RedrawWindowFlags.AllChildren);
4

1 回答 1

1

您想要做的与 Windows 为防止行为不端的程序从用户手中夺取控制权而制定的(复杂的)规则背道而驰。(控制不仅仅意味着输入焦点,还包括对可见和不可见的控制。)尽管您的意图可能与用户的意图一致,但您所要求的与破坏性程序通常试图做的没有区别。

其他方法可以通知用户非前景窗口需要注意。FlashWindowEx例如,退房。您还可以考虑弹出通知气球的托盘图标。这些似乎是适当且有效的解决方案。

于 2013-03-15T16:37:04.360 回答