----[wpmod.h]---- class wpModule{ protected: HINSTANCE handle; public: wpModule(HINSTANCE h=NULL){handle=h;} HINSTANCE getHandle() { return handle; } HINSTANCE operator()() { return handle; } HACCEL loadAccel(const char* acname) { return LoadAccelerators(handle, (LPSTR)acname); } }; extern wpModule* Module;handle はモジュールを識別するインスタンスハンドル、 Module は自分自身を指すポインタである。 loadAccel はアクセラレーターキーのロードを行う。 リソースのロードはEXE と DLLで共通なので、基底クラスで宣言する。
ここで使うモジュールクラスは次の本に出ていたものを簡略化したものである。
「Windowsオブジェクト指向プログラミング Windows++」
(Paul DiLascia著 翔泳社 ¥6,800)
----[wpdll.h]---- class wpDll:public wpModule{ private: friend BOOL WINAPI DllMain(HINSTANCE , DWORD , LPVOID ); void startup0(HINSTANCE h); BOOL startup (LPVOID lpvReserved);// ユーザー定義 BOOL terminal(LPVOID lpvReserved);// ユーザー定義 }; extern wpDll Dll;friend 宣言は private メンバーにアクセスするための おまじないで、 startup0 は必須の初期化処理である。
----[wpdll.cpp]---- #include <windows.h> #include "wpmod.h" #include "wpdll.h" wpModule* Module=NULL; wpDll Dll; void wpDll::startup0(HINSTANCE h) { Module=this; handle=h; } BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason){ case DLL_PROCESS_ATTACH: Dll.startup0(hInstance); return Dll.startup( lpvReserved); case DLL_PROCESS_DETACH: return Dll.terminal(lpvReserved); case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return TRUE; }DLL がロードされるとき、まず startup0 が呼ばれる。 startup0 でハンドルと自分自身のポインタを設定する。
----[test4dll.cpp]---- #include <windows.h> #include "wpmod.h" #include "wpdll.h" extern "C"{ int WINAPI _declspec(dllexport) TestFunc2(int arg1,int arg2); }; int _declspec(dllexport) TestFunc1(int arg1,int arg2) { return (arg1-arg2); } int WINAP _declspec(dllexport) TestFunc2(int arg1,int arg2) { return (arg1-arg2); } // FALSE を返すと DLL は Unload される BOOL wpDll::startup(LPVOID lpvReserved){ return TRUE;} BOOL wpDll::terminal(LPVOID lpvReserved ){ return TRUE;}
----[wpapp.h]---- class wpApp:public wpModule{ private: friend int PASCAL WinMain(HINSTANCE , HINSTANCE ,LPSTR , INT ); void startup0(HINSTANCE); int run(); int startup(LPCSTR);// ユーザー定義 int main(INT ); // ユーザー定義 int terminal(int); // ユーザー定義 void MsgTransaction(MSG&msg); HACCEL KeyAccel; public: }; extern wpApp App;
----[wpapp.cpp]---- #include <windows.h> #include "wpmod.h" #include "wpapp.h" wpModule* Module=NULL; wpApp near App; void wpApp::startup0(HINSTANCE hi) { Module=this; handle=hi; KeyAccel=loadAccel("KeyAccel"); } void wpApp::MsgTransaction(MSG&msg) { BOOL tflag=FALSE;//処理済み if(KeyAccel) tflag=TranslateAccelerator(msg.hwnd,KeyAccel,&msg); if(tflag) return; TranslateMessage(&msg); DispatchMessage(&msg); } int wpApp::run() { MSG msg; while (GetMessage(&msg,NULL,0,0)) MsgTransaction(msg); return msg.wParam; } //****************************************************************** int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) { int rc; App.startup0(hInstance); rc=App.startup(lpCmdLine); if(rc==0) rc=App.main(nCmdShow); if(rc==0) rc=App.run(); rc=App.terminal(rc); return rc; }startup0 は DLL クラスと同様にハンドルと自分自身のポインタを設定し、 次にアクセラレータをロードする。
----[test4.cpp]---- #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include <string.h> #include <stdio.h> #include "test4res.h" #include "wpmod.h" #include "wpapp.h" /*<---------------------------------------------------------------------->*/ HWND hwndMain; //Main window handle (途中省略) //***************************************************************** //*** ユーザー定義ルーチン ***************************************** //***************************************************************** int wpApp::startup(LPCSTR cmdline){return 0;} int wpApp::main(INT nCmdShow) { if (!InitApplication())return -1; if ((hwndMain = Createtest4WndClassWnd()) == (HWND)0) return -1; ShowWindow(hwndMain,nCmdShow); return 0;} int wpApp::terminal(int rc){return rc;}startup はコマンドラインの処理を行う。
初期化のルーチンが LibMain になっていたのを DllEntryPoint に修正。 Visual C と同じだと勘違いしていた。
外部公開名にアンダースコアが付かないようにするために、 以前はコンパイラオプションで -u- を指定していたが、 これだと C のライブラリ関数の呼び出しができなくなる副作用があるので、 WINAPI を付ける方法に変更した。
DLL 外部公開名にアンダースコアが付かないようにするために、 以前はコンパイラオプションで -u- を指定していたが、 これだと C のライブラリ関数の呼び出しができなくなる副作用があるので、 WINAPI を付ける方法に変更した。
2000.12.05 修正