こちらの方が、少しだけ効率のよいコードを出力できます。
ファイル名:editcolor.c
#include <windows.h> //API関数ポインタの型定義 typedef COLORREF (WINAPI *SETBKCOLOR)(HDC,COLORREF); typedef COLORREF (WINAPI *SETTEXTCOLOR)(HDC,COLORREF); typedef LRESULT (WINAPI *CALLWINDOWPROC)(WNDPROC,HWND,UINT,WPARAM,LPARAM); //HSP側で用意するデータ typedef struct{ SETBKCOLOR pSetBkColor; //API関数ポインタ SETTEXTCOLOR pSetTextColor; // 〃 CALLWINDOWPROC pCallWindowProc; // 〃 WNDPROC pPrevWndProc; //元のウインドウプロシージャ HBRUSH hBrush; //背景を描くブラシのハンドル COLORREF bkcolor; //文字の背景色 COLORREF textcolor; //文字の色 } hspstruct; LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { extern hspstruct * volatile pHspdata; //外部変数 hspstruct *pData=pHspdata; //この部分のコードを書き換える switch(uMsg){ case WM_CTLCOLOREDIT: pData->pSetBkColor((HDC)wParam,pData->bkcolor); pData->pSetTextColor((HDC)wParam,pData->textcolor); return (LRESULT)(pData->hBrush); default: return pData->pCallWindowProc(pData->pPrevWndProc,hwnd,uMsg,wParam,lParam); } }
外部のポインタから値を受け取ることで、仮アドレスによる意図しない影響を受けないようにします。(volatileも念のために付けておきます。)
外部変数を使用するようにしたため、それを記述したソースファイルが必要になります。
これはアセンブリファイルで用意します。
ファイル名:subfile.asm
.386 .model tiny,C externdef pHspdata:ABS pHspdata equ 0eeeeeeeeh END
subfile.asmをソースと同じフォルダに置いて、以下のバッチファイルを実行することでマシン語ファイル(拡張子
BIN)を作成できます。
LINK : warning L4055: start address not equal to 0x100 for /TINY
という警告が出ますが気にしないでください。
IDEを使用する場合はこちら。
ソースのファイル名と拡張子、VC++のインストール先を赤字部分に設定してください。
OSが Win9x,Meの場合はバッチファイルの「プロパティ」->「メモリ」->「環境変数の初期サイズ」を1024以上にしてください。
@SET file=editcolor @SET ext=c @echo off :コマンドライン用環境設定ファイル(VC++インストール時に作成されている) call "C:\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT" cl /c /FA /O2 /Fonul %file%.%ext% if errorlevel 1 goto error ml /c /Cp %file%.asm subfile.asm if errorlevel 1 goto error link16 /TINY /NODEFAULTLIBRARYSEARCH /NOIGNORECASE %file%.obj subfile.obj,%file%.bin,nul,,, if errorlevel 1 goto error echo =====================作成成功========================== goto fin :error echo =====================エラー======================== if exist %file%.bin del %file%.bin :fin if exist %file%.asm del %file%.asm if exist %file%.obj del %file%.obj if exist subfile.obj del subfile.obj if "%OS%"=="Windows_NT" pause>nul
IDEを使用する場合はsubfile.asmの設定で「このファイルをビルドしない」にチェックを入れてから、ソースファイルのカスタムビルド設定で以下のコマンドを入力します。
cl /c /FA /Fonul /Fa$(IntDir)\ /O2 $(InputPath) if errorlevel 1 goto error ml /c /Cp /Fo$(IntDir)\ $(IntDir)\$(InputName).asm $(InputDir)\subfile.asm if errorlevel 1 goto error link16 /TINY /NODEFAULTLIBRARYSEARCH /NOIGNORECASE $(IntDir)\$(InputName).obj $(IntDir)\subfile.obj, $(TargetDir)\$(InputName).bin,nul,,, if errorlevel 1 goto error echo =====================作成成功========================== goto fin :error echo =====================エラー======================== if exist $(TargetDir)\$(InputName).bin del $(TargetDir)\$(InputName).bin :fin
作成されたEDITCOLOR.BINをバイナリエディタなどでダンプ表示すると以下のようになります。
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
00000000 8B 44 24 08 56 8B 35 EE-EE EE EE 3D 33 01 00 00 |汽$.V.5・・=3...
00000010 74 1B 8B 4C 24 14 8B 54-24 10 51 8B 4E 0C 52 50 |t.記$.亀$.Q起.RP
00000020 8B 44 24 14 50 51 FF 56-08 5E C2 10 00 8B 56 14 |汽$.PQ.V.^ツ..儀.
00000030 57 8B 7C 24 14 52 57 FF-16 8B 46 18 50 57 FF 56 |W弓$.RW..祈.PW.V
00000040 04 8B 46 10 5F 5E C2 10-00 00 00 00 |.祈._^ツ.....
ソースファイルで定義した0xEEEEEEEEが見えていますので、リロケートする位置は0x00000007ということが分かります。
この部分をHSP側で書き換えます。
もし該当箇所が複数ある時はソースファイルの値を適当な値に変えてからもう一度マシン語ファイルを作成してください。
マシン語ファイルの使用例
WA_MACROを使用しています。
#include "winapi.as" #define GWL_WNDPROC $FFFFFFFC #define BS_SOLID $00000000 textcolor=$ff00ff ;文字の色 bkcolor=$ffffcc ;背景の色 relocpos=7 ;リロケーション位置 ;マシン語ファイルを読み込む filename="editcolor.bin" exist filename if strsize==-1:dialog filename+"がみつかりません。":end sdim func,strsize bload filename,func ;マシン語で使用するAPI ll_getproc lpSetBkColor,"SetBkColor",hdll_GDI32 ll_getproc lpSetTextColor,"SetTextColor",hdll_GDI32 ll_getproc lpCallWindowProc,"CallWindowProcA",hdll_USER32 ;元のウインドウプロシージャ GetWindowLong PRMHWND,GWL_WNDPROC lpPrevWndProc=dllret ;エディットボックスの背景を描くブラシ logbrush=BS_SOLID,bkcolor,0 CreateBrushIndirect ptr(logbrush) hBrush=dllret ;必要なデータを配列にまとめる hspdata=lpSetBkColor,lpSetTextColor,lpCallWindowProc,lpPrevWndProc,hBrush,bkcolor,textcolor ;リロケート getaddr pHspdata,hspdata getaddr ppHspdata,pHspdata memcpy func,ppHspdata,4,relocpos sdim s,256 mesbox s,640,480,1 idMesBox=stat ;サブクラス化 SetWindowLong PRMHWND,GWL_WNDPROC,ptr(func) ;エディットボックスの再描画を指示 InvalidateRect PRMHOBJ(idMesBox),NULL,TRUE stop