第245章 前章のクライアント側


今回は前章で作ったプログラムから呼び出される 子プロセス側を作成します。特に目新しいことはありません。



早速プログラムを見てみましょう。

// process03x.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)...", IDM_END END POPUP "パイプ(&P)" BEGIN MENUITEM "パイプに書き込み(&W)", IDM_WRITE END END ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 137, 67 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "パイプに書き込む" FONT 9, "MS Pゴシック" BEGIN EDITTEXT IDC_EDIT1,7,7,123,36,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN DEFPUSHBUTTON "OK",IDOK,7,46,50,14 PUSHBUTTON "キャンセル",IDCANCEL,80,46,50,14 END

普通のメニューと、ダイアログボックスのリソース・スクリプトです。

// process03x.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <windowsx.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE);LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); BOOL InitInstance(HINSTANCE, int); char szClassName[] = "process03x"; //ウィンドウクラス HANDLE hWrite; char szBuf[256]; HINSTANCE hInst;

継承されるハンドルをグローバル変数(hWrite)にしています。

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; hInst = hCurInst; 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座標 210, //幅 120, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

このへんはいつもと同じです。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; switch (msg) { case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_WRITE: DialogBox(hInst, "MYDLG", hWnd, (DLGPROC)MyDlgProc); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { if (hWrite) if (CloseHandle(hWrite)) MessageBox(hWnd, "hWriteをクローズしました", "OK", MB_OK); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

メニューからIDM_WRITEが選択されたらダイアログボックスを出します。

終了時にhWriteがNULLでない場合はCloseHandleで閉じます。

LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { DWORD dwWrite; char szStr[256]; switch (msg) { case WM_INITDIALOG: hWrite = GetStdHandle(STD_OUTPUT_HANDLE); if (hWrite == INVALID_HANDLE_VALUE) { MessageBox(hDlg, "hWriteが無効です", "OK", MB_OK); CloseHandle(hWrite); hWrite = NULL; } SetFocus(GetDlgItem(hDlg, IDC_EDIT1)); strcpy(szBuf, ""); return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: memset(szStr, ' ', sizeof(szStr)); szStr[255] = '\0'; WriteFile(hWrite, szStr, strlen(szStr), &dwWrite, NULL); Edit_GetText(GetDlgItem(hDlg, IDC_EDIT1), szBuf, sizeof(szBuf)); if (!WriteFile(hWrite, szBuf, strlen(szBuf), &dwWrite, NULL)) { MessageBox(hDlg, "書き込みエラーです", "Error", MB_OK); } CloseHandle(hWrite); hWrite = NULL; EndDialog(hDlg, IDOK); return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; } return FALSE; } return FALSE; }

ダイアログボックスのプロシージャです。

たったこれだけです。使い方は前章で作ったプログラムから このプログラムを起動します。そして、このプログラムのダイアログボックスに、 書き込みたい内容を記入します。すると、親プロセスのエディットコントロールに 内容が表示されます。

WM_INITメッセージが来たら、GetStdHandleで書き込みハンドルを取得します。 書き込みハンドルが有効でないときはCloseHandleで閉じてhWriteをNULLにしておきます。

エディットコントロールに文字列を書き込んで、OKボタンを押すと WriteFile関数でパイプにこの文字列を書き込みます。この関数が失敗したときは その旨メッセージボックスで知らせます。 成功しても失敗してもhWriteを閉じて、NULLにしておきます。 ダイアログボックスを開くたびにhWriteを取得するので閉じるときにはhWriteも閉じておきます。

もしメインウィンドウのプロシージャでhWriteを取得すると、次のような困った問題が起きます。
呼び出し側プログラムから、このプログラムが呼ばれたあとで親プログラムが終了してしまった 場合WriteFile関数が失敗しません。子プロセス側では、呼び出し元がいなくなったことに 気が付かない、ということが起こります。

このプログラムを単独で起動した場合、当然書き込みは失敗します。

いろいろな場合を想定して実験してみてください。簡単なプログラムですが結構奥が深いです。 また、匿名パイプを2本装備すると呼び出し側と子供側で双方向の通信ができるのでしょうか。 (親プロセスで書き込んだものを、子プロセスで表示、子プロセスで書き込んだものを親プロセスで 表示する)

これも実験してみてください。


[SDK第3部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 13/Dec/1999 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。