最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Setting focus to a Windows application from Node-JS - Stack Overflow

programmeradmin1浏览0评论

I have a NodeJS application running on Windows that needs to display and switch the focus to a running Windows application when a user does a certain action. I have been using the node-ffi package to make windows API calls but have not been able to make it switch focus consistently. Here is the code I am using. It successfully gets the HWND of a running Calculator app, but then tries to switch focus to that HWND and it only works sometimes:

    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);   

This combination of commands seems to work most consistently of the ones I have tried, but it does not work all the time. If the window I want to switch focus to is minimized it will always pop to the top. If the window is not minimized, but just behind another window, it will only be shown intermittently. I am not sure how to consistently to get a running windows application to always move to the top of the order, even if it is currently minimized.

I have a NodeJS application running on Windows that needs to display and switch the focus to a running Windows application when a user does a certain action. I have been using the node-ffi package to make windows API calls but have not been able to make it switch focus consistently. Here is the code I am using. It successfully gets the HWND of a running Calculator app, but then tries to switch focus to that HWND and it only works sometimes:

    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);   

This combination of commands seems to work most consistently of the ones I have tried, but it does not work all the time. If the window I want to switch focus to is minimized it will always pop to the top. If the window is not minimized, but just behind another window, it will only be shown intermittently. I am not sure how to consistently to get a running windows application to always move to the top of the order, even if it is currently minimized.

Share Improve this question asked Sep 9, 2016 at 23:37 KeithTheBipedKeithTheBiped 8821 gold badge10 silver badges22 bronze badges 3
  • You say both, that it always works for minimized windows as well as, that it doesn't work consistently. Which one is true? – IInspectable Commented Sep 10, 2016 at 0:18
  • You don't check for errors. Read the docs for SetForegroundWindow especially the list of conditions. – David Heffernan Commented Sep 10, 2016 at 7:21
  • @IInspectable It will always bring a minimized window to the top. If a window is not minimized, but is only behind another window, it will only bring it to the top intermittently. – KeithTheBiped Commented Sep 12, 2016 at 14:30
Add a comment  | 

1 Answer 1

Reset to default 19

I've worked out the following solution which works well in all circumstances to bring a window to the top. First it will get the window handle to a running instance of the Calculator application, then it will bring it topmost and focus it.

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)
发布评论

评论列表(0)

  1. 暂无评论