« NetHack 3.4.3 における祭壇の利用法 | トップページ | JNetHack::倉庫番::2F »

2005年2月 1日 (火)

他プロセスのコンソールアプリケーションを全画面表示にする

あんまり自信が無いんだけど、この手の資料の日本語のものが無いので参考までに。


void	Process::SetFullScreenMode()
{
	//プロセス起動直後にAttachConsoleしようとするとたいていうまく行かない。
	Sleep(1000);
	if( AttachConsole( TB_ENFORCE( API(), GetProcessId( mProcess ) ) ) )
	{
		TB_ENFORCE_TO_THROW
		{
			DllProc< BOOL (WINAPI*) (HANDLE,DWORD,COORD*) >	SetConsoleDisplayMode( FilePath( FolderPath::GetWindowsFolder(), "kernel32.dll" ), "SetConsoleDisplayMode" );
			COORD	coord;
			const int CONSOLE_FULLSCREEN_MODE = 1;
			TB_ENFORCE( API(), SetConsoleDisplayMode()( TB_ENFORCE( API(INVALID_HANDLE_VALUE), GetStdHandle( STD_OUTPUT_HANDLE ) ), CONSOLE_FULLSCREEN_MODE, &coord ) );
		}
		TB_ENFORCE_CATCH
		{
			//まずコンソールウインドウのハンドルを何とかしてとってくる。
			//そのためにウインドウタイトルをユニークなIDで置き換える。
			//同じアルゴリズムを使うプログラムと競合する可能性が(0%に近いけど)あるのでIdはGUIDを使う。
			std::string	guid = "{6A47F119-E665-4533-99CB-BDF3ABE2B1D0}";
			//タイトルをバックアップ
			StringReceiver	title;
			TB_ENFORCE( API(), GetConsoleTitle(title.Lock( 1024 ), 1023 ) );
			//置き換える。
			TB_ENFORCE( API(), SetConsoleTitle(guid.c_str()) );
			//別プロセスなのでウインドウタイトルをセットするためのコンテキストスイッチを起こして待つ。
			Sleep(50);
			//ウインドウタイトルを検索してハンドルを得る。
			//win9x系のコンソールのウインドウクラスはtty
			HWND	hConWnd = TB_ENFORCE( API<HWND>(NULL), FindWindow("tty", guid.c_str()) );
			//タイトルを元に戻す
			TB_ENFORCE( API(), SetConsoleTitle(title.UnLock().c_str()) );

			// pause before changing to fullscreen
			//Sleep(450);

			//コンソールウインドウにWM_COMMAND,57359,0を送ると全画面化する。
			SendMessage( hConWnd, WM_COMMAND, 57359, 0 );
		}
		TB_ENFORCE( API(), FreeConsole() );
	}
}

XPのSP2ならAttachConsole→SetConsoleDisplayModeで一発。
ただしSetConsoleDisplayModeはMSDN::English::Win32API::SetConsoleDisplayModeに"Header Declared in Wincon.h; include Windows.h."って書いてあるのに最新版のプラットフォームSDKのWincon.hにも無いのでKernel32.dllから気合でLoadLibrary&GetProcAddressしないとだめです。

挙句にAttachConsoleがなぜかかなりの確率で失敗します。
エラーメッセージは「ハンドルが無効です。」…いや引数ハンドルじゃないし。ハンドルはハンドルで有効だし。もちろんプロセスIDだってあってるよ!
ていうかGetLastError設定してないんじゃなかろか。


while( !AttachConsole( mProcessID ) )
	Sleep(500);
みたいなコードを書いても一度失敗したらなぜか二度と成功しません(アタッチしたい相手先のコンソールは元気に動いてます)。
というわけでAttachConsoleで失敗したら泣く泣く素直にあきらめてます。

また、Win9x系ではコンソールウインドウにWM_COMMANDのWPARAMが57359を送ると全画面化するそうです。
(Ref: http://mureakuha.com/koodikirjasto/635)

ただしこの技はNTでは使えません。
WPARAMが違うのかと思ってSPYでWM_COMMANDメッセージをみようと思ったらSPYがサブクラス化に失敗するので全ウインドウのWM_COMMANDを見張ったところ、確かにモードが変わったとき異なるWPARAMが送られてたのでそいつを上のコードの57359の変わりに送ってみたところ…変化なし。
SetConsoleDisplayModeはなんか"Requires Windows XP."だそうで、結局2000とかのコンソールを最大化させる手段はAlt+Enterをコンソールウインドウに送りつけるとかしかないかも。

|

« NetHack 3.4.3 における祭壇の利用法 | トップページ | JNetHack::倉庫番::2F »

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



« NetHack 3.4.3 における祭壇の利用法 | トップページ | JNetHack::倉庫番::2F »