MFCマクロ


CおよびC++言語でマクロを使用できます.マクロは、文字列またはソースコードのセグメントを表すマクロ定義コマンドdefineで識別子を定義します.MFCマクロは、MFCクラスライブラリの1つの構成要素として、MFCアプリケーションによく登場する.MFCマクロはパス"……/Microsoft Visual Studio/VC 98/MFC/Include"のAfxwin.h、Afx.h及びAfxmsg_.hなどのMFCヘッダファイルではそれぞれ定義されている.
(1)共通のMFCマクロ
NFCは、メッセージマッピングマクロ、ランタイムタイプ識別マクロ、シーケンス化マクロ、デバッグマクロ、例外マクロなど、多くのマクロを提供する.表1にプログラミング時によく遭遇するMFCマクロを示す.読者はMFCマクロの使い方を知っているかもしれないが、必ずしも廬山の正体を知っているとは限らない.MFCの内部メカニズムを本当に理解し、MFCを上手に運用するには、MFCマクロの基本原理と使用方法を把握しなければならない.
表1の一般的なMFCマクロ
(2)ランタイムタイプ認識に関するマクロ
ランタイムタイプ識別(runtime type information,RTTI)とは、プログラムの実行時にオブジェクトを特定できるタイプをいう.MFCは、一般的なC++におけるランタイムタイプ識別機能を拡張し、クラスがMFCのランタイムタイプ識別機能をサポートする場合、プログラムがオブジェクトの情報(クラス名、占有記憶空間サイズ、バージョン番号など)とベースクラス情報(runtime class informtation,RTCI)を取得することを可能にする.
      1.ランタイムベースマクロ:RUNTIME_CLASS(class_name)
      RUNTIME_CLASSマクロ戻りパラメータclass_nameで指定されたクラスの静的メンバー変数class#class_名前のポインタ.このポインタはCRuntime構造を指します.マクロの定義は次のとおりです.
    
