Microsoft Foundation Class

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索

Microsoft Foundation Class (MFC)は、マイクロソフトVisual C++用に開発した、Windows用のアプリケーション構築のためのアプリケーションフレームワーククラスライブラリ)である。Active Template Library (ATL)と同様に、Visual C++に同梱される有償のライブラリとなっている。

概要[編集]

MFCでは、Windowsアプリケーションにおけるメッセージハンドラやウィンドウフレームワークなどの基礎的な部分をあらかじめパッケージ化したほか、GDIオブジェクト、デバイス コンテキスト、スレッドソケットFTP/HTTPなどのインターネットサービス、可変長の文字列配列リストといったコンテナなど、一般にアプリケーションでよく使われるようなクラスを備えている。

SDKを使ってWindows APIを直接呼び出すのに比べ、Visual C++の統合環境との親和性が高く開発が容易になるという利点があるが、一方でMFCに過度に依存したプログラムを書くと他のOSへの移植が難しくなるといった問題もある。

MFCに似たライブラリとしては、Windows Template Library (WTL)がある。

歴史[編集]

MFCは1992年、16ビットバージョンのWindowsをターゲットとし、マイクロソフトのC/C++コンパイラ 7.0とともに発売された。これは開発ツールの分野におけるシェアを高めようとしていたマイクロソフトの努力の一環であり、MFCはプログラミング言語C++の能力を知らしめるよう設計されていた。当時、C++は商用アプリケーションの開発においてCからの移行が始まったばかりであり、C/C++ 7.0はマイクロソフトのコンパイラとして初めてC++をサポートした。MFCはMacintoshThink Class Library(TCL、後にSymantecによって買収された)に大きく影響を受け、その構造の多くをTCLから受け継いでいた。

同時期、Borland Cコンパイラに対応したObject Windows Library (OWL)が、競合製品としてBorlandから販売されていた。OWLの設計はより厳密にオブジェクト指向に準じていたので、一時期の間MFCよりも好評であった。しかし、Windowsへの機能追加とOWLのアップデートに時間差が生じてしまったので、OWLはシェアを失った。

Visual C++ 4.2においてWinInetおよびActiveXなどのインターネット関連のクラスが追加された後は、MFC自体に特に大きな変化がなく、Visual C++ 7.0 (Visual C++ .NET 2002) においてMFCとATLの一部が統合された程度にとどまっていたが、Visual C++ 2008 (Visual Studio 2008) へのサービスパック1適用時にインストールされる「MFC Feature Pack」において、MFCは大幅な進化を遂げている。具体的には、Office 2007風のリボン インターフェイスを構築するための"CMFCRibbon~"で始まる名前を持つクラスや、Visual Studio 2005風のスマート ドッキング ウィンドウを実現するCDockablePaneクラスなど、100以上のクラスが追加されている。これらのクラスを利用する場合、開発者は基本的に、Feature Packインストール後にMFCアプリケーション ウィザードに追加されるリボンUIあるいはVisual Studio UIのテンプレートを選択して、自動生成されるフレームワークをベースにしてコーディングしていくことになる。ただし.NET Frameworkによる開発とは異なり、RADではなくコードベースでGUIを構築する必要があるため、これらのクラスを使いこなすにはMFCプログラミングに精通していることが前提となる。なお、Windows 7 SDK(Windows SDK for Windows 7 and .NET Framework 3.5 SP1)にもリボン インターフェイスを実装するための「リボン フレームワーク」と呼ばれるAPI群が追加されているが、実質的にCOMコンポーネントを利用したAPIプログラミングであり、さらにリボン フレームワークのコンポーネントが導入されているのはWindows Vista SP2以降のOSであるため、ネイティブ(アンマネージ)のリボンUIアプリケーションの開発に関しては、MFCの選択は有力候補となり得る。

Visual C++ 2010 (Visual Studio 2010) においては、リボンUIを視覚的に編集する機能(リボン デザイナー)[1]がリソース エディタに追加されたほか、Windows Vista以降のOSに実装されている「タスク ダイアログ」や「再起動マネージャー」などを利用するための機能も追加されている[2]。また、Visual C++ 2010へのサービスパック1適用後は、Direct2Dラッパー[3]およびWindows Animation Managerラッパー[4]の機能(クラス ライブラリ)が追加されるなど、.NET Frameworkとはまた違った方向の機能拡張が続けられている。

仕様[編集]

