----[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 修正