Microsoft Foundation Class

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

ATL/MFCはもともと有償エディションのVisual C++単体製品や、有償エディションのVisual Studio製品のみに同梱されていたが、Visual Studio Communityエディションでは無償でATL/MFCを利用できる。

1. 概要
-----

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

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

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

2. 歴史
-----

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

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

Visual C++ 4.2においてWinInetおよびActiveXなどのインターネット関連のクラスが追加された後は、MFC自体に特に大きな変化がなく、Visual C++ 7.0  においてMFCとATLの一部が統合された程度にとどまっていたが、Visual C++ 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  にもリボン インターフェイスを実装するための「リボン フレームワーク」と呼ばれるAPI群が追加されているが、実質的にCOMコンポーネントを利用したAPIプログラミングであり、さらにリボン フレームワークのコンポーネントが導入されているのはWindows 7およびWindows Vista SP2 Platform Update以降のOSであるため、ネイティブのリボンUIアプリケーションの開発に関しては、MFCの選択は有力候補となり得る。

Visual C++ 2010  においては、リボンUIを視覚的に編集する機能がリソース エディタに追加されたほか、Windows Vista以降のOSに実装されている「タスク ダイアログ」や「再起動マネージャー」などを利用するための機能も追加されている。高DPI環境にも標準対応するようになった。また、Visual C++ 2010へのサービスパック1適用後は、Direct2DラッパーおよびWindows Animation Managerラッパーの機能が追加される。

Visual C++ 2015では動的レイアウトにも対応するなど、.NET Frameworkとはまた違った方向の機能拡張が続けられている。

3. 仕様
-----

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

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

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

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

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

MFCはあくまでWindows APIのラッパークラス群およびそれらを利用したフレームワークという位置付けのため、生産性の点ではVisual BasicやVisual 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のみを利用した場合と比べて難易度が高くなる。

4. MFCの欠点に対する批判
---------------

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

5. バージョン
--------

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

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

Visual C++ .NET 2003までは、C/C++  およびMFCのランタイム ライブラリは開発環境のインストールとともにWindowsのシステム フォルダにインストールされるようになっていたが、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アプリケーションをエンドユーザー環境で実行するためには、下記の方法が存在する 。

エンドユーザー環境にVisual C++のランタイムパッケージを別途インストールする。
アプリケーションをビルドする際、CRT/MFCをスタティックリンクする。
アプリケーションマニフェストを使用してCRT/MFCランタイムをプライベートアセンブリ化する。1番目の方法は、エンドユーザーの負担が増えるものの、セキュリティ面で最も安全な方法である。インストールされたランタイムDLL群は、Microsoft Updateなどによって提供されるセキュリティパッチの適用対象となる。なお、エンドユーザーランタイムのインストーラはマイクロソフトから無償提供されており、開発者による再配布も行なえるようになっている。 2番目の方法は、エンドユーザーの手間を減らせるが、アプリケーションビルド時のリンク時間が増加し、実行プログラムのファイルサイズが肥大化するという欠点がある。また、セキュリティパッチ適用の対象外となる。 3番目の方法は、アプリケーションにMFCランタイムを同梱するための方法であり、スタティックリンクする場合と同様にエンドユーザーの手間を減らせる。

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

6. MBCSとUnicode
---------------

MFCではアプリケーションのコンパイル＆ビルド時に設定・定義するMBCS/UNICODEシンボル情報に合わせて、それぞれMBCS版MFCライブラリとUnicode版MFCライブラリが暗黙的にリンクされて使用される。MBCS版とはANSIマルチバイト文字セット  版のことで、例えば日本語版の場合Shift_JISに相当する。データの格納にはchar型およびその配列が主に使われる。Unicode版とはWindows用のUnicode対応版のことで、UTF-16LEに相当する。データの格納にはwchar_t型およびその配列が主に使われる。WindowsではOSの内部文字コードがUTF-16LEのため、一般的にはアプリケーションの内部文字コードとしてUTF-8マルチバイトやUTF-32が使われることは少ない。

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

Unicode文字列に対応したWindows OSはWindows 2000およびWindows XPからで[2]、Windows 9x系のOSではもともとUnicode非対応であり、歴史的にWindowsアプリケーション開発言語としてのC/C++は長らくMBCSを使用してきたが、国際化対応が求められるという時代の流れから、まずVisual Studio 2005ではプロジェクトの既定の設定がUnicodeとなり、さらにVisual Studio 2013からは、MBCS版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というネイティブ拡張言語による開発も可能となっているが、ATLの一部は使用できるもののMFCは使用できない。また、Windowsストアアプリではマルチバイト文字・文字列のAPIが使えなくなっており、ASCIIもしくはUnicode文字・文字列のみが使用できる。

7. 脚注
-----

8. 関連項目
-------

Microsoft Visual C++
Windows API
Active Template Library
Windows Template Library

9. 外部リンク
--------

[3]
[4]

9.1. 非公式
--------

[5]
[6]
[7]
[8]
[9]