#pragma twice

KAB-studio > プログラミング > #pragma twice > 143 Version 8.01 ウィンドウズ、はじめの一歩

#pragma twice 143 Version 8.01 ウィンドウズ、はじめの一歩

前のページへ 表紙・目次へ 次のページへ

 Version 8.01
ウィンドウズ、はじめの一歩

前回まではデバイスコンテキスト編。今回からは、 MFC を使わずにダイ
アログを作ってみます
それって大変?
大変
げげ
っていうより、これまでと全然違う感じだから、その辺は戸惑うかもね
全然違うの? じゃあ、 MFC を使うのと使わないの、どっちやればいい
の?
両方ともできないと
そりゃ無理でしょ
その無理をって話。ま、実際には MFC は API から作られてるんだし、あ
る程度分かってくれば大丈夫でしょ
ホントに?
たぶん。じゃ、まずは元になるプロジェクトを作りましょう。メニューか
ら【ファイル】−【新規作成】を選んで
ここまではいつもと同じよね
【プロジェクト】のページから、いつもは【MFC AppWizard (exe)】を選
んでいたけど、今回は【Win32 Application】を選んで
 AppWizard って付いてないね
そう、これまでのダイアログアプリは AppWizard が基本的なプログラム
を作ってくれたけど、これはそうじゃないから一から作る必要があります
だから面倒なわけねー
プロジェクト名は SimpleDialog にでもしようかな
それでOKね。うお、次のページがもう違う!
【空のプロジェクト】【単純な Win32 アプリケーション】【標準的な 
"Hello World" アプリケーション】のみっつがあるけど、今回は最初からや
りたいから【空のプロジェクト】を選んで
……他のを選ぶと、少し簡単になるんじゃ……
それはそうなんだけど、少し書くことが少なくなるくらいだし
うー
それに、これまでのって、なんか MFC のクラスがごちゃっとあって
わけ分かんない感じではあったけどねぇ
それがないから、そういう意味では楽しいと思うよ
……ま、しゃーないか
というわけで【空のプロジェクト】を選んで【終了】ボタンを押して
ほい。次のもOKね
じゃ、作られた SimpleDialog フォルダを見てみて。
えーっと、空の Debug に、 SimpleDialog.dsp 、 SimpleDialog.dsw 、 
それに SimpleDialog.ncb の3ファイル……だけ!?
そう、つまりプログラムはまったくなし!
異常だわ……
ま、ホントはこれが普通なんだけどね
 AppWizard は過保護?
そうなるかなー。今度は、 VC のワークスペースで【FileView】を見て
こっちもまったくファイルがないねぇ
というわけで作ります。メニューの【ファイル】−【新規作成】を選ん

あれ、さっきと同じ……と思ったら、ページが【ファイル】になってる
プロジェクトを開いてる時はこっちが出るから。この中から【C++ ソース
ファイル】を選んで、ファイル名には Main.cpp にして
ほいOK。ん?  Main.cpp が開いたのかな?
何も書かれてないから分かりにくいけど、そう。これで SimpleDialog の
方にも Main.cpp ができてるでしょ
【FileView】の【Source Files】にも追加された
ここに、次のように書き込んで

#include <Windows.h>

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    MessageBox( NULL, "テスト", "WinMain()", MB_OK );
    return 0;
}

ん? 結構短いね
うん、これはね
これはね、ですか……じゃ、ビルド。うん、ビルドは通ったね。じゃ、実
行。お! ダイアログが出た!
 OK を押すと
ダイアログ閉じた。なんだ簡単ねーって、これは MessageBox() で出した
ダイアログじゃない!
そう、普通のダイアログを作るのはちょっと先
ってことはやっぱ簡単じゃないのねー。話がうますぎるとは思ったの
よ〜
泣かない泣かない。とりあえずひとつずつ見ていきましょう。まずはイン
クルードしてる Windows.h から
初めて見るインクルードファイルだけど、すごくべたなファイル名よね
そう、実は API を使うためには必ずインクルードしなきゃいけないファ
イル
じゃあ MFC 使ってる時は、 MFC が勝手にインクルードしてる?
そゆこと。直接は afxv_w32.h がインクルードしてるから見ておいて。こ
の afxv_w32.h を間接的に afxwin.h がインクルードしてるから
??
あ、この前の Anime プロジェクトを開いて StdAfx.h を見てみれば
お、 afxwin.h をインクルードしてる。つまりここから間接的に 
Windows.h をインクルードしてるわけね
そゆこと。このファイルのインクルードは必須ってことで
次の WinMain() は関数だよね
そう。これはとっても重要だから、抜き出してみます

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )

