|
1.概要
本ページは、私がバイナリエディタを作成する際に使用した技術を
紹介することを目的としています。
紹介する技術は、必ずしもこれでないと実現できないというわけではありません。
方法は他にもたくさんあると思います。
2.必要な機能
バイナリエディタには、最低限、以下の機能が必要です。
・ファイルを開き、データをリードする。
・ファイルを開き、データをライトする。
・リードデータを、16進表示する。
・16進データを、バイナリデータに変換する。
・'0'〜'9'、'A'〜'F'までの文字以外の入力を制限する。
・1画面に収まらないデータ量の場合は、画面をスクロールさせる。
3.機能実現の為に必要な技術
では、2.の機能を実現する為に必要な技術とは何でしょう?
ただ単にエディットボックスへ入力されたキーを、16進表示で2桁ずつ
表示するだけじゃないか〜、と言われるかもしませんが、これが結構大変なんです。
まず、キー入力制限。これは、WM_KEYDOWNで処理しますか?16進数を2桁ずつ表示し、
入力もこの制限を守るには?
などなど、課題は山積みです。また、実現方法も幾通りもある為、自分がどれをチョイス
するのがベスト見極める必要があります。
4.私が使用した技術
では、私が使用した技術を紹介致します。
(但し、私が使用した技術が最良ではありません。
もっといい方法があると思いますので、参考までにご覧下さい。)
(1)ローカルフック
(2)エディットボックスのサブクラス化
(3)カーソル位置の取得・設定
(4)アクティブコントロールの管理
(5)画面再描画
※画面スクロールについては、まだ実現出来ていない為、ご紹介できません。
(1) ローカルフック
ローカルフックは、キー入力制限をかける為に使用します。
ローカルフックは、SetWindowsHookEx関数で実現できます。
以下に、キーボードフックの引数指定を紹介します。
・第1引数・・・フック関数タイプ。
キーボードフックを張る場合は、ここに"WH_KEYBOARD"を指定します。
・第2引数・・・フックプロシージャのアドレス。
・第3引数・・・インスタンスハンドル。
ローカルフックの場合は、自分のインスタンスハンドルを設定します。
・第4引数・・・フックするスレッドID。
ローカルフックの場合は、自分のスレッドIDを設定します。
例)HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD,
(HOOKPROC)HookProc,
hInst,
GetWindowThreadProcessId(hWnd, NULL));
これで、フック設定は完了です。戻り値は、フックプロシージャ、フック解除に
指定しますので、大切に保管しておきます。
次に、フックプロシージャです。以下に、例を紹介します。
例)LRESULT CALLBACK HookProc(int nCode,
WPARAM wparam,
LPARAM lparam)
nCodeが0未満の場合は、次のフックプロシージャへ流します。
それ以外の場合は、wparam(押されたキーコード)をチェックします。
キーを無効にしたい場合は、return( TRUE )で抜けるようにします。
次のフックプロシージャへ流したいときは、
return CallNextHookEx(hHook, nCode, wparam, lparam)
で抜けるようにします。
フックが必要なくなったら、きちんとフックを解除してあげます。
下記に解除の例を紹介します。
例)UnhookWindowsHookEx(hHook)
(2) エディットボックスのサブクラス化
エディットボックスのサブクラス化は、カーソル移動を拾う為に行います。
サブクラス化は、GetWindowLong関数・SetWindowLong関数を使用します。
設定例を以下に紹介します。
例)SubhWnd = (FARPROC)GetWindowLong(GetDlgItem(hWnd, エディットID),
GWL_WNDPROC);
SetWindowLong(GetDlgItem(hWnd, エディットID),
GWL_WNDPROC, (LONG)SubProc);
LRESULT CALLBACK SubProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
return (CallWindowProc((WNDPROC)SubhWnd, hWnd, msg, wp, lp));
}
(3) カーソル位置の取得・設定
カーソル位置の取得・設定は、16進2桁表示を行う際に、16進2桁同士の間にある、
空白部分にカーソルを移動させない為に使用します。
取得の例を、以下に紹介します。
例)SendMessage(エディットボックスハンドル,
EM_GETSEL,
(WPARAM)&選択開始位置格納用変数,
(LPARAM)&選択終了位置格納用変数);
Y座標 = SendMessage(エディットボックスハンドル,
EM_LINEFROMCHAR , -1 , 0);
設定の例を、以下に紹介します。
例)SendMessage(エディットボックスハンドル,
EM_SETSEL,
(WPARAM)選択開始位置,
(LPARAM)選択終了位置);
(4) アクティブコントロールの管理
アクティブコントロールの管理は、キーボードフック対象となるコントロールか
どうか判定する為に使用します。
キーボードフック対象以外のコントロールがアクティブな場合は、入力制限は
かけないようします。
アクティブコントロールは、EN_SETFOCUSメッセージから認識します。
例)if( HIWORD(wparam) == EN_SETFOCUS ){
if( LOWORD(wparam) == フック対応エディットID ){
HookCtrl = 1;
}else{
HookCtrl = 0;
}
}
(5) 画面再描画
キーボードフック宣言にかからないキーボード入力が発生した場合、入力した16進数を、
文字列表示用エディットボックスに表示する必要があります。
まず、入力されたかどうかは、EN_UPDATEメッセージで認識します。
例)if( HIWORD(wp) == EN_SETFOCUS ){
if( LOWORD(wp) == エディットボックスID ){
文字列編集処理();
}
}
<質問・要望など>
上記内容に対しての質問、要望などは常に受け付けております。
以下のメールフォームか、掲示板へ書き込みをお願いします。
メール送信フォーム
掲示板
|