TipsとMFCの仕組み

MFCの森


まだまだ木の芽程度ですが、芽から木、木から林、林から森へと大きくしていきたい・・・。

プリコンパイル

プロジェクト形態によっては若干異なりますが、アプリケーションウィザードで生成された stdafx.h には以下のような記述があります。

#include <afxwin.h> // MFC のコアおよび標準コンポーネント #include <afxext.h> // MFC の拡張部分 #include <afxdisp.h> // MFC オートメーション クラス #include <afxdtctl.h> // MFC の Internet Explorer 4 コモン コントロール サポート #ifndef _AFX_NO_AFXCMN_SUPPORT #include <afxcmn.h> // MFC の Windows コモン コントロール サポート #endif // _AFX_NO_AFXCMN_SUPPORT

afxwin.h は5000行ほど記述があります。さらに他のヘッダーファイルをインクルードしていますので実際にはもっともっと多くなります。
(afxwin.hafx.hafxver_.hafxv_w32.h とたどっていくと windows.h もインクルードされていることがわかります。)

ここで、A.cpp というソースファイルと B.cpp というソースファイルがあり、それぞれ afxwin.h をインクルードしていた場合を考えます。
コンパイラは、A.cpp をコンパイルする際に必要な afxwin.h の展開処理 を行います。
また、B.cpp をコンパイルする場合にも同様に afxwin.h を展開 します。当然 A.cppB.cpp それぞれに対してそれなりの時間がかかります。これが10個、100個と数が多くなったらものすごく時間がかかることになります。
そこで、A.cpp をコンパイルした際に登場した afxwin.h の展開結果をそのまま B.cpp に適用することが出来れば速度アップが望めます。

つまり、
同じ展開処理は毎回行わず、一度展開した結果を再利用するための情報を抽出すること」が プリコンパイル です。

プリコンパイルされた情報は、XXX.pch というファイル(XXXはプロジェクト名)に書き出されています。デフォルトでも数MB〜数十MBのサイズになります。

プロジェクトでプリコンパイル済みヘッダーを利用する場合、すべてのcppファイルにおいて stdafx.h をインクルードしておく必要があります
ひとつでもインクルードされていないcppファイルがあると、「fatal error C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。」というエラーが出てビルドに失敗します。自作ソースファイルを取り込む(作成する)際には注意しましょう。

MDIアプリケーション起動時に空ドキュメントを開かないようにする(2004/12/06 Update)

ProcessShellCommand関数 へ渡す CCommandLineInfoインスタンス のメンバ変数を変更します。

BOOL CMyApp::InitInstance() { // DDE、file open など標準のシェル コマンドのコマンドラインを解析します。 CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); if(cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew){ cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing; } if(!ProcessShellCommand(cmdInfo)) return FALSE; }

ParseCommandLine関数 は、アプリケーションのコマンドライン引数を解析し、次の ProcessShellCommand関数 で処理すべき情報を cmdInfo変数 に格納してくれます。 cmdInfo.m_nShellCommandFileNew に設定されている場合、新しいビューを作成することになりますので、この場合に何もしない FileNothing に書き換えてやります。

コマンドライン引数の例(cmdInfo を生成時のまま ParseCommandLine関数 へ渡した場合)
コマンドライン引数cmdInfo.m_nShellCommand値実行されるコマンド
app−(FileNewから変更なし)新規作成
app filenameFileOpen開く
app /p filenameFilePrintデフォルト プリンタにファイルを印刷
app /pt filename printer driver portFilePrintTo指定のプリンタにファイルを印刷
app /ddeFileDDE起動し、DDE コマンドを待つ
app /AutomationOLE オートメーション サーバーとして起動
app /Embedding埋め込まれた OLE アイテムとして起動

CDocumentからCViewへデータ更新を通知

UpdateAllViews関数 を呼び出します。第1引数をNULLとすることで、ドキュメントにリンクされているすべてのビューに対して CView::OnUpdate関数 が呼び出されます。

UpdateAllViews(NULL, 0, NULL);

スクリーンセーバの起動

とっても簡単。以下の一行で起動できます。

SendMessage(hWnd, WM_SYSCOMMAND, SC_SCREENSAVE, NULL);

トップへ
Programトップへ