Hatena::ブログ(Diary)

applet@Hatena このページをアンテナに追加 RSSフィード

2008-10-25

非公開関数 SetForegroundWindow // FIXME: completely useless. why ?

Linux & Mac版が公開され、機能追加要求も出ており、いくつか なるほど と思った要望もあったので、「のどか」のソースコードを眺めていた。

そうしたら「窓使いの憂鬱」には、ヘルプに出ていない非公開関数があることを発見。

(ヘルプに記載が無いだけで、mayu-mode.el には書いてある。nodoka-mode.el には、4.04で追加した、IconColor の記述が漏れていたので追加する。)

1) &SetForegroundWindow(ウィンドウクラス名, 0か1 , ウィンドウタイトル名)
2) &ClipboardChangeCase(bool)
3) &LogClear

2)の &ClipboardChangeCaseは、専用の&ClipboardUpcaseWord, &ClipboardDowncaseWord があるから、公開しても需要が無いのだろう。

3) &LogClear は、ログウィンドウのログをクリアする機能だが、その必然性は低い感じがする。

1) &SetForegroundWindow は、指定したウィンドウをフォアグランドにする機能で、例えば下記のように指定する。

key C-S-F = &SetForegroundWindow(/Notepad/)

一応動くこともあるのだが、たまに動かない。だから非公開なのかと思い、さらにソースコードを追いかけると、ちゃんと意思が書いてあった。

 // FIXME: completely useless. why ?

了解です。

というわけで、機能追加要求の話は、頭の隅において、こちらの &SetForegroundWindow()のワークアラウンド強化にトライしてみようと思う。


追伸。とりあえずのコードを示します。14:19

ただし、フォアグランドにしたあとで、他のWindowをフォアグランドにすると、のどか からキーバインド変更が、できなくなったケースがあったので、大変残念だけど、ヘルプには記載しない。


参考にしたところ

http://hpcgi1.nifty.com/~kokubu/index.cgi?%B5%BB%BD%D1%A5%E1%A5%E2#i4

http://d.hatena.ne.jp/gsf_zero1/20071211/p1

http://d.hatena.ne.jp/ytqwerty/20050811

 

bool setForegroundWindow(HWND i_hwnd)
	{
	int nForegroundID = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
	int nTargetID = GetWindowThreadProcessId(i_hwnd, NULL);

	if(nForegroundID == nTargetID)		// 同じだったので、SetForegroundWindowを実行して終了。
		{
		OutputDebugString(L"It's Me\n");
		if(IsIconic(i_hwnd))						// 最小化されていたら、元に戻す。
			{
			OutputDebugString(L"Iconic: try ShowWindow\n");
			ShowWindow(i_hwnd, SW_RESTORE);
			}
		OutputDebugString(L"try SetForegroundWindow\n");
		SetForegroundWindow(i_hwnd);
		}
	else
		{
		if(IsIconic(i_hwnd))
			{
			OutputDebugString(L"Iconic: try ShowWindowAsync\n");
			ShowWindowAsync(i_hwnd, SW_RESTORE);	// 最小化されていたら、元に戻す。
			}

		if (!AttachThreadInput(nTargetID, nForegroundID, TRUE))
			{
				DWORD sp_time;

				OutputDebugString(L"try SetActiveWindow and someone\n");
				SetActiveWindow(i_hwnd);	// SystemParametersInfo失敗避け

				SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &sp_time, 0);
				SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (void *)0, 0);

				SetActiveWindow(i_hwnd);
				SetForegroundWindow(i_hwnd);

				SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (void *)sp_time, 0);

				AttachThreadInput(nTargetID, nForegroundID, FALSE);
			}
		else
			{	// AttachThreadInputに失敗したが駄目押しで下記を実行。
				OutputDebugString(L"try BringWindowToTop and someone\n");
				SetActiveWindow(i_hwnd);
				SetForegroundWindow(i_hwnd);
				BringWindowToTop(i_hwnd);
			}
		}
	return true;
	}

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証