まずは WinMain() って関数の名前。実はこの名前がとっても大事
関数名が?
普通に作った関数はプログラムの中から呼び出されるけど、この
WinMain() って関数は別。この WinMain って名前の関数は、プログラムの
中で一番最初に呼ばれることになってます
つまり、プログラムのスタート地点ね
まさにそう。こういう、プログラムの中で一番最初に呼ばれる関数のこと
を【エントリーポイント】って言います
エントリーって〈入口〉とかって意味だよね。まさにプログラムの入口っ
てわけね
あ、ひとつ注意。 WinMain() がエントリーポイントなのは、ウィンドウ
ズアプリだけ。他だとまた違ってくるからね
ま、それはまだ先の話だしー
あと、これは自分で作る関数だけど、どういう関数かっていうのはリファ
レンスにちゃんと書いてあるから。 MSDN を見てみて
ほい。うん、戻り値や引数同じだね
ウィンドウズではこういう、自分で作る API が結構あるから、そういう
時にはこの MSDN のリファレンスを参考にして作ることになるかな
引数の名前とかは違ってもいいんだ
そう、それは変えてもいいから。そういうのって難しいよね
そうなのよねー、どこを変えていいのか、どこを変えちゃいけないのか、
その辺って難しいかも
そこまでたどり着くのって、結構先かも
げげ
そういうのの第一歩かもしれないのが、 WINAPI って印
戻り値? int WINAPI って
ううん、戻り値じゃないんだよね。戻り値は int 。 WINAPI は、関数の
性質を決めるためのもの
関数の性質?
まず、コンピューターの世界では、関数ひとつ呼ぶにもいろんな手順が必
要、ってことを憶えて
見た目は全然分かんないけどね
ポインタみたいに、プログラムの裏に隠された世界、って感じかも。 
WinMain() は、外から呼ばれるんだけど、〈外〉ってどこだと思う?
メッセージとかみたいに、ウィンドウズそのもの?
そう! WinMain() はウィンドウズから呼ばれるんです。それはつまり、
アプリの外から呼ばれるってこと
ってことは、普通の関数はアプリの中から、 WinMain() は外から呼ばれ
るから WINAPI が必要ってこと、なのかな
そうそう、プログラムの中から呼び出す時の手順と、外から呼び出される
時の手順が違うから、 WINAPI を付けるんです
そういうルールなのね
コンピューターの世界は厳密で複雑だからね。こういうのも知らないとい
けないっていうのは、 VC プログラマーの大変なところかも
ってゆーか、見えないところだから教えてもらわないと分からない
し……
確かにね、この辺は情報も少ないし。あ、でも見えるところもあるよ。た
とえば…… API の MassageBox() 。この宣言部が Winuser.h にあるんだけ


WINUSERAPI
int
WINAPI
MessageBoxA(
    HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType);

あ、 WINAPI が付いてる!
 API は、アプリの外にある関数だから
そっか、 WinMain() とは逆の立場なんだ。これはあたし達が外から呼び
出すから、 WINAPI が付いてるのね
アプリの外から呼ばれるのなら WINAPI 、中からなら何もつけなくてい
い、ってとこかな
うんうん。あれ? でも、これ見るとなんか……
 MessageBoxA() って A が付いてること?
あ”、そういえば。何これパチモン?
これはちゃんとした MessageBox() だよ。むしろいつも呼び出してる 
MessageBox() の方が偽物
???
ま、それはまたおいおい。最後に、 WINAPI の正体について。 Windef.h 
に書いてあります

#define WINAPI      __stdcall

この __stdcall が関数の性質を変えるのね
そゆこと。コンパイルする時にこれを見つけると、関数の性質を外から呼
べるようにしてくれるんです。あと、普通の関数、つまり中から呼ばれる関
数には __cdecl ってのが付きます
?? どゆこと?
んーと、つまり、ホントに何も付いてない関数、ってのはないってこと。
関数の性質を決めるために、 __cdecl か __stdcall か他の何かか、とにか
く何かを付けて関数の性質を決めないといけないわけ
見えないけど、全部の関数に __cdecl が付いてるわけね
そんな感じ。ちなみに、全部 __stdcall が付いてることにすることもで
きます。メニューの【プロジェクトの設定】ダイアログの【C++】ページ、
カテゴリ【コード生成】に
お、 __cdecl がある!
ここに書いてあるように、関数の性質のことを正確には【呼び出し規約】
って言います。デフォルトのがここで指定したのだから
何も付けてないと __cdecl なわけね
そゆこと。これを変えれば
何も付けてないのが全部 __stdcall になる?
うん、たとえば WinMain() の頭の WINAPI を取ると

warning C4007: 'WinMain' : '__stdcall' でなければなりません。

あ、こういうエラーが出るんだ
正確には警告だけどね
ホントだ。実行もちゃんとできるし……
で、さっきの設定を __stdcall にすると
今度は警告出ない! じゃあ、ずっと __stdcall にしちゃえば
いや、 __stdcall は外から呼ばれるのだけに付けた方がいいから……

/*
    Preview Next Story!
*/
 __stdcall とかって細かいよねー。見た目の違いは分からないし
そう、この辺は実行ファイルの中身を直に見たりしないとね
う”、それはちょっとしたくないなー
でも次回はそれをしてもらいます
げ!
というわけで次回
< Version 8.02 インスタンスハンドル >
につづく!
今回の章はちょっと手強いかもね
手強くしてるのはあんたでしょうが!
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。