◆DOS窓から窓を開く
メモリ操作,スレッド操作のAPIは,ともにコンソールアプリケーションから利用できます.Win32ではコンソール,つまりDOS窓と通常のウィンドウはほぼ同様に扱うことができます.
それでは,コンソールアプリケーションから通常のウィンドウは開けないのでしょうか.
CreateWindow()などでは,インスタンスハンドルが必要です.WinMain()とmain()の引き数を比べてみても,システムからインスタンスハンドルだけは得ることができません.
ところが,Win32ではどのアプリケーションも同じインスタンスハンドルの値を取ることがわかっています.そこで,GetWindowLong()を使ってデスクトップのインスタンスハンドルを得て,それで代用してみることにします.
リスト8.c1では定番helloのウィンドウをDOS窓から開きます.VCではDOS窓から起動されるアプリケーションをコンソールアプリケーションと呼びmain()で始まります.このmain()にメッセージループを置いてここからメッセージの配信も行えます.リスト8.c1ではメッセージループとウィンドウプロシージャの両方でメッセージの内容をDOS窓にモニタするようにしています.これを見るとメッセージループから配送されるメッセージ以外にも直接ウィンドウプロシージャを呼び出しているメッセージがあることがわかります.前者がPostMessage()による配信,後者がSendMessage()による配信ということです.
あまりこのような使い方は紹介されていませんが,大規模なDOSプログラムの一部の操作をウィンドウ化する場合やデバッグ用の隠し技として利用する価値はあるように思います.
<リスト8.c1>コンソール版hello:list08c1.cpp
// list08c1 コンソール版定番hello
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
void main()
{
MSG msg;
HWND hWnd;
WNDCLASSEX wndclass; // 新しくつくるウインドクラス
HINSTANCE hi = (HINSTANCE)GetWindowLong(HWND_DESKTOP, GWL_HINSTANCE);
// DESKTOPからインスタンスを得る
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.style = 0;
wndclass.lpfnWndProc = WndProc; // このクラスの持つウインドプロシージャ
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hi;
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndclass.hIconSm = LoadIcon( NULL, IDI_WINLOGO );
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = "wh04co"; //このクラスの名前
if(! RegisterClassEx( &wndclass )) return; // ウィンドクラスの登録
// できないと終了
hWnd = CreateWindow( "wh04co", // クラスの名前
"Windows example",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, // ウィンドウの属性
CW_USEDEFAULT, CW_USEDEFAULT, // 位置大きさは指定しない
CW_USEDEFAULT, CW_USEDEFAULT, // WS_OVERLAPPEDWINDOWのときのみ可
HWND_DESKTOP, // 親はディスクトップ
NULL, hi, NULL );
while( GetMessage( &msg, NULL, 0, 0 ) ){
printf( "GetMsg %8X %8X %8X %8X\n",
msg.message, msg.wParam, msg.lParam, msg.time );
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return ;
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMessage,
WPARAM wp, LPARAM lp )
{
PAINTSTRUCT ps;
char *p = "hello";
printf("WinPro %8X %8X %8X\n",(int)iMessage ,(int)wp, (int)lp);
switch( iMessage ){
case WM_PAINT:
printf("WM_PAINT \n");
BeginPaint( hWnd, &ps );
TextOut(ps.hdc, 10, 10, p, strlen( p ));
EndPaint( hWnd, &ps );
break;
case WM_DESTROY: //必ず必要,DefWindowProcでは処理されない
PostQuitMessage(0);
return 0;
default:
return DefWindowProc( hWnd, iMessage, wp, lp );
}
return 0;
}
<図8.c1>リスト8.c1の実行画面:zu08c1.bmp
ダウンロード
実行ファイル