我对SetWindowPos函数有一个奇怪的问题。此功能用于通过以下代码将应用程序置于顶部:
if (!SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, NO_FOCUS_FLAGS))
Log.LogError("SetWindowPos HWND_TOPMOST returned false");
if (!SetWindowPos(this.Handle, HWND_NOTOPMOST, 0, 0, 0, 0, NO_FOCUS_FLAGS))
Log.LogError("SetWindowPos HWND_NOTOPMOST returned false");
在大多数情况下,我能够从Windows中看到正常的事件堆栈:
WndProc(): m - msg=0x46 (WM_WINDOWPOSCHANGING) hwnd=0x21016 wparam=0x0 lparam=0x20d688 result=0x0
WndProc(): m - msg=0x14 (WM_ERASEBKGND) hwnd=0x21016 wparam=0xffffffffc60128f1 lparam=0x0 result=0x0
WndProc(): m - msg=0x135 (WM_CTLCOLORBTN) hwnd=0x21016 wparam=0xffffffff950128ae lparam=0x40f2e result=0x0
WndProc(): m - msg=0x47 (WM_WINDOWPOSCHANGED) hwnd=0x21016 wparam=0x0 lparam=0x20d688 result=0x0
WndProc(): m - msg=0x46 (WM_WINDOWPOSCHANGING) hwnd=0x21016 wparam=0x0 lparam=0x20d688 result=0x0
WndProc(): m - msg=0x135 (WM_CTLCOLORBTN) hwnd=0x21016 wparam=0xffffffffc60128f1 lparam=0x40f2e result=0x0
WndProc(): m - msg=0x47 (WM_WINDOWPOSCHANGED) hwnd=0x21016 wparam=0x0 lparam=0x20d688 result=0x0
但有时我得到以下内容:
WndProc(): m - msg=0x46 (WM_WINDOWPOSCHANGING) hwnd=0x104f4 wparam=0x0 lparam=0x3ad6cc result=0x0
WndProc(): m - msg=0x14 (WM_ERASEBKGND) hwnd=0x104f4 wparam=0x26012ce9 lparam=0x0 result=0x0
WndProc(): m - msg=0x135 (WM_CTLCOLORBTN) hwnd=0x104f4 wparam=0x90127a1 lparam=0x105de result=0x0
WndProc(): m - msg=0x46 (WM_WINDOWPOSCHANGING) hwnd=0x104f4 wparam=0x0 lparam=0x3ad6cc result=0x0
在这种情况下,SetWindowPos()返回成功,但应用程序没有达到顶峰。
这个问题太难重现,我无法轻易测试。
有谁知道WM_WINDOWPOSCHANGED缺少什么? 我该如何解决这个问题?
提前致谢!
答案 0 :(得分:0)
让我把任何程序放在前面的最有效的方法是:
它每次都适用于我,它从我尝试的任何应用程序中窃取焦点。 就像全屏显示Citrix或远程桌面一样,我的程序就在前台。
诀窍是制造窗户"思考"我们的进程和目标窗口(hwnd)通过附加线程(使用AttachThreadInput API)和使用替代API来关联:BringWindowToTop。
public static void AttachedThreadInputAction(Action action)
{
var foreThread = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
var appThread = GetCurrentThreadId();
bool threadsAttached = false;
try
{
threadsAttached =
foreThread == appThread ||
AttachThreadInput(foreThread, appThread, true);
if (threadsAttached) action();
else throw new ThreadStateException("AttachThreadInput failed.");
}
finally
{
if (threadsAttached)
AttachThreadInput(foreThread, appThread, false);
}
}
用法:
public const uint SW_SHOW = 5;
///<summary>
/// Forces the window to foreground.
///</summary>
///<hwnd>The HWND.</param>
public static void ForceWindowToForeground(IntPtr hwnd)
{
AttachedThreadInputAction(
() =>
{
BringWindowToTop(hwnd);
ShowWindow(hwnd, SW_SHOW);
});
}