ウィンドウズプログラミング (C/C++)
以下の解説では、Java や、C# は除外されます。
はじめに
わたくしが Windows Programming をはじめたときは、開始早々すぐさま MFC という名前に直面し、「MFC がないとできないことがあるのか」 などが、Windows API に関する多少の不安のもとではありました。更にはクラスライブラリやらの名前なども複数、あらわれだすといよいよややこしいく、仮にすこしは便利なシロモノだとしても、あちこちむやみに手を伸ばすのもスマートなやり方とは思えないのでやめました。特に MFC などは、製品を買わないと使えないと思っていたし、そして、実際に MFC のプログラミングができない以上は、詳しくわかろうスベもなかったから、結局は多少盲目的に、 Windows API だけにたよる形で、やりたいことをやっていかざるを得なかったのです。
ところが今は、それらをいまだ使っていなくても、ある程度述べることができますので、述べてみたいと思います。特に、これから (ウィンドウズでプログラミングを) やる人 は、視野を広げておくための参考にしてみてください。
以下で述べていることは、
VC++、BCB(BC++)、SDK、Windows API(Win32 API)、MFC、VCL、ATL、COM、STL、DirectX、また、
フリーのコンパイラの各社の違い のことも知っている人にとっては、混乱があるかもしれませんが、以下で述べることの区別とは、直接的には無関係です。外国製のコンパイラでは、C/C++ と、Windows API が利用できる (コンパイルできる) ことが最低の共通事項です。
MFC、VCL と、 Windows API
MFCプログラミング
、VCLによるプログラミング、という場合は、まずこれらは、言語記述の文法には、C や C++ を使います。Windows API に関しては、これら MFC と VCL の根本には、Windows API が存在する、と思ってください。( マイクロソフトの説明でも、「Win32 API の大部分をカプセル化、つまり "ラップ"」 している※と言っています 。) ただ、根本的に Windows API が基礎にあるということではあるけれど、「C/C++ と Windows API でプログラムを組む」 のとは、プログラミングスタイルが少し違います (以下)。C++ と Windows API の知識があれば理解はできるのですが、残念ながらこれらのプログラミングは、C/C++ と Windows API でプログラムを組もうというときには、ほんとうに参考になりません。(参考にできる、とできることできないこと、とは切り離して考えてください)また、これら2つ (
MFC または VCL) で "とどのつまりできること" は、 Windows API だけでできることに加えて、製品のサービスにより、少しだけ拡張されています。だから、その拡張された部分は、フリーコンパイラからでは行えない思ってください。(Windows)
SDKプログラミング と表現されるプログラミングは、おおかた、このホームページが扱うのと同じ、「C/C++ と Windows API によるプログラミング」 です。ただ、"SDK" は、"Platform SDK" となってはじめて固有名となるものなので、その点に気をつけてください。"なんとかSDK" はネーミングだから他にもたくさんあります。SDKを使ったプログラミング、といってあらぬ方向に迷いこみそうな場合は注意です。迷ったときは Windows API 関数の "CreateWindow" や "WinMain" といった関数が、いいキーワードです。Platform SDK と Windows API の関係は?は下のほうに書いてあります。また、"Windows API プログラミング" は、本当はこのホームページにもその副題をつけるのがちょうどいいのですが、実際には語弊があるからやめたのです。"Windows API Programming(プログラミング)" といって、具体的に C や C++ もあわせて使っていたら、よくいう Windows API プログラミングです。
※ 包み込む、包括する。
MFC は、(を使えば、) C++ の"クラス"によって "Windows API" をまとめてあるから、Windows API を包括して使えるようにしてあります、と言っている。※ C++ は、C が進化したもので、文法部分が少しと、クラスやテンプレート、
STL などの点が追加されています。C++ がコンパイル可能なコンパイラは、純粋な C もコンパイルできます。更に、C 言語は B 言語が進化したものです。C 言語の歴史について、「Dr. Ken Thompson (ケン・トンプソン博士) により開発された」 とか、「Unix開発の功績」 しか説明されていない場合がありますが、ほんとうはもっとおもしろい。( ヒント : "Space Travel"、スペーストラベル ) 歴史を説明するのなら一言でも注釈を入れておけばいいとおもうのですけどね。
以上が Windows API をこれから扱う人にとって、興味あるところだと思います。
以下は、さきほどお約束した説明です。
VC++ : Visual C ++
& BCB : Borland C++ Builderさて、まず、
VC++ と BCB からいきましょう。VC++ は、Visual C ++ という、「プログラミング統合開発環境」 IDE で、製品です。これ一つで、コード記述(エディタ)からダイアログボックスなどリソースの作成、プロジェクト管理(職業プログラマ)、最後にコンパイルまで、これ一つで統一して行えます。BCB は、Borland C++ Builder でこれも同じく製品です。BC++ という場合もあります。また、VC++ ≠ VCL にも注意しましょう。日本ではこの2つを良く見かけます。VC++ には MFC が、BCB には VCL が、それぞれ付属しています。※ VC++ は、MFC と ATL を完全にサポートしています。Windows API を扱う場合は情報が大事ですが、MFC に関しても ATL に関しても、本などによる情報のサポートも充実しています。ただこの点では、Windows API だけのプログラミングのほうも負けてはいません。Windows API を利用するプログラマーによる情報の提供量にはすばらしいものがあります。MFCプログラミングでは、Windows API も直接使うことができるので、その点は更に有利かもしれません。
MFC : Microsoft Foundation Class
MFCプログラミング
、といったら、VC++ に含まれる、MFC(Microsoft Foundation Class) を使うプログラミングです。C++ の「便利なクラス」 を使うのには STL を使いますが、同様に 「Windows API がラップされた、便利なクラス」 を使うために MFC を使います。VC++ ではあらかじめ、どのようなプログラムを書くかをいくつか選択できる (コンソールアプリ、Win32アプリ、ATL(COM)、MFC など) ようになっています。MFCプログラミングをやる場合も、あらかじめこの中からそれを選択するようになっています。そして、MFCプログラミングのスタイルに従ってはじめから記述することになります。詳しいことは述べられませんが、
MFCを使うプログラミングのスタイルは、・クラス化されている ( ラップされている : wrap )
・全くスタイルが違う ( メッセージループがない、イベント駆動式[イベントドリブン] )
・複数人で作業の分担ができる ( ファイルごとに分けるのが容易だから )
・書くコードの量自体は、あまりかわらないか、かえってかさばる
・MFC は、 C++ の"クラス"なので、クラスを扱うために C++ の知識が必要
・Windows API のサポートしないウィンドウが少しは出せる。
MFC では、「メッセージループ」というものは書かなくて良いのですが、これは書かなくてもいいように隠されています。イベント駆動式 (イベントドリブン) のスタイルは、C/C++ と Windows API だけのプログラミングでいうところの、 「メッセージクラッカー」 の考え方と同じです。更に、「ウィンドウプロシージャ」 も隠されています。隠されてはいるものの、「メッセージループ」 や、「ウィンドウプロシージャ」 といった "Windows API の仕組み※" は、一つ以上のウィンドウを持つアプリケーションを作る場合は、必ず必要なものなのです。
<table><td>さて、「ラップしている※」 ということは、Windows API を"使って" C++ の"クラス" にまとめているだけのことです。例えば、MFC の、CListView クラスのメンバ関数 Create()、CListView::Create() により作成できるウィンドウは、"Windows API関数" の一つ CreateWindow()関数 をつかって "SysListView32" とか、L"SysListView32" を指定して作成できるウィンドウと同じものです。
CListView::Create() <=> CreateWindow( L"SysListView32", .... ) </td></table>
ラップしてあるとは、まとまりごとに C++ の "クラス" を作って整理してあるということです。そして、同時に上のような対応関係があるということです。Windows API が提供する、リストビューコントロールやらの、基本的なコントロール ウィンドウ※は、十数種程度ありますが、MFC では、これらのすべてについて、ラップされ、クラスが存在します (クラス化)。MFC はそのように構成されています。
つまり、「コントロールウィンドウ」に関して例をとりますが、MFC を"使わなくても" 同じことができます。手間もどっこいどっこいです。しかし、そういうことでは製品として面白くないから、「スプリッタウィンドウ」 はじめいくつか、C/C ++ と Windows API によるプログラミング をやっている側からは、「いいなぁ」 と思われる部品※ ( これは API 外) も扱えるようになっています( "CSplitterWnd" というクラスが入っています)。わたくしは Fax ソフト をつくれましたから、Windows API の柔軟性に関しては信頼していいと思います。だいたいこのソフトの製作には、MFC があったらとか、なかったらとかは全く関係ありません。VC++ がないとだめか、などという考えにはやすやすと屈しないようにしましょう !
※ Windows API にたよる場合は、"Windows APIの提供する、固有の" メッセージループということになります。そして、「メッセージループ自体」は、GUI でやりとりしたいアプリケーションにとっては、やはり必ず必要です。
※ 例えばリッチエディットコントロールをラップする、といったら、リッチエディットコントロールを扱う周辺の関数や定数を、一つのクラスにコンパクトにまとめてしまう、使いやすいように新たに便利な関数を作ってそのなかに収める、そういうクラスを作る、ことを言います。
※ これらコントロールを利用するということは、マイクロソフトデザインのリストビューやらボタンを使用するということではあります。CreateWindow関数 と SendMessage関数。
※ コンポーネント自体はあるようです。
VCL : Visual Component Library
VCL
は、Borland C++ Builder BCB に付属しているもので、具体的内容は Borland 社独自のもので MFC とは異なりますが、考え方としては MFC に相当するものです。VCL を中心に解説するページでは、MFC こそ VCL に相当するものだ、と説明されることでしょう。独自のラッパーがついています。[もともとは Delphi の...]ここで使わせてもらう フリーコンパイラ bcc は、
BCB のコンパイラ部分のみが提供されたものです。VCL は使えません。
ATL : Active Template Library
[公式の説明]"
ATL" と "COM" はセットで考えます。ATL
は、MFC と同じように、マイクロソフトの "C++ によるライブラリ" です。COMプログラミング
では、COMという技術によって(たよって)、具体的には、推奨される ATL を使用して、開発を行います。ATLは、COMオブジェクトを効率よく作るためにあるとされていますが、必ず ATL が必要であるかは述べられていません。COMオブジェクトを作るのに、ATL を利用することは一般的な推奨事項のようです。COMコンポーネント
を「作っ」 てみたことがないので、実は詳細は述べられません。ところが、いまのところわたくし個人は、ATL が "使用できないフリーコンパイラ" からでも、正式な意味での COMプログラミング はできるのではないかと思っています。bcc の説明書には midl.exe の使用法や IDL に関して記されています。そして、COMオブジェクトを「扱う」 ことは ATL がなくても可能です ( IStream、IStorage インターフェース等、各インターフェース )。ただ、今のところ、オブジェクトを「扱った」 だけ、というのは、Windows API によるプログラミングの延長と考えることにして、COMプログラミングとは呼ばないことにします。ATL と MFC は両者ともマイクロソフトのものですが、2つともお互いに別の技術です。ATL は MFC と同様、製品 「VC++」から、プロジェクト開始時に選択できます。マイクロソフトの生み出したもの、という意味では、この2つは並べて考えてよさそうです。
MFC は、「クラス化がなされていてイベント駆動式」 で、プログラマのコード記述がスムーズになるという点が主眼ですが、ATL は、コンピュータへのアクセスに関する技術的な部分を提供するのが主眼なので、サービス的な性質も違うし、技術的な意味あいも全く違います。また、MFC と違って、ATLの場合は、フリーコンパイラからでも利用できないこともありません。また、フリーコンパイラでも MFC と ATL の両方ともはじめから使用できるものがあります (Digital Mars)。COM : Component Object Model
[呼称について]
COMプログラミングとして説明される場合、ATL を使うことを前提として説明されていることが圧倒的に多いです。そして VC++ の 「ATLウィザード」で話を進めるのでその場合やはり参考になりません。その方向からのアプローチを避けるために以下、多少長くなります。COMコンポーネントを作って、それを使用する、という一環をCOMプログラミングといえばいいのか、悩みどころです。なぜかというと、COMコンポーネントやCOMオブジェクト を「利用」することは、ATL を使わなくても、またそれを、COMプログラミングと呼ばなくても、Windows API を利用することだけでできるからです。しかも、これを可能にしてくれる Windows API の中の 「部分」をもはや、 Windows API と呼んでいいのかも、わたくしにはわかりません。Windows API としての説明がなされていないのに、なぜかありがたいことに、配布されているものには含まれています。そして COMオブジェクトを利用しているからそれはCOMプログラミングだといっていいのかもわからないし、Windows API プログラミングと呼べるのかもわからないからです。C/C++ と Windows API だけから COM オブジェクトを利用するだけのことは、暫定的には前者と呼べずに後者と呼べるか、または 「拡張Windows API プログラミング」 となるでしょう。[COM] さて、Windows API という 「仕組み」では、主に関数を、「利用」するだけです。もう「提供」が確立されたものを利用するだけ、ということです。
COM という技術 (仕組み) のおかげで、それに相当するもの (COMコンポーネント)を、「作り : Server 側 (提供)」 そして 「使う : Client 側」 ことができます。(COMプログラミング) この、Server 側を作るにも、Client 側を利用するにも、独特の 「インターフェース」 というものを使いますが、実態は 「C++ の "クラス"」 オブジェクトへのポインタです。C/C++ と Windows API を使いつつ、このインターフェースをプログラム内で扱うことは、普通に可能です。※ COMコンポーネントの作成に関しては詳しく述べられません。[DLLとCOM] C/C++ と Windows API によるプログラミングでは、"DLL" というものを作成できます。この DLL の中に関数を詰めておいて、あとからその関数を 「動的」に、呼び出すことで利用します ( GetProcAddress() 関数 )。この DLL の技術を使えば、「作って : Server」、「利用する : Client」 という、上で言ったことが、達成できてしまいます。ところが、この "DLL" は ("GetProcAddress()" 関数で DLL に直接触れてからでないと説明しするのが徒労のように思えますが敢えて)、汎用性をもたせて 関数を公開するのには多少不便なのです。
COM という技術 (仕組み) を活用すると、関数(やメソッド)の作り手も使い手にも、規格化されたやりかたがあるから、「DLL」 によって直接関数を提供するよりは、プログラム上からそれを 「使う」 側にとってメリットがあり、汎用性があるのです。COM はもともとの DLL という技術の拡張です (そもそも COMコンポーネント自体基本的に DLLです)。[COMプログラミングの目的]
COMプログラミングは、DLL作りを練習するときに、「DLLを作って」から、「DLLの関数を呼んでみる」 のペアでやらないことには意味がないのと同じように、「(COMコンポーネント:関数)をつくり」、「それ( COMコンポーネント: 関数) を使う」 ことでやっとなりたつことのようです。そしてこの、COMプログラミングの根本的な意義は、自分の作った関数とかを「公開」できる、という点であることは確かです。或いは、システムにより深くアクセスできるかもしれません。そしてただ、難解さとあまりのネタのなさが協調しあうために、非常に物好きでなければやってみる機会がありません。COMプログラミングと、C/C++ と Windows API のみのプログラミングとは別物でしょうか。否、このホームページでは、勘違いをおそれずに、
COMプログラミングは、後者の延長だと思っておくことにします。ただ同時に今のところ十分な情報がないので、「本格的な」COMプログラミングはあきらめることにします。[Windows API から COM へ] 返す返すも、
COMコンポーネントは「作っ」たことがないので詳しいことは述べることができません ( midl.exe、タイプライブラリ、IDL記述、等 )。ただ、「利用」するほうは大いに簡単です(C/C++ と Windows API の延長で)。だったら簡単なほうからやりましょう。インターフェースと呼ばれるものを利用しますが、C++ の "クラス" への "ポインタ" を応用したものです。ポインタだから結局は単なる数字です。また、オブジェクトの識別には、 guid や iid などの考え方を使います。ただ、「利用」 のほうは、パソコン内には本当に多くの COMコンポーネントがあるのに、そのなかで プログラミングのネタになるものが本当に乏しいのが残念です。( IRichEditOle , ITextDocument : リッチエディット、IHTMLDocument2 、DirectX など、これらはCOMオブジェクト。IHTMLDocument2 だけ 一応 ATL を必要とします。ほかは、Windows API だけでも可能です。ただ、この際 Windows API と呼んでいいかが微妙な線です。提供はされていても説明のない部分があるからです (VARIANT、VariantInit()、SysAllocString()、<oleauto.h>) 。Windows API リファレンスに載っている部分は API だと思うことにしましょう。 わたくしの勘違いかもしれませんが、これらの型(構造体)や関数は、Windows API → COM の臨界点を示しているのだと思います。物好きしかやらないと思いますが、やってみれば、API → COM への発展を肌で感じることができるでしょう。MFC を使うのが MFCプログラミングだから、
ATL を使ったプログラミングを、ATLプログラミングといってもよさそうだと思いますが、COMプログラミングには ATL が推奨されているだけに、COMプログラミングと呼んでいることが圧倒的に多いようです。ATL/COM プログラミング のようになっている場合もあります。※ COMコンポーネントとCOMオブジェクトという言葉は多少あいまいの可能性があります。
※ MFC や ATL は VC++ に付属するだけではなく、BCB にも版により、付属します。
STL : Standard Template Libraray( 標準テンプレートライブラリ )
STL
は、C++ 言語の概念です。ATL とも違います。STLプログラミング
といったら、C++ の勉強のことだと思います。わたくしは、構造体でできることを配列でやろうとしたり、
STL でやれば簡単にできることを 構造体のリスト構造でやってしまったりした経験があります。無理のない程度でも早めに STL に目を向けておくと、きっと得をします。MFCプログラミングでもVCLプログラミングであろうと、C/C++ と Windows API によるプログラミングだろうと COMプログラミングであろうと、
STL はもちろん使用できます。
DirectX
DirectXプログラミング
は、DirectX を扱います。スクリーンセーバーや、グラフィカルな 2Dや3Dのゲーム、図形の立体シミュレーションプログラムなどが作れるでしょう。一般の Windows 利用者としては、DirectX が楽しめるように、DirectX をインストールして、マイクロソフトからサービスを受けますが、これをインストールしたからといって、DirectXプログラミングが可能になるわけではありません。ただもちろん DirectXプログラミングをやるのであれば、左記のインストールは必要です。DirectX
プログラムを作りたい場合は、基本的には、 "Platform SDK" の "DirectX SDK" に、必要なヘッダファイルやスタティックライブラリが用意されていますが、色々問題があります (coff、omf)。問題なく DirectXプログラミングをやりたい場合は、Watcom や lcc のフリーコンパイラをあたるといいでしょう。bcc や Digital Mars のものでは、"DirectX SDK" のうち、ヘッダファイルのみが必要な目的物となります。あとは使いものにならないので自分であれこれ準備することになります。果ては数学的関数の自作です。こちらでもできないことはありません。詳しくはいろいろ調べてください。[こちらも参考まで]DirectXプログラミング
では、インターフェース( DIRECT3D8 : IDirect3D8 * など ; これは DirectX 8 の場合 ) を使うので、COMオブジェクトにも触れることになります。この場合は、ATL は必須ではありません。
※ VC++ をもっていなくても、Platform SDK には、mfc や atl のソースが含まれています。これらがなんの目的で含まれているいるのかはあまり明確ではありませんが、いいヒントになると思い、少し探索してみました。MFC でしか使えないものに、スプリッタウィンドウがあります。このソース (winsplit.cpp) が C:\Program Files\Microsoft SDK\src\mfc ディレクトリにあったので、bcc で、コンパイルに挑戦してみましたが、一筋縄ではいかないようです。コンパイルできない部分などを確かめてみると、c++ コンパイラの各社のせめぎあいの技術的な先端、コンパイル技術の限界点に接近することができます。C++ の高度な文法は、コンパイラによって扱えるものと扱えないものがあります。ただ、この試みは失敗しましたが、atlbase.h は、少々手直しすると、或いは手直ししなくても直接コードを利用すれば、テンプレートの "CComPtr" や "CComQIPtr" (スマートポインタ) などが使えます。bcc で com をやりたい場合は(
COMプログラミング)、必要なものとしては、Platform SDK の、atlbase.h などをヒントにします ( これも、C:\Program Files\Microsoft SDK\src\mfc)、更には midl.exe 。※※ テンプレート特化... や、同時に宣言の構文エラー、といったコンパイルエラーが出るようであれば、それはコンパイラがサポートできない文法で書かれているということです。コンパイラのバージョン次第で、新たな C++ の feature が追加されるなどすれば、コンパイルが可能になるかもしれません。
※ VBプログラミング (VB: Visual Basic) は 、C/C++ 言語は使いません。独特の文法形式を用いますが、VB からも Windows API を使用することができます。
※ Windows API も Platform SDK も、「プログラムを組む側のために提供されるサービス」 であることはおなじです。Windows API は、主に、オペレーティングシステムの中に「組み込ま」れる形で提供されているもので、プログラマーが 「OS に容易にアクセスするため」 に欠かせない、"仕組み" としてのサービスです。そのような仕組みが OS に 「組み込ま」 れていないと、Windows に向かって Programatically に命令を出すこと自体が不可能になります。Windows API は、"仕組み" ということだから、内容としては「サービス」 ということに加えて、「OS 論」 的、技術的 な色合いが濃いものです。一方、Platform SDK は、ヘッダファイルやライブラリ、そしてツールといった、具体的なプログラミング作業で必要となるもの、を配布するという形になっています。DirectX SDK もこちらに属します。Windows API と Platform SDK は、必ずしも一致しません。そして、Platform SDK は、Windows API (というサービス又は技術) の 「一部」 を含んでいます。Platform SDK の、この「一部」 がないと、Windows API というサービス又は技術は完結しません。
※ リソーススクリプトも Platform SDK の範囲に入るようです。Platform SDK には、"一応"、「リソースコンパイラ」 が付属しています。
※ 広義(という格式ばった言葉を使うのも若干気が引けるのですが)、広義には、Windows API といったら、Java API も含むだろうし、新たな API、WinFX API も登場してきているようです。しかし、システムの中枢と結びついているのは、Win32 API で、特に Java〜、や、〜FX といっていない限り、Windows API とはこの、「Win32 API 」 のことを指すと思います。これが特に中枢的な、API たる API だと個人的には言いたいのですが、Windows API の歩んできた過程 ( Win16 〜 Win32s 〜 (Win32c) Win32 : それぞれ API の名前 ) と、Win32 にきてどうやら進歩 (関数の数) が落ち着いたこと、そして、数千というその API の数 ( ただし "API関数" だけなら数千にのぼらないはず、やる気をなくしますね。定数の定義を含めたりするとだと思います。 ) がその根拠です。
※ 「C/C++ だけ」 によるプログラミングは ここでは言うまでもないことです。Windows API を使用する場合 (Win32 アプリ)、コンパイル時に オプション -tW などを使って、「bcc32 -tW ソースファイル」 のようにしますが、一方、C/C++ だけでプログラムをしたいとき、書いたとき (16ビットコンソールアプリ) は、それらのオプションなしで、「bcc32 ファイル名」、とすればよいことになります。bcc32(.exe) というのはこの際具体的なコンパイラの実行ファイル (実行モジュール) です。
※ C# ( シー・シャープ ) は、文法には C++ を用います。これはマイクロソフトの仕様です。C/C++ のように"標準的"な言語体系ではありません。Windows API 関数と1対1対応になるような関数を使うことができますが、Windows API を利用しているものではありません。さらに、Windows の上位機種専用です。( Windows 98上では、おそらくできた実行ファイルを走らせることも不可 ) 探索の結果なんと、わたくしの XP マシンには、C# コンパイラが付属してました。(C:\WINDOWS\Microsoft.NET\Framework 以下 )
※ アセンブラ次第ですが、アセンブリからも Windows API は利用できます。
※ あまりメジャーとはいえないものではありますが、wxWindow や、FOX-Toolkit、WTL を使ったプログラミングなどがあります。これらも、MFC や VCL のように考えてよいですが、FOX-Toolkit などは、「メッセージループ」 のレベルから、独自に構成されています。
要点
C/C++ と Windows API (だけ) でプログラムを組もうというときには、
さて、いいヒントにはなればさいわいです。
トップ <<前へ 次へ>>