Cppコード
  • #define RUNTIME_CLASS(class_name)   
  •               ((CRuntimeClass*)(&class_name::class##class_name))  
  • #define RUNTIME_CLASS(class_name)
                  ((CRuntimeClass*)(&class_name::class##class_name))

    プログラムはRUNTIME_を利用できるCLASSマクロはクラスのインスタンスをリアルタイムで作成します.このマクロを機能させるには、定義されたクラスはクラスCObjectの派生クラスである必要があり、派生クラスの定義でマクロDECLARE_を使用する必要があります.DYNAMIC、DECLARE_DYNCREATEまたはDECLARE_SERIAL、派生クラスの実装ソースファイルにマクロIMPLEMENT_を使用DYNAMIC、IMPLEMENT_DYNCREATEまたはIMPLEMENT_SERIAL.この3つのマクロはMFCクラスとその派生クラスに3つの異なるレベルの機能を持たせる.
          2.動的サポートマクロ:DECLARE_DYNAMIC(class_name)と
               IMPELMENT_DYNAMIC(class_name,base_class_name)  
    動的サポートマクロを使用すると、CObject派生クラスのオブジェクトに基本的なタイプ識別機能を持たせ、メンバー関数CObject::IsKindOf(ClassName)テストオブジェクトと所与のクラスClass_を呼び出すことができます.Nameの関係.
          DECLARE_DYNAMIC()マクロの定義は次のとおりです.
      
    Cppコード
  • #define DECLARE_DYNAMIC(class_name)/  
  • public:/  
  •          static const AFX_DATA CRuntimeClass class##class_name;/  
  •          virtual CRuntimeClass* GetRuntimeClass() const;/  
  • #define DECLARE_DYNAMIC(class_name)/
    public:/
             static const AFX_DATA CRuntimeClass class##class_name;/
             virtual CRuntimeClass* GetRuntimeClass() const;/

    例1クラスMyClassを定義し、RUNTIME_を使用するCLASS()マクロの基本オブジェクト識別機能.
        
    Cppコード
  • //ヘッダーファイルMyClass.h   
  • class CMyClass:public CObject   
  • {   
  •     DECLARE_DYNAMIC(CMyClass)   
  • public:   
  •     void someFunction(void);   
  • };  
  • //    MyClass.h
    class CMyClass:public CObject
    {
    	DECLARE_DYNAMIC(CMyClass)
    public:
    	void someFunction(void);
    };
    

     
    Cppコード
  • //実装元ファイルMyClass.cpp中
  • #include "MyClass.h"  
  • IMPLEMENT_DYNAMIC(CMyClass,CObject)   
  • void CMyClass::SomeFunction(void)   
  • {   
  •     CObject* pObject=new CMyClass;   
  •     if(pObject->IsKindOf(RUNTIME_CLASS(CMyClass)))   
  •     {   
  •         CMyClass* pMyObject=(CMyClass*)pObject;   
  •         AfxMessageBox("MyObject is an object of the class CMyClass");   
  •     }   
  •     else  
  •         AfxMessageBox("MyObject is not an object of the class CMyClass");   
  •     delete pObject;   
  • }  
  • //      MyClass.cpp 
    #include "MyClass.h"
    IMPLEMENT_DYNAMIC(CMyClass,CObject)
    void CMyClass::SomeFunction(void)
    {
    	CObject* pObject=new CMyClass;
    	if(pObject->IsKindOf(RUNTIME_CLASS(CMyClass)))
    	{
    		CMyClass* pMyObject=(CMyClass*)pObject;
    		AfxMessageBox("MyObject is an object of the class CMyClass");
    	}
    	else
    		AfxMessageBox("MyObject is not an object of the class CMyClass");
    	delete pObject;
    }

          3.動的作成マクロ:DECLARE_DYNCREATE(class_name)と
             IMPLEMENT_DYNCREATE(class_name,base_class_name)
    動的作成は、基本的なタイプ識別機能に加えて、動的作成マクロを使用して、CObjectクラスの派生クラスに実行時に動的にオブジェクトを作成する機能を持たせる動的サポートのスーパーセットです.動的作成をサポートするクラスには、安定したオブジェクトに使用するためのデフォルトのパラメータなしコンストラクション関数が必要です.MFCアプリケーションフレームワークはこの機能を利用して新しいオブジェクトを動的に作成する.たとえば、シーケンス化中にディスクからオブジェクトが読み込まれると、アプリケーション・フレームワークは、ドキュメント・クラス、ビュー・クラス、およびボックス・クラスの動的作成機能を使用して、実行時オブジェクトを動的に作成します.MFCアプリケーションフレームワークでは、ウィザードがMFC派生クラスに2つの動的作成マクロを自動的に追加します.      4.シーケンス化:DECLARE_SERIAL()とIMPLEMENT_SERIAL()
    シーケンス化は動的サポートと動的作成のスーパーセットであり、基本的なカテゴリ識別と動的作成機能に加えて、シーケンス化マクロを使用することでCObjectクラスの派生クラスにオブジェクトの持続性を実現するシーケンス化機能を持たせることができる.
    (3)MFCデバッグマクロ
           1.TRACEトレース宣言マクロ
    TRACE()マクロ構文の説明は次のとおりです.
            TRACE(,)
    パラメータは、関数printf()のパラメータと同じ形式の出力フォーマットと式で構成されます.TRACEマクロの機能は、デバッグ実行時に式の値をOutputデバッグウィンドウに出力することです.TRACEマクロは、MFCアプリケーションDebug版のデバッグ実行状態でのみ機能し、Developer StudioでのEnable tracing設定を保証する必要があります.これは、Tools|MFC Tracerコマンドを実行する必要があります.
    例2次のコードについて
    Cppコード
  • char* szName="LiMing";   
  • int nAge=18;   
  • TRACE("Name=%s,Age=%",szName,nAge);  
  • char* szName="LiMing";
    int nAge=18;
    TRACE("Name=%s,Age=%",szName,nAge);

    デバッグ実行時にOutウィンドウで次の内容が出力されます.
          Name=LiMing,Age=18
          2.ASSERTアサートマクロ
             ASSERT()
    マクロを実行すると、式が真の場合、プログラムは実行を続行します.そうでなければ、プログラムの実行を一時停止し、実行を一時停止した行とファイルの情報をユーザーに伝えるダイアログボックスがポップアップされます.ユーザーは、実行の終了、デバッグ、または実行の継続を選択できます.例えば、ビュー派生クラスのメンバ関数GetDocument()では、MFCはASSERT()マクロを用いて、現在のドキュメントがランタイムクラスのオブジェクトであるか否かを判断する.
    例3はCMyFrameというフレームワークウィンドウクラスをカスタマイズしたものであり,CframeWndの派生クラスでもある.CMyFrameに関連付けられたドキュメントテンプレートオブジェクトをプログラムで構築し、構築したドキュメントテンプレートのフレームウィンドウを作成します.次に、このフレームワークウィンドウを使用するコードを記述できます.
     
    Cppコード
  • CMyFrame* pFrame=(CMyFrame*)AfxGetMainWnd();   
  • ASSERT(pFrame->IsKindOf(RUNTIME_CLASS(CMyFrame)));//判断pFrameのタイプ
  • pFrame->DoSomeOperation();//メンバー関数を呼び出していくつかの操作を完了する
  • CMyFrame* pFrame=(CMyFrame*)AfxGetMainWnd();
    ASSERT(pFrame->IsKindOf(RUNTIME_CLASS(CMyFrame)));   //  pFrame   
    pFrame->DoSomeOperation();        //            

    AfxGetMainWnd()はグローバル関数であり、CWnd*のタイプのアプリケーションメインウィンドウへの戻り値のポインタであるため、強制的なタイプ変換が必要です.しかし、変換に成功したかどうかをどのように知っていますか?CMyFrameクラスもCObjectの派生クラスであり、メンバー関数IsKindOf()と組み合わせてASSERT()マクロを使用してpFrameのタイプをチェックすることができます.pFrame->DoSomeOperation()文の前にASSERT()マクロを挿入すると、メカニズムの実行時にタイプチェックを行い、タイプが一致しない場合にブレークダウンを起こし、プログラムの実行を中断することができます.
    ASSERTマクロはDebugバージョンでのみ機能し、Releaseバージョンではコンパイルされず、ReleaseバージョンではVERIFYマクロを使用できます.VERIFYマクロとASSERTマクロのDebugバージョンでの役割は一致しています.違いは、ReleaseバージョンではVERIFYマクロが依然として有効であり、パラメータ式を評価しますが、結果にかかわらずプログラムの実行を一時停止しません.
    プログラムに悪影響を及ぼさないように、ASSERTマクロを使用する場合は、パラメータ式に関数呼び出し文がないことを保証する必要があります.ASSERTマクロの関数呼び出し文はReleaseバージョンに存在しないためです.この場合、ASSERTマクロの代わりにVERIFYマクロを使用できます.
          3.ASSERT_VALID断言有効マクロ
             ASSERT_VALID()マクロ構文の説明は次のとおりです.
             ASSERT_VALID()
           ASSERT_VALIDマクロは、ポインタとオブジェクトの有効性をチェックするために使用されます.一般ポインタの場合、ポインタが空であるかどうかのみがチェックされます.MFCクラスオブジェクトポインタについては,CObjectクラスのメンバ関数AssertValid()を呼び出すことでオブジェクトの捨て方性を判断する.ASSERT_VALIDマクロプロンプトポインタまたはオブジェクトが無効な方法でASSERTマクロと同じように、メッセージダイアログボックスが表示されます.ASSERT_VALIDマクロもDebugバージョンでしか機能しません.
     
    ソース:http://fpwjp.javaeye.com/blog/387004