2016-09-09 114 views
6

我有一個在Windows上運行的NodeJS應用程序,需要在用戶執行特定操作時顯示並將焦點切換到正在運行的Windows應用程序。我一直在使用node-ffi包進行windows API調用,但一直沒有能夠使其切換焦點。這是我正在使用的代碼。它成功地獲取HWND正在運行的計算器應用程序,但隨後試圖將焦點切換到該HWND,它只能有時:將焦點設置爲來自Node-JS的Windows應用程序

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

你說這兩個,它始終適用於最小化窗口以及它不一致工作。哪一個是真的? – IInspectable

+0

您不檢查錯誤。閱讀SetForegroundWindow的文檔,特別是條件列表。 –

+0

@IInspectable它總是會將最小化的窗口帶到頂部。如果一個窗口沒有被最小化,但是隻在另一個窗口的後面,它只會間歇性地將其置於頂端。 – KeithTheBiped

回答

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) 
+0

我在哪裏可以找到更多關於user32 API的信息? –

+0

@PauloHenrique Wiki條目https://en.wikipedia.org/wiki/Windows_USER給出了一些有關user32.dll的高級信息。對於更深的潛水,您可以在Windows API下查看MSDN。我的解決方案中使用的大多數功能的文檔可以在「Windows」部分找到:https://msdn.microsoft.com/en-us/library/windows/desktop/ff468919(v=vs.85).aspx 。否則,WINAPI編程是一個深刻的黑洞,對於更多信息,我會找到一個介紹性指南,其中有很多,以便概述一些Windows操作系統概念,數據結構等。 – KeithTheBiped

+0

提供的值到'FindWindowA'是該過程的標題。 – Luke

相關問題