MASATOの開発日記


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

2002/02/25

ソフトウェアには、ドキュメントが付き物です。 フリーソフトでさえそれは例外ではありません。
WindowsのHelpは、今後HTML Helpが主流になっていくような感じですので、 私もHTML Helpを使うことにしました。 複数のHTMLファイルと画像ファイルがそのままHelpになって何か新鮮な感じです。
しかし、Helpを書いた後に機能を変更してしまうと、Helpを変更する必要があり、それがなかなか単純には行きません。
MicroSoftが提供しているHTML Help作成ツールHTML Help Workshopでは、 コンテンツのテーブルやキーワードは、全て1つずつ自分で設定する必要があります。
よって、機能を変更すると、文章だけ書き直すだけではなく、 こういったヘルプの設定も変更する必要があります。 これは全部手作業ですので、正確に全て変更するのは大変です。
テキストを<KEYWORD></KEYWORD>で囲んでおくと、 そこをキーワードとして抜き出してくれる仕組みがあると楽そうです。 といっても実現するのはそれほど難しく無さそうなので、 既にそんな機能が付いたHTML Help作成ソフトがあるかもしれませんね。

CArchiveとistream&ostream

MFCのストリームを扱うのはCArchiveクラス。C++標準ライブラリだと、istreamとostreamです。 iostreamというクラスもありますが、これはistreamとostreamを継承(多重)したクラスですので、 実態はistreamとostreamです。

CArchiveクラスは、入力ストリームか出力ストリームかを、構築時のフラグで判断します。 入力ストリームに出力しようとしたら、実行時にASSERTエラーが発生します。
istreamとostreamは、入力ストリームと出力ストリームを異なるクラスで扱うことにより、 入力ストリームに出力しようという操作はそもそもコンパイルエラーとなります。

どちらの方式が優れているかという議論は置いておきますが、 CArchiveはどちらかというとC++ではなくCに近く、istream&ostreamは、C++そのものです。

複数のクラスに分けるか、1つのクラスだけでフラグを指定してカスタマイズできるようにするかを選択する場面は しばしば訪れると思います。どちらを選ぶのかは場合によりけりですが、 前者はC的で後者はC++的であることも考慮してみても良いのではないかと思います。

クラスにメッセージを送る方法(2)

環境Visual C++ 6.0

前回の続きです。 CWndProcDeliverに届いたウィンドウメッセージを受け取るクラスです。

ヘッダファイルは大体次のような感じになります。

class CWndProcReceiver
{
public:
  virtual BOOL OnWndMsg(CWnd* lpWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult );
  CWndProcReceiver();
  virtual ~CWndProcReceiver();
};

ソースファイルは次のようになります。 なお、これらのコードをそのままコピー&ペーストしても色々問題が発生すると思われます。 全てのコードをここに記述しているわけではないからです。 これらのコードは、参考程度として下さい。

CWndProcReceiver::CWndProcReceiver(){}

CWndProcReceiver::~CWndProcReceiver(){}

BOOL CWndProcReceiver::OnWndMsg(CWnd* lpWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult)
{
	return FALSE;
}

OnWndMsgは純粋仮想関数にしても良いでしょう。

CWndProcDeliverとCWndProcReceiverの使用例も書いておきます。

クラスAに対してウィンドウメッセージを送れるようにしたいと思ったときは、 クラスAをCWndProcReceiverから派生させ、メンバ変数にCWndProcDeliverを持たせます。

class A : public CWndProcReceiver
{
  CWndProcDeliver m_WndProc;
  // ...
};

そして、m_WndProcを初期化するときにthisを与えておきましょう。

A::A() : m_WndProc(this) {}

Aが他のクラスを既に継承している場合、多重継承という形になります。

こんなややこしいことをしなくても、クラスAがCWndを継承すれば全て事足ります。 そうしなかった理由は、クラスAがCWndをそのまま継承すると、 クラスAから、使う必要も無いCWndのprotected/public関数を呼べてしまうからです。
前回に述べたとおり、「見えないウィンドウを使う」というのがアイデアの根幹ですので、 実装方法は、CWndProcDeliverとCWndProcReceiver以外にもあるでしょう。 今回のお話に縛られること無く、好きな方法を使うのが良いと思います。

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