他のプログラムよりも集中する必要がある Firefox 拡張機能を開発しています。window.focus() は、他の Firefox ウィンドウでのみ機能します。これは可能ですか?
1 に答える
これは、私がここで回答した別の質問に似ています: xul:panel position on multiple monitor
js-ctypes によってロード/使用される外部 DLL の助けを借りて、あなたが望むものを達成することができました。OS レベルのウィンドウ フォーカスを操作するには、次の 2 つのことを実行できる必要があります。
- 問題の Firefox ウィンドウを見つけます
find_window
(以下の JavaScript 関数)。 - ウィンドウにフォーカスします(
window_focus
以下の関数)。
ウィンドウ ハンドルを見つける最も簡単な方法は、ウィンドウ タイトルを他のウィンドウ タイトルと衝突しない予測可能なもの (たとえば、MD5 の合計"your-app"+(new Date())
) に変更し、そのウィンドウを探しているすべての OS レベルのウィンドウを列挙することであることがわかりました。タイトル ( find_window
)。
ウィンドウ ハンドルを取得したら、window_focus
(以下で定義) を呼び出して OS レベルのウィンドウにフォーカスすることができます。
Win32 の例:
外部 DLL を JavaScript にバインドするための基本は次のとおりです。この例は Win32 のみを対象としていますが、同じプロセスがそれぞれに適用されます。
3 つの部分があります。
- プラットフォーム固有の (つまり、Win32) API をロード/バインドするための特権 JavaScript コード
- 外部 DLL の CPP ヘッダー ファイル
- 外部 DLL の CPP ソース ファイル
msvcr100.dllに応じて、後の2つのファイルとコンパイルされたwmctrl.dllを使用してVS2010で単純なGUI DLLプロジェクトを構築し、依存関係ウォーカーを使用して、js-ctypesで使用するためにDLLによってエクスポートされた「プレーンC」シンボルを見つけました。
特権 JavaScript コード (例: アドオン コード):
// import js-ctypes
const {Cc,Ci,Cu} = require("chrome"); // you probably don't need this line.
var file=null, lib=null, ctypes = {};
Cu.import("resource://gre/modules/ctypes.jsm", ctypes);
var ctypes = ctypes.ctypes;
// build platform specific library path (yours will be named/located differently)
var filename = ctypes.libraryName("wmctrl");
var comp = "@mozilla.org/file/directory_service;1"; // read the docs for this!!!
var file = Cc[comp].getService(Ci.nsIProperties).get("CurProcD", Ci.nsIFile);
file.append("browser_code"); // a sub-folder
file.append(filename);
// get the JavaScript library interface (load the library)
var lib = ctypes.open(file.path);
// wmctrl_find_window: returing unsigned 32bit (long) "window handle"
// takes string "window title".
var find_window = lib.declare("?wmctrl_find_window@@YAKPAD@Z",
ctypes.stdcall_abi, ctypes.uint32_t,
ctypes.char.ptr);
// wmctrl_window_focus: takes unsigned 32bit (long) "window handle".
var window_focus = lib.declare("?wmctrl_window_focus@@YAXK@Z",
ctypes.stdcall_abi, ctypes.void_t,
ctypes.uint32_t);
wmctrldll.h
#ifdef WMCTRLDLL_EXPORTS
#define WMCTRLDLL_API __declspec(dllexport)
#else
#define WMCTRLDLL_API __declspec(dllimport)
#endif
WMCTRLDLL_API unsigned long wmctrl_find_window(char* find_title);
WMCTRLDLL_API void wmctrl_window_focus (unsigned long wid);
wmctrldll.cpp
typedef struct {
HWND hWnd;
char title[255];
} myWinSpec;
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
char String[255];
myWinSpec* to_find = (myWinSpec*) lParam;
// not a window
if (!hWnd) return TRUE;
// not visible
if (!IsWindowVisible(hWnd)) return TRUE;
// no window title
if (!GetWindowTextA(hWnd, (LPSTR)String, 255)) return TRUE;
// no title match
if (strcmp(String, to_find->title) != 0) return TRUE;
to_find->hWnd = hWnd;
return FALSE;
}
WMCTRLDLL_API void wmctrl_window_focus(unsigned long wid) {
SetForegroundWindow((HWND) wid);
}
WMCTRLDLL_API unsigned long wmctrl_find_window(char* find_title) {
myWinSpec to_find;
sprintf_s(to_find.title, sizeof(to_find.title), "%s", find_title);
to_find.hWnd = 0;
EnumWindows(EnumWindowsProc, (LPARAM)&to_find);
return (unsigned long) to_find.hWnd;
}
Linux (X11) と Mac OS X についても、それほど問題なく実行できました。