●キーカスタマイズ
管理者IDとパスワードを忘れない為に、早速日記を書く。
年末から更新してきた聞々ハヤえもんだが、そろそろキーカスタマイズ機能をつけることにする。以下の流れで開発を行っていく。
(1)動的にアクセラレータテーブルを管理する CAcceleratorTable クラスを作る。
※メンバ関数として、Create, Destroy, Add, Delete 関数を持つ。
(2)キーボードショートカットの選択にホットキーコントロールの使用を考えている為、CHotKeyCtrl クラスを作る。
※デフォルトのホットキーコントロールでは、スペースキー等入力不可なキーがあるのでサブクラス化できるようにしておく事。
(3)キーカスタマイズ用ウィンドウを管理する CKeySettingWnd_MainWnd クラスを作る。
※CFrameWnd クラスを継承する事。
(4)「システム→キー操作」メニューを追加。
※修正対象は、CMenu_MainWnd クラスと CMainWnd クラス。
これが済んだらホットキーに対応して、ウィンドウが非アクティブな場合でも操作ができるようにする。
さーて、作るぞ。
というわけで、まず、「(1)動的にアクセラレータテーブルを管理する CAcceleratorTable クラス」を書いてみた。
//----------------------------------------------------------------------------
// AcceleratorTable.h : アクセラレータテーブルの管理を行う
//----------------------------------------------------------------------------
#ifndef AcceleratorTableH
#define AcceleratorTableH
#include <windows.h>
//----------------------------------------------------------------------------
// アクセラレータテーブルの管理を行うクラス
//----------------------------------------------------------------------------
class CAcceleratorTable
{
public: // 関数
CAcceleratorTable() : m_hAccel(0) { }
virtual ~CAcceleratorTable() { Destroy(); }
virtual BOOL Add(BYTE fVirt, WORD key, WORD cmd)
{
// ハンドルが存在しない場合は新たに作成する
if(!m_hAccel)
{
ACCEL accel[1];
ZeroMemory(&accel, sizeof(ACCEL));
accel[0].fVirt = fVirt;
accel[0].key = key;
accel[0].cmd = cmd;
Create(accel, 1);
}
else
{
int nAccel = GetNum();
ACCEL * pAccel = new ACCEL[nAccel + 1];
Copy(pAccel, nAccel);
pAccel[nAccel].fVirt = fVirt;
pAccel[nAccel].key = key;
pAccel[nAccel].cmd = cmd;
Create(pAccel, nAccel + 1);
delete [] pAccel;
}
return m_hAccel ? TRUE : FALSE;
}
virtual int Copy(LPACCEL lpAccelDst, int cAccelEntries)
{
if(!m_hAccel) return 0;
return CopyAcceleratorTable(m_hAccel, lpAccelDst, cAccelEntries);
}
virtual BOOL Create(LPACCEL pAccel, int nAccel)
{
Destroy();
m_hAccel = CreateAcceleratorTable(pAccel, nAccel);
return m_hAccel ? TRUE : FALSE;
}
virtual BOOL Delete(BYTE fVirt, WORD key, WORD cmd)
{
if(!m_hAccel) return FALSE;
int nAccel = GetNum();
ACCEL * pAccel = new ACCEL[nAccel];
Copy(pAccel, nAccel);
BOOL bFound = FALSE; // 同じエントリが見つかったかどうか
for(int i = 0; i < nAccel; i++)
{
if(pAccel[i].fVirt == fVirt && pAccel[i].key == key && pAccel[i].cmd == cmd)
bFound = TRUE;
if(bFound) // 見つかったら、1つずつ前に移動
{
pAccel[i].fVirt = pAccel[i + 1].fVirt;
pAccel[i].key = pAccel[i + 1].key;
pAccel[i].cmd = pAccel[i + 1].cmd;
}
}
if(bFound) Create(pAccel, nAccel - 1);
delete [] pAccel;
return m_hAccel ? TRUE : FALSE;
}
virtual BOOL Destroy()
{
BOOL bSuccess = FALSE;
if(m_hAccel)
{
bSuccess = DestroyAcceleratorTable(m_hAccel);
m_hAccel = 0;
}
return bSuccess;
}
// エントリ数を得る
virtual int GetNum() { return Copy(NULL, 0); }
private: // メンバ変数
HACCEL m_hAccel;
public: // メンバ変数の取得
operator HACCEL() const { return m_hAccel; }
};
//----------------------------------------------------------------------------
#endif
これで、動的にアクセラレータテーブルを管理する事ができる。
次。「(2)キーボードショートカットの選択にホットキーコントロールの使用を考えている為、CHotKeyCtrl クラス」を作る。まあ、今までのコントロールと同じイメージ。
//----------------------------------------------------------------------------
// HotKeyCtrl.h : ホットキーコントロールの管理を行う
//----------------------------------------------------------------------------
#ifndef HotKeyCtrlH
#define HotKeyCtrlH
#include <commctrl.h>
#include "Wnd.h"
//----------------------------------------------------------------------------
// ホットキーコントロールの管理を行うクラス
//----------------------------------------------------------------------------
class CHotKeyCtrl : public CWnd
{
public: // 関数
CHotKeyCtrl() { }
virtual ~CHotKeyCtrl() { }
virtual BOOL Create(HWND hParentWnd)
{
Destroy();
INITCOMMONCONTROLSEX ic;
ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
ic.dwICC = ICC_HOTKEY_CLASS;
InitCommonControlsEx(&ic);
m_hWnd = CreateWindow(HOTKEY_CLASS, "", WS_CHILD, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hParentWnd, 0, GetModuleHandle(NULL), NULL);
if(!m_hWnd) return FALSE;
SetProc();
return TRUE;
}
};
//----------------------------------------------------------------------------
#endif
実際に使うホットキーコントロールは、こいつを継承して作る。
次。「(3)キーカスタマイズ用ウィンドウを管理する CKeySettingWnd_MainWnd クラス」を作る。
キーカスタマイズ用ウィンドウには、ショートカット羅列用のリストビューと追加ボタン、変更ボタン、デフォルトの復元ボタン、OKボタン、キャンセルボタンがある。追加ボタン、変更ボタンを押すと、ショートカット入力用の別ウィンドウが表示される。ショートカット入力用ウィンドウには、コマンド選択用コンボボックス、ホットキーコントロール、OKボタン、キャンセルボタンがある。
コマンド名については、キーカスタマイズ用ウィンドウが管理する。GetCommandName関数を持っており、ID→コマンド名、コマンド名→IDの相互変換が可能。