MASATOの開発日記


前の開発日記 次の開発日記 一覧

2002/06/10

実装と設計は、どちらが重要か?となるといつも悩みます。 世間一般では設計の方が重要だとなっていますが、 私は実装のバグに悩まされると実装が大事だと思い、 設計のバグに悩まされると設計が大事だと思ってしまいます。

どんなうまい設計をしても、実装がうまくできないと全然動作しないので、 実装というのは侮れない、大事な工程であると思います。

しかし、実装や設計のバグを解析していて感じたこととしては、 実装のバグは、どんなややこしいバグでも、なんとか見つけて潰せば終わりですが、 設計のバグは、なんとか見つけても、潰せないのです。 直すとなると、大幅な変更が必要になり、その変更がまたバグを生んで・・・と大変なことになります。 そのため、バグがあるのが分かっていながら、なんとも出来ないという悲惨な状況になってしまうことが多いです。 というわけで、やはり設計の方が大切です。
ああ世間一般と同じ結論に達してしまいました。オチが無くてごめんなさい。

CSplitterWndを用いて分割したViewのフォーカスをTABキーで移動する方法

環境Visual C++ 6.0

1つのフレームウィンドウ内に、複数のウィンドウがあると、やはりTABキーで移動したくなります。 ダイアログではOSが処理してくれますが、分割ウィンドウでは自分で処理を追加する必要があります。

一番簡単な方法は、アクセラレータに追加することです。 ID=ID_NEXT_PANE、キー=VK_TAB、及びID=ID_PREV_PANE、キー=Shift + VK_TABの2つを アクセラレータに追加しましょう。

しかし、アクセラレータに登録すると、 フォーカスを移動して欲しくないときも移動されてしまうことがあります。 例えば、CListViewを使用し、インプレイス編集を可能にした時です。 アイテム名をインプレイスで編集中にTABキーを押すと、他のViewに移ってしまい、 不便を感じる場合があります。
これを防ぐには、OnKeyDown(あるいはそれに類する関数)に以下のようなコードを 挿入します。仮想キーコードは変数nCharに格納されていると仮定します。

switch (nChar){
case VK_TAB:
  if ((GetKeyState(VK_SHIFT) & 0x8000) == 0){
    OnNextPaneCmd(ID_NEXT_PANE);
  }else {
    OnNextPaneCmd(ID_PREV_PANE);
  }
  break;
}

OnNextPaneCmdは、元々ID_NEXT_PANE及びID_PREV_PANEコマンドを処理するための関数です。 これを直接呼び出すことによりView間のフォーカス移動が可能になりました。

次のように、コマンドメッセージを送る形でも同様の機能を実現できます。

CDATA[switch (nChar){
case VK_TAB:
  if ((GetKeyState(VK_SHIFT) & 0x8000) == 0){
    AfxGetMainWnd()->SendMessage(WM_COMMAND, MAKEWPARAM(ID_NEXT_PANE, 0), NULL);
  }else {
    AfxGetMainWnd()->SendMessage(WM_COMMAND, MAKEWPARAM(ID_PREV_PANE, 0), NULL);
  }
  break;
}

尚、既にご存知かもしれませんが、最初からアクセラレータに VK_F6(ID_PANE_NEXT)及びShift + VK_F6(ID_PREV_NEXT)が登録されています。 必要に応じてアクセラレータから削除してしまっても良いでしょう。

前の開発日記 次の開発日記 一覧