我在Windows上运行的NodeJS应用程序需要在用户执行某项操作时显示并将焦点切换到正在运行的Windows应用程序。我一直在使用node-ffi包来进行Windows API调用,但却无法使其一致地切换焦点。这是我正在使用的代码。它成功获得正在运行的计算器应用程序的HWND,但随后尝试将焦点切换到该HWND,它只在以下情况下有效:
var ffi = require('ffi');
var intPtr = ref.refType('long');
var user32 = new ffi.Library('user32', {
'FindWindowA': ['long', [ 'string', 'string']],
'SetForegroundWindow': ['bool', ['long']],
'BringWindowToTop': ['bool', ['long']],
});
var winToSetOnTop = user32.FindWindowA(null,"calculator")
var res = user32.ShowWindow(winToSetOnTop, 9);
res = user32.SetForegroundWindow(winToSetOnTop);
res = user32.BringWindowToTop(winToSetOnTop);
这些命令的组合似乎与我尝试过的命令最为一致,但它并不是一直有效。如果我想要将焦点切换到的窗口最小化,它将始终弹出到顶部。如果窗口没有最小化,但只是在另一个窗口后面,它将只是间歇性地显示。我不确定如何始终如一地使正在运行的Windows应用程序始终移动到订单的顶部,即使它当前已最小化。
答案 0 :(得分:7)
我已经制定了以下解决方案,该解决方案适用于所有情况,可以将窗口置于顶部。首先,它将获得一个正在运行的Calculator应用程序实例的窗口句柄,然后它将把它带到最顶端并将其聚焦。
var user32 = new ffi.Library('user32', {
'GetTopWindow': ['long', ['long']],
'FindWindowA': ['long', ['string', 'string']],
'SetActiveWindow': ['long', ['long']],
'SetForegroundWindow': ['bool', ['long']],
'BringWindowToTop': ['bool', ['long']],
'ShowWindow': ['bool', ['long', 'int']],
'SwitchToThisWindow': ['void', ['long', 'bool']],
'GetForegroundWindow': ['long', []],
'AttachThreadInput': ['bool', ['int', 'long', 'bool']],
'GetWindowThreadProcessId': ['int', ['long', 'int']],
'SetWindowPos': ['bool', ['long', 'long', 'int', 'int', 'int', 'int', 'uint']],
'SetFocus': ['long', ['long']]
});
var kernel32 = new ffi.Library('Kernel32.dll', {
'GetCurrentThreadId': ['int', []]
});
var winToSetOnTop = user32.FindWindowA(null, "calculator")
var foregroundHWnd = user32.GetForegroundWindow()
var currentThreadId = kernel32.GetCurrentThreadId()
var windowThreadProcessId = user32.GetWindowThreadProcessId(foregroundHWnd, null)
var showWindow = user32.ShowWindow(winToSetOnTop, 9)
var setWindowPos1 = user32.SetWindowPos(winToSetOnTop, -1, 0, 0, 0, 0, 3)
var setWindowPos2 = user32.SetWindowPos(winToSetOnTop, -2, 0, 0, 0, 0, 3)
var setForegroundWindow = user32.SetForegroundWindow(winToSetOnTop)
var attachThreadInput = user32.AttachThreadInput(windowThreadProcessId, currentThreadId, 0)
var setFocus = user32.SetFocus(winToSetOnTop)
var setActiveWindow = user32.SetActiveWindow(winToSetOnTop)