MASATOの開発日記 2001年2月


2/28

可変長配列を使いたい!と思ったらどういう選択肢があるだろうか。

  1. 自分で可変長配列クラスを作る。
  2. STLのvectorを使う。
  3. MFCのCArrayを使う。
ざっとこんなものだろう。ちなみに私はCArrayを使う。 自作クラスは、作るのに手間がかかるし、手間をかけてつくっても それがSTLやMFCよりも良いものを作れるとはあまり思えない。 また、Windows以外に移植することは無いので互換性は気にならない。 また、Window関係でMFCのクラスを使う事になるので、 MFCとSTLの両方を使うよりは、MFCだけ使った方が良いという判断だ。 なによりCString::Formatは非常に強力だ。

私は、コードは出来る限りネイティブに書く。 つまり、マクロをあまり使わずに、出来る限りC/C++の書式通りに書くという事だ。 Windows上で開発しているので、windows.hで定義されているのも 勝手にネイティブに含まれるとみなす。そしてLPCTSTRやUINT等も使っている。 しかし、これでは上で述べたような可変長配列は使えない。 よって、さらに範囲を広げて、MFCを使ったコードもネイティブとみなすことにする。 STLではなくてMFCを使っているあたりが「腐ったWindows開発者」とも言えそうだが。 STLとMFCのどちらか片方を選ぶとしたら、私はGUIの領域までカバーしているMFCを選ぶ。 本来STLで書ける場所はSTLで書いてそれで無理なところはMFCを使うべきなのかも しれないが、(多少機能が重なった)ライブラリを2つも使うのがイヤだ、という 理由もある。

このようにして、MFCのほかには、出来る限り余計なものを使わず、作らずにコードを 書くわけだ。なんでこうしているかと言うと、こうやって書かれたコードは、 同じMFCの他のプロジェクトに移植した場合、恐ろしい移植性を誇る。(Windows限定) MFCしか使われていないので、余計なものも必要なく、 ただ対象のコードだけを移せば完了するからである。これは結構便利だと思う。 ちなみにMFCを使っているとWindows以外のOSに移植しようとすると地獄をみると思うので 注意しましょう。

(Visual C++)MDIで、既存のドキュメントに新しくViewウィンドウを追加する方法。

MFCのMDIで、既に開かれているドキュメントにもう1つビューを追加する方法です。 ウィンドウ分割を使用する方法は、MSDNにサンプルもあるので、 もう1つウィンドウとしてビューを追加する方法を考えてみます。 メニューから何かコマンドを選ぶと、 現在開かれているドキュメントに新しいビューウィンドウが1つ追加される、という方針とします。

まず、Viewクラスを作成します。クラスウィザードを用いると簡単でしょう。
しかし、クラスウィザードを用いると、CxxxApp::InitInstanceに 余計なコードを加え、起動時にどのビューを用いるか選択を迫られるようなアプリになることがあります。
それで良いというのならば構わないのですが、方針と違いますので CxxxApp::InitInstanceに追加されたコードを削除しておきましょう。
次に、CxxxAppクラスにメンバ変数を追加します。
CMultiDocTemplate* m_lpxxxTemplate;
コンストラクタでNULLに初期化しておきましょう。
CxxxApp::CxxxApp()
{
    m_lpxxxTemplate = NULL;
}
次に、CxxxApp::InitInstanceでCMultiDocTemplateクラスのオブジェクトを作成します。 CxxxViewには、新しく作成したViewクラスの名前を入れましょう。
BOOL CxxxApp::InitInstance()
{
    ...
    m_lpxxxTemplate = new CMultiDocTemplate(
        IDR_XXX,
        RUNTIME_CLASS(CxxxDoc),
        RUNTIME_CLASS(CChildFrame),
        RUNTIME_CLASS(CxxxView));
    ...
}
ExitInstanceで解放しておきましょう。
CxxxApp::ExitInstance()
{
    if (m_lpxxxTemplate != NULL)delete m_lpxxxTemplate;
}
これで準備は完了です。 実はAppクラスのメンバとする必要はありません。Documentクラスで m_lpxxxTemplateを管理しても良いかもしれませんね。
それでは最後に、実際に新しいビューを開くコードを書きましょう。
CxxxDocクラスの、何かのコマンドハンドラに書く事にします。
CxxxDoc::Onxxx()
{
    CFrameWnd* pNewFrame = ((CxxxApp*)AfxGetApp())->m_lpxxxTemplate->CreateNewFrame(this, NULL);
    pNewFrame->InitialUpdateFrame(this, TRUE);
}
これで完了です。自力でテンプレートオブジェクトの管理をするのが コツでしょうか。結構ややこしいかもしれません。 ビュークラスが増えるにつれ、テンプレートオブジェクトも 新たに管理する必要があります。 ここらへんをまとめて便利にやってくれるクラスを用意しておくと 良いかもしれませんね。


masato@mb.kcom.ne.jp