第120章 簡単にウィンドウを作る


今回は、左のようなプログラムを作ります。 (256色で見るときれいに見えないのでなるべく6万 5千色以上で見てください)
グラフィックスのプログラムのサンプルなどによく出てくる ものです。では、早速プログラムを見てみましょう。

// dlltest2.cpp #define STRICT #include <windows.h> #include "dll02.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); char szClassName[] = "dlltest2"; //ウィンドウクラス int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!InitApp(hCurInst, (WNDPROC)WndProc, (LPCTSTR)szClassName)) return FALSE; if (!InitInstance(hCurInst, nCmdShow, (LPCTSTR)szClassName)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id, i, red; PAINTSTRUCT ps; HDC hdc; RECT rc; switch (msg) { case WM_PAINT: GetClientRect(hWnd, &rc); hdc = BeginPaint(hWnd, &ps); for (i = 0; i < rc.bottom; i++) { red = 255 -i; MyDraw(hdc, 0, i, rc.right, i, RGB(red, 0, 0)); if (red < 0) red = 255; } EndPaint(hWnd, &ps); break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

いつもに比べて何か短いですね。自作関数のInitApp, InitInsance関数の 本体がありません。また、dll02.hをインクルードしています。 プロシージャのWM_PAINTでMyDrawという自作関数を使っています。 もうお気づきのことと思いますが、前2者はいつもほとんど変わり映えせず、 後者は便利そうなのでdllにしてしまいました。このdllをWindowsの ディレクトリにコピーしておくとプログラム作りが多少楽になるかもしれません。 (実際はたいして楽にもならない)

気を付けることはこのプログラムをビルドするときにdllを作った際に 生じたlibファイルをプロジェクトにリンクするのを忘れないということです。

では、dllのプログラムを見てみましょう。

// dll02.h #define EXPORT extern "C" __declspec(dllexport) EXPORT BOOL CALLBACK MyDraw(HDC, int, int, int, int, COLORREF); EXPORT BOOL CALLBACK InitApp(HINSTANCE, WNDPROC, LPCTSTR); EXPORT BOOL CALLBACK InitInstance(HINSTANCE, int, LPCTSTR);

ヘッダファイルです。このファイルはdllを作るときと、これを呼び出すプログラムを 作るときの両方で必要になります。

// dll02.cpp #include <windows.h> #include "dll02.h" int WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, PVOID pvReserved) { return TRUE; } EXPORT BOOL CALLBACK MyDraw(HDC hdc, int x1, int y1, int x2, int y2, COLORREF crColor) { HPEN hPen, hOldPen; hPen = CreatePen(PS_SOLID, 1, crColor); hOldPen = SelectObject(hdc, hPen); MoveToEx(hdc, x1, y1, NULL); LineTo(hdc, x2, y2); SelectObject(hdc, hOldPen); DeleteObject(hPen); return TRUE; } EXPORT BOOL CALLBACK InitApp(HINSTANCE hInst, WNDPROC WndProc, LPCTSTR szClassName) { 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 = NULL; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } EXPORT BOOL CALLBACK InitInstance(HINSTANCE hInst, int nCmdShow, LPCTSTR szClassName) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるdll", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

前回に引き続きDllMain関数では何もせずにTRUEを返しています。

InitAppとInitInstance関数はいつもと同じです。dll内で使っている インスタンスハンドルはすべて呼び出し側のプログラムから もらっている点に注意してください。

プログラム自体は難しくないのですが、dllを作るときはコンパイラ等の 設定に十分注意してください。ソースファイルを置くディレクトリにも 工夫する必要があります。VC++5.0を使っている人は1つのワークスペース内に dllを作るプロジェクトと、これを呼び出すプロジェクトを作っておくと 比較的便利です。さらに筆者はdllとヘッダファイルを呼び出し側の ディレクトリにコピーするバッチファイルを作って利用しています。 dllを修正したら、バッチを実行します。その後呼び出し側のプログラムを ビルドすると間違いが起こりません。


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

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