第119章 簡単なdllを作る


今回は、簡単なdllの作り方を解説します。Windowsのディレクトリを 見ると星の数ほどdllが存在します。dllを自分で作れるようになると すごく、プログラムがうまくなったような自己満足に浸れます。

dllはご存じのようにDynamic Link Librariesの略です。その名の通り 実行時にリンクされるライブラリです。これに対してプログラムを 作る時点でリンクされるライブラリはスタティック・ライブラリなどと 言われます。こちらの方はすでにC言語編 第54章で解説してあるので 参照してみてください。

簡単なdllはその名の通り作り方も簡単です。ただ、初めて作る方は コンパイラの設定などで少し手間取るかもしれません。VC++5.0の統合環境を 例にとって解説します。

メニューから「ファイル」「新規作成」「プロジェクト」(タブ)を選択します。 そこから「Win32 Dynamic-Link Library」を選びます。プロジェクト名を 入力します。(ここではdll01としました)あとは、普通のプログラムを 作るのと同じです。

では、早速例題を見てみましょう。

// dll01.cpp #include <windows.h> #include "dll01.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; }

DllMain関数は普通のプログラムのWinMain関数と思ってください。 引数もこのようにしておいてください。ここでは、何もせずに TRUEを返すだけです。

MyDrawという自作関数は普通にプログラムを書くときと同じです。 中身を見ればすぐわかると思いますが、(x1, y1)から(x2, y2)へ crColorの色で直線を描画する関数です。

この関数の頭についている語句はこの通りにしておいてください。

// dll01.h #define EXPORT extern "C" __declspec(dllexport) EXPORT BOOL CALLBACK MyDraw(HDC, int, int, int, int, COLORREF);

#defineの行はおまじない的にこのようにしておいてください。 あとは、自作関数のプロトタイプを書いておきます。 このヘッダファイルはdllを呼び出す方のプログラムでも使います。

さてこれをビルドすると目的のdllが出来上がりです。 この時dll01.dllの他にdll01.libというファイルも作られます。

今作ったdll01.dllがきちんと動作するか呼び出しもとのプログラムを 作りましょう(test01.exe) これは、普通のプログラムを作るのと同じです。ただ先ほどのdll01.lib をプロジェクトに参加させておく必要があります。

// test01.cpp #define STRICT #include <windows.h> #include "dll01.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); char szClassName[] = "test01"; //ウィンドウクラス 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; }

いつもと同じですが、dll01.hをインクルードしておいてください。

BOOL 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 = NULL; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { 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; }

いつもと同じです。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; HDC hdc; PAINTSTRUCT ps; switch (msg) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); MoveToEx(hdc, 0, 0, NULL); LineTo(hdc, 100, 100); MyDraw(hdc, 100, 0, 0, 100, RGB(255, 0, 0)); MoveToEx(hdc, 0, 50, NULL); LineTo(hdc, 100, 50); 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 0L; }

WM_PAINTのところを見てください。MyDraw関数で(100, 0)から(0, 100)の赤い直線を 描画しています。この関数がきちんと動作するか実際に動かして試してみてください。 もちろんdll01.dllはtest01.exeから見えるところに存在しないといけません。 (test01.exeと同じディレクトリか、Windowsのディレクトリなど)


左のように赤い直線が描画されれば成功です。


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

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