MFCが発売された時、マイクロソフトはマクロの活用によってC++の文法を拡張し、ウインドウメッセージ、例外処理実行時型情報、クラスの動的インスタンス化などを管理していた(例外処理、実行時型情報などは当時のC++の言語仕様にも実装(コンパイラ)にも存在しなかった)。ウインドウメッセージのために構文に変化を加えたことは、不要な仮想関数テーブルの使用を避けることでメモリの消費量を抑える狙いがあった。さらに、構造がより具体的になり、Visual C++に付属する多様なツールがソースコード全体を解析することなく処理できるという効果もあった。メッセージ処理のマクロは、C++の仮想関数の代わりとなった。ただ、一部のマクロはコンパイラによる型チェックを無効化することがあるので、しばしばバグの原因となった。

MFCを使用することの主な利点は、Windows APIを利用したプログラム開発にオブジェクト指向プログラミングモデルを導入するという点である。もう一つは、Windowsのリソースに関連した一般的なデータ型に対するラッパーを提供するという点である。これらのラッパーを使用することで、リソース管理オブジェクトのスコープを出た時に自動的にリソースのハンドルを解放させることなどができる(RAII)。さらに、MFCはModel View Controllerモデルに基づいたアプリケーションを開発するためのドキュメント/ビュー フレームワークを提供する。

MicrosoftはC++標準化にあたって、多重継承について否定的な立場をとっていた。MFCもその理念に従い初期のMFCは多重継承を全く使用しておらず、オブジェクトとしての機能は基底クラスに、そして具体的な機能の実装は単純継承によって実装されている。これはオブジェクトが不要なメンバによって肥大化する事が無く、また不必要に修飾されていないので個々のクラスを理解する事が容易になっている。しかし、一部のクラスは多重継承(より近代的な実装ならばテンプレート)によって実装されるべき物も単純継承によって実装されており、これらは統合開発環境の支援なくしては扱えない難解な物になっている(後述のCViewやCDocumentもこれに含まれる)。

MFCの主な欠点は、多くのオペレーティングシステムで利用できないという点である。MainsoftはUNIXで利用可能なMFCツールを開発した[5]。マイクロソフトは、1990年代にMacintoshに対応したMFCを販売していたが、それ以降はMacintoshに対するVisual Studioのサポートは中止された。

また、Visual C++のC/C++ライブラリと同様に、ライブラリのバージョンごとにメモリ管理が異なるため、互いに異なるバージョンのMFCを使用したEXE-DLLプログラム間でDLL境界を越えてMFCオブジェクト・CRTオブジェクトをやりとりできないなど、バージョン間でのバイナリレベルの互換性が低くなっている[6]。そのため、旧バージョンのMFCを使って開発されたDLL(MFC拡張DLL)やスタティックライブラリを、新バージョンのMFCアプリケーションでそのまま利用することは基本的に不可能(その逆もまた然り)となっており、ソースコードからの再ビルドが必要となる。なお、非MFCアプリケーションや、異なるバージョンのMFCアプリケーションから、MFCを使って実装したコードを実行する場合、MFC標準DLLもしくはATL COMサーバーのプロジェクト形式を選択し、C言語関数形式のインターフェイスやCOMインターフェイスを作成してアプリケーション側に公開する必要がある。

MFCはあくまでWindows APIのラッパークラス群およびそれらを利用したフレームワークという位置付けのため、生産性の点ではVisual BasicVisual C#DelphiなどのRADツールに遠く及ばない。また、C++言語の習得は比較的難しい部類に入るため、エンドユーザープログラミング(エンドユーザーコンピューティング)の観点からも敬遠されがちである。しかし、そういったいくつかの問題点を抱えているにもかかわらず、MFCが未だ多くの企業や個人プログラマーに利用されているのは、実行速度や動作プラットフォーム、開発環境および開発言語の変更コストの問題などで旧来のネイティブコード資産を完全に.NETに移行することが難しく、またWindowsアプリケーションにおいて凝った機能を実装しようとすると、Windows APIおよびCOMコンポーネントを直接操作するほうが返って楽であることが多く、これらと親和性の高いMFCを選択せざるを得ないためである。

なお、Visual C++ .NETに搭載されているマネージ拡張C++、あるいはVisual C++ 2005以降に搭載されているC++/CLI言語を利用することで、従来のMFCアプリケーションから.NET Frameworkのライブラリをシームレスに利用する、もしくはMFC標準DLLに実装されたMFCネイティブコードをマネージコードでラップすることで、C#あるいはVB.NETのような.NET言語向けにクラスライブラリの形で公開する、といったハイブリッド開発・相互運用が可能となり、ネイティブコードとマネージコードの資産をともに活かすことができるようになる。しかし、マネージ拡張C++やC++/CLI言語を用いた開発はネイティブコードおよびマネージコード双方にまたがる知識が必要となるため、MFCのみを利用した場合、もしくは.NETのみを利用した場合と比べて難易度が高くなる。

