Javascript 从节点JS设置Windows应用程序的焦点

Javascript 从节点JS设置Windows应用程序的焦点,javascript,node.js,winapi,node-ffi,Javascript,Node.js,Winapi,Node Ffi,我有一个在Windows上运行的NodeJS应用程序,当用户执行某个操作时,它需要显示并将焦点切换到正在运行的Windows应用程序。我一直在使用node ffi包进行windows API调用,但未能使其一致地切换焦点。这是我正在使用的代码。它成功获取正在运行的计算器应用程序的HWND,但随后尝试将焦点切换到该HWND,并且它仅在以下情况下工作: var ffi = require('ffi'); var intPtr = ref.refType('long');

我有一个在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应用程序始终处于最顶端,即使它当前已最小化。

我已经找到了以下解决方案,在所有情况下都能很好地将窗口置于顶端。首先,它将获取计算器应用程序的运行实例的窗口句柄,然后将其置于最顶端并对其进行聚焦

var ffi = require('ffi-napi')

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)

你可以说,它总是适用于最小化的窗口,也可以说,它的工作方式并不一致。哪一个是正确的?你不检查错误。阅读SetForegroundWindow的文档,尤其是条件列表。@IInspectable它将始终将最小化窗口置于顶部。如果一个窗口没有最小化,而只是在另一个窗口之后,它只会间歇性地将其置于顶部。我在哪里可以找到有关user32 api的更多信息?@PauloHenrique Wiki条目提供了一些有关user32.dll的高级信息。要深入了解,您可以查看Windows API下的MSDN。我的解决方案中使用的大多数函数的文档可以在“Windows”部分找到:。否则,WINAPI编程是一个很深的黑洞,为了获得更多信息,我会找到一个介绍性的指南,其中有很多,以便对Windows操作系统的一些概念、数据结构、,等等。提供给
FindWindowA
的值是进程的标题。调用
AttachThreadInput
非常不合适。如果有的话,您必须在调用
setforegroughindow
之前调用它(以确定调用成功的先决条件)。调用
AttachThreadInput
时发生错误。这一切似乎都是基于猜测。如果你不知道你的代码为什么工作,它也不知道。这里也是这样。@Luke:采用窗口标题和/或窗口类名。这些都与进程名称无关。