#pragma twice

KAB-studio > プログラミング > #pragma twice > 090 Version 5.25 ボタンを作ろう!

#pragma twice 090 Version 5.25 ボタンを作ろう!

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

 Version 5.25
ボタンを作ろう!

さて、前回はコントロールもウィンドウって所まで見ていきました
そーそー。 CreateWindow() でボタンが作れるってゆーし
では実際に作ってみましょう!
ええっ!?

// いつものメンバ関数。
void CFileTestDlg::OnBtnShow() 
{
    HWND hWnd
        = ::CreateWindow
            ( "BUTTON"
            , "てすと"
            , WS_CHILD | BS_PUSHBUTTON | BS_TEXT
            , 10, 10, 100, 30
            , GetSafeHwnd()
            , (HMENU)1050
            , AfxGetInstanceHandle()
            , NULL );
    ::ShowWindow( hWnd, SW_SHOW );
    return;
//  あとは取っておきましょう。

ビルドして実行! うわ、ホントにダイアログにボタンができた! こん
なふうにしてボタンが作れるなんてなんか感動……
他の OS はこういうふうに作ること多いかな。ウィンドウズはダイアログ
エディタで簡単にできるようになってるんだけどね
なんかこの関数って呼ぶのめんどそうだし……
でも今の火美ちゃんの知識でも全然大丈夫だと思うよ。まず最初の引数
これはウィンドウクラス名だね。これが BUTTON だから
ボタンが作られたってわけ。ちなみにウィンドウクラス名は大文字小文字
区別しないから。たとえば今作ったボタンを Spy++ で見ると……
 Button になってる
そういうこと。2番目は〈キャプション〉
これはボタンに出る文字だね
ちなみに、普通のウィンドウだとタイトルバーの名前になります
ん、なんか複雑?
3番目はウィンドウスタイル。 WS_CHILD は〈子ウィンドウ〉って意味
子ウィンドウ? あ、 Ver 5.23 ( No.088 ) でやったね
ウィンドウには親子関係とかが作られてるから。それはちょっと飛ばして
 BS_PUSHBUTTON は CreateWindow() のリファレンスに書いてあるね。ボ
タンのスタイルなんだ
押しボタン式で、文字列を表示するってもの。たとえば  BS_PUSHBUTTON 
を BS_CHECKBOX に変えると
×ボタンのになった!! へー、ってことはこれはボタンの一種なんだ
そゆこと。こういうの知らないと、別のコントロールだと思っちゃうよね
うん、そうだと思ってた
第4〜第7引数はボタンの位置とサイズ
これで位置決めするのってめんどいよね。ダイアログエディタがあれば簡
単なのに
あと、ダイアログの左上からってことに注意
あ、ホントだ。画面全体の左上じゃないんだね
ウィンドウでこういうのの操作をするときには、その辺に注意した方がい
いかな
第8引数は CFileTestDlg::GetSafeHwnd() を呼んでるってことは……ダ
イアログのウィンドウハンドルだね
そう、ここではボタンの〈親ウィンドウ〉を指定してます
あ、ここでしっかり指定しないといけないんだ。自動だと思ってた
 API の世界に自動って言葉はないって思った方がいいかも。ここで親ウィ
ンドウを指定しているから、ボタンの位置がその親ウィンドウの左上からに
なるわけ
じゃーこれを他のウィンドウにしたら?
そのウィンドウの左上から
じゃあそれをリストボックスのにしたら?
リストボックスの左上から
なんか変……
ま、その辺が柔軟だから色々できるんだけどね
第9引数はなんか変だね。 HMENU にキャストしてる
普通のウィンドウだと、ここにはメニューのハンドルを指定します
だから HMENU ね
でもコントロールなんかの子ウィンドウの場合には ID を指定します
 ID って、あー IDC_BTN_SHOW とかだ!
そゆこと。それも整数値だったでしょ
そうそう、 resource.h の中で書かれてるんだよね
この ID もそれと同じ。ホントは
 #define とか const int とかでってゆーんでしょ?
そゆこと。第9引数はちょっと難しいけど、〈インスタンスハンドル〉っ
ていうのを渡してます
前にやったね、 Ver 3.6 ( No.031 ) とかで
これは一応、アプリのハンドルって考えればいいかな。これは 
AfxGetInstanceHandle() で取得できるからそれを渡せばOK
第10引数は NULL だね
これは…… MSDN の CWnd::OnCreate() を見てみて
ほい見たよ
んーと、ちょっと戻って、 OnBtnShow() はボタンが押されたときに呼ば
れるメンバ関数でしょ
うんそだよ。 CWnd::OnCreate() もそういうの?
そういうの。これはウィンドウが作られる時に呼ばれるメンバ関数。で、
そのとき渡される CREATESTRUCT のページを
ほい
その第1引数は
 LPVOID 型の lpCreateParams ってゆーの
実は、これが CreateWindow() の第10引数そのものなんです
ええっ!? そーいえば同じ LPVOID 型だし……でも CreateWindow() の
リファレンス見るとなんか違くない?  CREATESTRUCT のポインタを渡すっ
て読めるけど
げ! ……あー、これは訳が間違ってるんじゃないかな。 CreateWindow()
の英文リファレンスを見れば
 CREATESTRUCT を通して渡される、って読めるね
このポインタは、あるクラスへのポインタをこの第10引数から渡して、 
CWnd::OnCreate() で受け取って初期化に使う、ってふうに使います
そっか、そうすればクラスの大きさとか関係なしに送れるんだね
この仕組みは API じゃよく使われてるから
でも、キャストし間違えたら……
 API はそういう部分多いからねぇ、使う時は気を付けないと
ここまででウィンドウ作りは終わりね。 ShowWindow() は、まんまウィン
ドウを表示させるのってことでいいの?
そう、ま、ホントはこの API はウィンドウを消したり最大化したりもで
きるんだけどね
やってみたい!
んじゃやってみましょう

void CFileTestDlg::OnBtnShow() 
{
    ShowWindow( SW_SHOWMAXIMIZED );
    return;
//  あとは取っとく。

あれ、最初のと引数が違うよ?
最初のは API 、これは MFC の CWnd::ShowWindow() メンバ関数
そーいえば、 :: が最初に付いてるってことは API だからなんだよね
そう。 ShowWindow() も CreateWindow() も同名のメンバ関数が CWnd に
あるからね。逆に、 CWnd のってことを明示するなら

    CWnd::ShowWindow( SW_SHOWMAXIMIZED );

そっか、 ::ShowWindow() ってゆーのは〈どのクラスにも属してない〉っ
て意味なんだ!
そういうこと。じゃ、ビルドして
実行! うわ、ダイアログが画面いっぱいに!
これができるのも、ダイアログが基本的にはフツーのウィンドウだから
そーゆーの、結構融通きくんだねー
と、話を戻して、普通にウィンドウを表示するなら SW_SHOW を渡せばO

 MFC で思ったんだけど、 MFC のなんかのクラスでもこーゆーボタン作る
ことできるの?
もちろんできるよ。 MFC には CButton っていうクラスがあって、これを
使うとかなり簡単に作れるから

CButton g_cButton;

void CFileTestDlg::OnBtnShow() 
{
    CRect cRect( 10, 10, 110, 40 );
    g_cButton.Create
        ( "てすと"
        , BS_PUSHBUTTON | BS_TEXT
        , cRect
        , this
        , 1050 );
    g_cButton.ShowWindow( SW_SHOW );
    return;
//  あとは取っておきましょう。

あ、関数の外に変数がある
グローバル変数って言って、他の関数とかからも使える変数
 API とかランタイムとかの関数ってそうだよね
そう、その変数版。だーけーどー、ホントは使っちゃダメ
なんで?
いつの間にか書き換えちゃったりする可能性があるから。できるだけ書き
換えられる範囲は狭い方がいいからね
それって const ポインタ使うのと同じ考えだよね
そういうこと!  const を使うのと同じように、グローバル変数は使わ
ない方が
書き換えられる範囲が狭まるってことね。これが悪い例だとすると、いい
例って?
 CFileTestDlg のメンバ変数にすること
 m_cDataLstBox なんかとおなじよーに?
そう、まさにそう
でもメンバ変数って CFileTestDlg のどのメンバ変数からでも使えるんだ
から、五十歩百歩じゃない?
う”……それはかなり難しい話になってくるからまた今度
あたしもそーゆー話ができるようになったのねー
子供の方が核心突くのうまいってゆーし
なんかゆった?
なんでも
……あとふたつ分かんないとこがあるんだけど。まず CRect のとこ
 CRect は MFC のクラスで、左上の x と y 、右下の x と y を格納する
クラス。【コンストラクタ】って憶えてる?
 Ver 5.17 ( No.082 ) でやったね。変数作るときに呼ぶ関数だよね
そう。ここで cRect( 10, 10, 110, 40 ) ってやってる部分は、そのコン
ストラクタを呼び出して、4つのメンバ変数にいっぺんに値を入れてるんで

そーゆー便利なのがあるのね。あと this って? 色が変わってるから 
C++ 言語のなんかなんだろうけど
 this は……今呼ばれてるメンバ関数は?
 CFileTestDlg::OnBtnShow() だけど
これもメンバ関数なんだから、当然 ????.OnBtnShow(); って感じに呼ば
れてるはずでしょ。その ???? のアドレス、つまり &???? が this
????? どーゆー意味?
前にやったでしょ、どんなクラスも、ちゃんと変数として作られてて、そ
のメンバ関数もその変数を通して呼ばれてるんだって
うん憶えてるよ。えーっと、 Ver 3.3 ( No.028 ) とかでやったよね、こ
れだと、 FileTest.cpp の CFileTestApp::InitInstance() で作られてる、
CFileTestDlg dlg; の dlg がその変数なんだよね
そう、だから基本的には dlg.OnBtnShow() って呼ばれてるってこと
うんうん
で、その dlg.OnBtnShow() の中で dlg そのものを取得したいときは?
そのとき this を使う……アドレスってことは、 this は &dlg になるっ
てことなんだ!
そういうこと!

/*
    Preview Next Story!
*/
はっきし言って、自分でボタン作れるのって、感動!
自分で操作できるのって楽しいからね
ホント、この前も言ったけど、色々できてくると楽しい!
でも、ある意味今が一番辛いかも……
というわけで次回
< Version 5.26 コントロールをゲットしよう! >
につづく!
げ、なんでエラー消えないの? なんで変なダイアログ出るのぉ!?
ほらね
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。