MFCの欠点に対する批判[編集]

  • CDocument, CView 等の基本的なクラスの仕様が難解である。Windowsメッセージ、コマンド、およびシェルといったWin32 APIの基本を理解していることが前提となる。
  • クラスは基本的に単一継承のみであるため、階層が深くなりがちである。また、friendクラスが多用されていることもあって直交性が低い。
  • すべての構造体、クラスおよび列挙型などがグローバル名前空間に存在し、さらにマクロが多用されているため、名前のコンフリクト(識別子の衝突、競合)が発生しやすく、また継承の階層構造がわかりにくい。なお、MFCシリアライズ機能を使用するクラスは、グローバル名前空間で定義しなくてはならない。
  • 実行時型情報例外処理機構などの一部の仕様は、独自のマクロを使用した実装となっているため、標準C++に慣れたユーザーは戸惑う(標準C++の実行時型情報および例外処理機構との併用や共存は可能)。
  • 変数名に(16bit時代からの)古いシステムハンガリアン記法を採用しているため、最新のコーディングスタイルに合わない。
  • Win32 API自体が拡張を繰り返した結果、APIとしての統一性に欠けるものとなったため、その薄いラッパーでしかないMFCでは隠蔽しきれない。
  • トレース用のDEBUG_NEWマクロによるnewキーワードの置換など、標準規格違反を犯している[1]

バージョン[編集]

MFCのバージョンは、バージョン6.0以降はその対応するVisual C++製品のバージョン番号と同じとなっている。なお、Visual C++コンパイラ自体は _MSC_VER という予約マクロによりバージョン番号が定義されるが、MFCでは _MFC_VER という予約マクロによりバージョン番号が定義される。これらはそれぞれ異なる内部数値になっているので、バージョンに応じてユーザープログラムコードを分岐したい場合は注意が必要となる。

Visual C++に同梱されるMFCのバージョン一覧を下記に示す。

Visual C++とMFCのバージョンの履歴
VC製品バージョン MFCバージョン 備考
Microsoft C/C++ 7.0 MFC 1.0
Visual C++ 1.0 MFC 2.0
Visual C++ 1.5 MFC 2.5
Visual C++ 2.0 MFC 3.0
Visual C++ 2.1 MFC 3.1
Visual C++ 2.2 MFC 3.2
Visual C++ 4.0 MFC 4.0
Visual C++ 4.1 MFC 4.1
Visual C++ 4.2 MFC 4.2
Visual C++ 5.0 MFC 4.21 (mfc42.dll)
Visual C++ 6.0 MFC 6.0 (mfc42.dll)
Visual C++ .NET 2002 MFC 7.0 (mfc70.dll)
Visual C++ .NET 2003 MFC 7.1 (mfc71.dll)
Visual C++ 2005 MFC 8.0 (mfc80.dll) サービスパックおよびセキュリティパッチの適用により、複数のバージョンがインストールされる。
Visual C++ 2008 MFC 9.0 (mfc90.dll) サービスパックおよびセキュリティパッチの適用により、複数のバージョンがインストールされる。
Visual C++ 2010 MFC 10.0 (mfc100.dll)
Visual C++ 2012 MFC 11.0 (mfc110.dll)
Visual C++ 2013 MFC 12.0 (mfc120.dll)

Visual C++ .NET 2003までは、C/C++ (CRT) およびMFCのランタイム ライブラリはWindowsのシステム フォルダ(%WinDir%\System32あるいは%WinDir%\SysWOW64)にインストールされるようになっていたが、Windows XP以降の場合、Visual C++ 2005および2008はDLL地獄を解消する目的で、%WinDir%\WinSxS 以下の、amd64_microsoft.vc80.mfc_*、ia64_microsoft.vc80.mfc_*、x86_microsoft.vc80.mfc_*などのフォルダにSide-by-Sideアセンブリとしてインストールされるようになっている。これにより、サービスパックを適用したランタイムをインストールしたり、ランタイムにセキュリティパッチを適用したりすると、旧バージョンのランタイムは上書きされず、新しいバージョンのランタイムが追加インストールされるため、複数の異なるバージョンが共存できる。なお、Visual C++ .NET 2003までは、MFCを使用するアプリケーションの実行プログラムの存在するフォルダにMFCランタイムをコピーして再配布すれば、MFCランタイムがインストールされていないエンドユーザー環境でも実行できていたが、Visual C++ 2005および2008ではこのようなSide-by-Sideアセンブリの形態をとるようになっているため、単純にコピーを添付するだけでは実行することができない。Visual C++ 2005および2008を使用して作成されたMFCアプリケーションをエンドユーザー環境で実行するためには、下記の方法が存在する[2] [3]

  1. エンドユーザー環境にVisual C++のランタイムパッケージを別途インストールする。
  2. アプリケーションをビルドする際、CRT/MFCをスタティックリンク(静的リンク)する。
  3. アプリケーションマニフェストを使用してCRT/MFCランタイムをプライベートアセンブリ化する(Windows XP以降)。

