読み出し側ではGetStdHandle関数で標準入力をhReadにリダイレクトしておきます。
次に、通常は読み出し専用スレッドを用意してパイプからの読み出しを
専門に行います。
では、プログラムを見てみましょう。
普通のメニューのリソース・スクリプトです。// process02x.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END END
特に説明は不要でしょう。// process02x.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); DWORD WINAPI MyThreadProc(LPVOID); char szClassName[] = "process02x"; //ウィンドウクラス HINSTANCE hInst; HANDLE hRead; HANDLE hThread; DWORD dwThreadID; char szBuf[256]; HWND hMain;
いつもと同じです。int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "子プロセス", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; hMain = hWnd; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }
WM_CREATEメッセージが来たら、標準入力をリダイレクトしておきます。//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; HDC hdc; PAINTSTRUCT ps; switch (msg) { case WM_CREATE: hRead = GetStdHandle(STD_INPUT_HANDLE); if (hRead == INVALID_HANDLE_VALUE) { MessageBox(hWnd, "GetStdHandle Error", "Error", MB_OK); return 0; } else { hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MyThreadProc, NULL, 0, &dwThreadID); if (!hThread) { MessageBox(hWnd, "CreateThread Error", "Error", MB_OK); return 0; } } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 10, 10, szBuf, strlen(szBuf)); EndPaint(hWnd, &ps); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; } case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { if (hThread) { if( CloseHandle(hThread)) MessageBox(hWnd, "スレッドハンドルクローズ成功", "OK", MB_OK); } DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }
プログラム終了時にはスレッドハンドルのクローズを忘れないようにします。
パイプからの読み出しはReadFile関数を使います。第1引数にパイプの読み出しハンドル を指定します。読み出し後InvalidateRect関数でクライアント領域を更新して 読み込まれた内容を表示します。DWORD WINAPI MyThreadProc(LPVOID lpParam) { DWORD dwResult; BOOL bSuccess; MessageBox(NULL, "スレッドが作られました", "OK", MB_OK); while (1) { bSuccess = ReadFile(hRead, szBuf, sizeof(szBuf), &dwResult, NULL); if (!bSuccess) { break; } InvalidateRect(hMain, NULL, TRUE); } MessageBox(NULL, "スレッドを抜けます", "OK", MB_OK); return 0; }
読み出し側ではこんな簡単なプログラムで済みます。さて、プログラムを注意深く見ていくと hRead, hMainなどのグローバル変数がスレッド間共有変数となっています。 しかしhReadは子スレッドが作られる前に親スレッドで書き込みが起こり、以後親では アクセスしていません。hMainについても同様です。したがって特別の手立ては不要です。
Update 03/Dec/1999 By Y.Kumei