1番目の方法は、エンドユーザーの負担が増えるものの、セキュリティ面で最も安全な方法である。インストールされたランタイムDLL群は、Microsoft Updateなどによって提供されるセキュリティパッチの適用対象となる(ただし前述の通り、DLL自体はセキュリティパッチによって書き換えられるわけではない)。なお、エンドユーザーランタイムのインストーラはMicrosoftから無償提供されており、開発者による再配布も行なえるようになっている。 2番目の方法は、エンドユーザーの手間を減らせるが、アプリケーションビルド時のリンク時間が増加し、実行プログラムのファイルサイズが肥大化するという欠点がある[4]。また、セキュリティパッチ適用の対象外となる(ちなみに/clrオプションを有効にして.NETハイブリッドアプリケーションを作成する場合はそもそもCRT/MFCライブラリをスタティックリンクすることはできない)。 3番目の方法は、アプリケーションにMFCランタイムを同梱するための方法であり、スタティックリンクする場合と同様にエンドユーザーの手間を減らせる。

なお、Visual C++ 2010以降では、CRTおよびMFCランタイムのSide-by-Side配置方式は廃止され、再びVisual C++.NET 2003以前と同じようにWindowsシステム フォルダへインストールされるようになっている。サービスパックおよびセキュリティパッチが適用されると、システム フォルダ内のDLLファイル(mfc100.dllなど)が書き換えられる。

MBCSとUnicode[編集]

MFCではアプリケーションのコンパイル&ビルド時に設定・定義するMBCS/UNICODEシンボル情報に合わせて、それぞれMBCS版MFCライブラリとUnicode版MFCライブラリが暗黙的にリンクされて使用される。MBCS版とはANSIマルチバイト文字セット(Multibyte Character Set)[7]版のことで、例えば日本語版の場合Shift_JIS(厳密にはANSIコードページ932)に相当する。Unicode版とはWindows用のUnicode対応版のことで、UTF-16LEに相当する。WindowsではOSの内部文字コードがUTF-16LEのため、一般的にはアプリケーションの内部文字コードとしてUTF-8マルチバイトやUTF-32が使われることは少ない。

MFCアプリケーション開発において、MBCSおよびUnicode両方のバージョンで動作するコードを記述する場合、一般的にはMBCS, _MBCS, UNICODE, _UNICODEなどのシンボル定義状況に応じてコンパイルするコードを分岐させることで対処する。MFC/ATL、標準C/C++ランタイムライブラリ(CRT)およびWin32 APIにはMBCS/Unicode両対応を容易にするためのマクロ(CreateFileA()/CreateFileW() APIに対応するCreateFileマクロや、MBCS/Unicode文字列リテラルを切り替えるTEXT(), _T()マクロなど)や、TCHAR, LPTSTR, LPCTSTR型およびCStringクラスといったヘルパーが用意されている。

Unicode文字列に対応したWindows OSはWindows 2000およびWindows XPからで[8]Windows 9x系のOSではもともとUnicode非対応であり、歴史的にWindowsアプリケーション開発言語としてのC/C++は長らくMBCSを使用してきたが、国際化対応(Unicode対応)が求められるという時代の流れから、まずVisual Studio 2005ではプロジェクトの既定の設定がUnicodeとなり、さらにVisual Studio 2013からは、MBCS版MFC/ATLライブラリは非推奨となりインストーラに同梱されなくなった(Unicode版MFC/ATLライブラリのみ同梱)。なお、ライブラリのバイナリがIDEにバンドルされなくなっただけで、Visual Studio 2013向けMBCS版MFCライブラリのDLLバージョンはマイクロソフト社の公式サイトからダウンロードすることで取得できる。一方、Visual C++ 再頒布可能パッケージ(エンドユーザー向けリテールランタイム)には、2013以降も、引き続きMBCS版MFCランタイムDLLが含まれ、MBCS版MFCランタイムを顧客に再頒布するための追加の手順は必要ない。

なお、Windows 8/Windows RTで導入されたWindowsストアアプリは、C#などの.NET言語による開発のほか、C++/CXというネイティブ拡張言語による開発も可能となっているが、MFCは使用できない。また、Windowsストアアプリではマルチバイト文字・文字列のAPIが使えなくなっており、ASCIIもしくはUnicode文字・文字列のみが使用できる[9]

脚注[編集]

[ヘルプ]

関連項目[編集]

外部リンク[編集]

非公式[編集]