ウィンドウのカスタマイズ(customize)

Windowsアプリケーション ソフトウェアを作る場合、作成するウィンドウの大まかなイメージを描く必要があります。最近、Raman散乱用の分光器の制御用に作成したウィンドウを以下に示します。クライアント領域には、水銀ランプのスペクトルが描かれています(横軸は波長:nmで、縦軸は:強度 )。

ソフトウェアの中身は無視して、見かけだけ同じものを作ってみましょう。ウィンドウ事始めで説明した方法で、プロジェクト名をspec25として、新規にプロジェクトを作ります。これをカスタマイズして行きます。


ウィンドウの大きさ

spec25.cppの中に
CMainFrame::CMainFrame()
{
	Create(((Cspec25App*)AfxGetApp())->mainclass,
		"spec25 Program",
		WS_OVERLAPPEDWINDOW,
		rectDefault,NULL,NULL);
}

という部分を見つけてください。Create関数はウィンドウを作成(create)する関数ですが、その引数でrectDefaultがウィンドウの大きさの初期値を指定しているところです。rectDefaultは、デフォルト値(default:初期設定 いろいろな変数に対して、我々が意識して設定しないときには、Visual C++が設定している値を初期値とします。これをデフォルト値と言います)を表しています。ここを、適当な値に変えます。以下のように変えてください。詳しくは説明しませんが、これで縦700、横1000の大きさのウィンドウになります。

CMainFrame::CMainFrame()
{
	CRect rectWin=rectDefault;

	rectWin.right=rectWin.left+1000;
	rectWin.bottom=rectWin.top+700;

	Create(((Cspec25App*)AfxGetApp())->mainclass,
		"spec25 Program",
		WS_OVERLAPPEDWINDOW,
		rectWin,NULL,NULL);
}

ここで、プログラムを実行して画面の大きさを確認してください。縦横の大きさを変えてみるのも良いと思います。また、興味があれば、"spec25 Program"のコーテーションで囲まれた文字を変えた時、どこが変わるのかを確かめるのも良いと思います。


クライアント領域の色

Raman散乱は通常暗い部屋の中で行います。そのとき、クライアント領域の色の明度が高いと目によくありません。そこで、クライアント領域を、暗い色に変えます。 spec25.cppの中に関数Cspec25App::InitInstance()を見つけ、そしてその中に

	HBRUSH hbrush   = (HBRUSH)::GetStockObject(WHITE_BRUSH);

という行を見つけます。これを以下のように変えます。

	HBRUSH hbrush   = CreateSolidBrush(RGB(0,0,90));

これで、クライアント領域の色は、赤(R)、緑(G)、青(B)の3原色の値(それぞれは0から255までの値をとれます)で指定します。今の場合、青色で値が小さい90ですから、暗い青になります。RGBの値を適当に設定すれば、好きな色にすることができます。(注)

ここで、プログラムを実行してクライアント領域の色を確認してください。

注:Windowsにはペイントというソフトウェアがありますので、それを起動して、メニューの色->色の編集を選択すると色の編集のためのダイアログ ボックスが現れます。そこで、色の作成ボタンを押すと、ダイアログ ボックスが右手に広がり、その右端に赤、緑、青を指定するところがありますので、そこに適当な値を入れると、その値に対応する色が現れます。


メニューの作成

Visual C++のメニューで、挿入->リソースを選択すると、以下の様なリソースの挿入というダイアログ ボックスが現れます。そこで、マウスでMenuを選択して、新規作成ボタンを押すと、

次の図の様に、ワークスペース ウィンドウの中にIDR_MENU1という名前が、また、このウィンドウの右隣にメニュー作成ウィンドウが現れます。

次に、メニュー作成ウィンドウに2重に点線で囲まれた部分を、マウスで右クリックすると、

の様な、メニューアイテム プロパティというダイアログ ボックスが現れます。そこで、次のように、ポップアップについているチェックをクリックで外し、ID欄にID_FILE(半角で入力)、キャプション欄にファイルと書き込んでください。

すると、メニュー作成ウィンドウは以下の様になります。

これで、ファイルという項目を持つメニューができました。

メニュー項目を増やします。ファイルという項目の右に2重に点線で囲まれた部分を、マウスで右クリックします。あとは上記と同じ方法で、 ID欄とキャプション欄に、ID_ORIGIN、基点設定と書き込みます。さらに、ID欄とキャプション欄に、ID_START、測定開始とID_STOP、測定中止とするメニュー項目を2つ増やします。次のようになります。


メニューの表示

まず、メニューの名前を変えます。上図で、ワークスペース・ウィンドウの中のIDR_MENU1という名前を右クリックすると、下図、左のようなウィンドウが現れるので、一番下にあるプロパティーを左クリックで選択します。すると、下図、右のダイアログボックスが現れるので、ID欄をIDR_MENU1から"MENU"(適当な名前で結構ですが、半角のコーテーションで囲むこと)へに変えます。これで、メニューの名前が"MENU"となります。

次に、ワークスペース・ウィンドウの下方にある、File Viewタブをクリックし、Source Filesにあるspec25.cppなる文字をダブルクリックして、spec25.cppの中身を表示させます。関数CMainFrame::CMainFrame()の中のCreate関数の引数を再び変えます。Create関数の引数の一番最後にあるNULLのところを、次のように"MENU"としてください。これで、先ほど作った"MENU"という名前のメニューを持つウィンドウができあがります。

	Create(((Cspec25App*)AfxGetApp())->mainclass,
		"spec25 Program",
		WS_OVERLAPPEDWINDOW,
		rectWin,NULL,"MENU");

ここで、プログラムを実行して、メニュー付きのウィンドウとなっていることを確認してください。


メニュー項目に対応するハンドラー関数

作ってきたプログラムを実行してみると分かると思いますが、メニューのファイル等の項目を選択しても何もおこりません。クリックしたということは、イベントを発生させたわけですが、このイベントに対するハンドラー関数を作っていないからです。ここでは、測定開始というメニュー項目に対するハンドラー関数だけを追加します。ハンドラー関数を追加する方法は、すでにメッセージのところで説明しています。Visual C++のメニューから表示->ClassWizardを選択すると、次のようなMFC ClassWizardというダイアログボックスが現れます。

このダイアログボックスで、オブジェクトIDでID_STARTを、またメッセージでCOMMANDをマウスで選択し、関数の追加ボタンを押します。すると

のようなダイアログ ボックスが現れ、ここでハンドラー関数の名前を決めます。デフォルトでOnStart()という名前になっています。ここでは、このままの名前としますので、OKボタンを押します。すると、spec25.cppの一番下に、関数OnStart()が

void CMainFrame::OnStart() 
{
	// TODO: この位置にコマンド ハンドラ用のコードを追加してください
	
}

のように追加されています。

さて、ここで、この関数がきちんと働いていることを確認します。まず、//TODOの位置にマウス カーソルを持ってきてクリックすることにより、カーソル(縦棒で、文字を入力する位置を示す点滅する縦棒)を、ここにもって来ます。Visual C++メニューで、ビルド->デバックの開始->カーソルの前まで実行を、マウスで選択して行くと、ダイアログ ボックスが現れ、ビルドを行いますかと聞かれますので、OKボタンを押します。これで、プログラムが実行されます。メニューのファイル項目をクリックすると、先ほど設定したカーソル位置でプログラムが止まれば、正常です。それを確認したら、デバックを終えます。具体的には、Visual C++メニューのデバック->デバックの中止を選択します。なお、デバックは虫取り(debug)を意味し、プログラムに潜む間違い(害虫に例えられます)を取り除くことを意味します。

実際のプログラミングでは、この、//TODOの位置に、Raman散乱スペクトルのデータを収集する作業をプログラミングするのですが、ここでは、なにもしません。


ステータス バーの追加

通常ウィンドウの最下位に表示するものが、下図のようなステータス バーです。 プログラムのなかで示したい情報を表示したりします。例えば、測定の何%が終了しているのかを実時間的にステータス バーに表示します。ウィンドウにステータス バーをつけるのには、少々手間が掛かります。次のようにします。

1. spec25.cppの中に、IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)という所を見つけます。その上に

static UINT indicators[] =
{
	ID_SEPARATOR,
	ID_SEPARATOR           // ステータス ライン インジケータ
};

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

の様に、indicators変数を追加します。これで、ステータスバーが2区画(ペイン:pane)で構成されることになります。さらに区画を増やす場合は、ID_SEPARATORをカンマで区切って追加します。

2. 関数CMainFrame::CMainFrame()に、関数status.Create等を以下のようにつけ加えます。


CMainFrame::CMainFrame()
{
	CRect rectWin=rectDefault;

	rectWin.right=rectWin.left+1000;
	rectWin.bottom=rectWin.top+700;

	Create(((Cspec25App*)AfxGetApp())->mainclass,
		   "spec25",
		   WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
		   rectWin,NULL,"MENU");

	status.Create(this,WS_CHILD|WS_VISIBLE|CBRS_BOTTOM,IDR_STATUS);
	status.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT));
	status.SetPaneInfo(0,0,0,200);status.SetPaneInfo(1,0,0,900);
	status.SetPaneText(0,"測定状況");

}

ここで、SetPaneInfo(0,0,0,200)で第0区画の幅を200とし、SetPaneInfo(1,0,0,900)で第1区画に幅を900としています。またSetPaneText(0,"測定状況")で、第0区画に初期設定として"測定状況"なる文字列を表示しています。第1区画にも何か表示したければ、status.SetPaneText(1,"何か");を追加します。

3. ワークスペース ウィンドウで、Heder File(フォルダの様になっています)をダブルクリックして、現れるspec25.hをダブルクリックします。すると、spec25.hの内容が表示されます。その中で、以下のように、クラスの定義であるclass CMainFrame : public CFrameWndの一番下に、privated:とCStatusBar status;の2行を追加します。これで、CStatusBar(ステータスバーを扱う専門家と思ってください)のstatusさんを登場(生成)させることができます。前項でのstatus.Createなどは、このstatusさんにステータス ウィンドウ(ステータスもウィンドウの1種です)の作成などを、お願いしていることになります。

	DECLARE_MESSAGE_MAP()
private:
	CStatusBar status;
};

なお、クラス内だけで使う変数はクラス変数(今の場合はクラスの実体です)と言いますが、これは原則としてprivate:とします。記憶願います。クラス外から変数を変えることも(public:)、またこのクラスから派生させるクラスから変数を変えることも(protect:)できますが、できるということは、意図しないで変えてしまうという危険性を伴います。できるだけ、変えるということに制限をもうけた方が安全なので、private:にします。

4. 最後に、ワークスペース ウィンドウでResource.hをダブルクリックして、その内容を表示させます。そこで、IDR_STATUS [status.Create(this,WS_CHILD|WS_VISIBLE|CBRS_BOTTOM,IDR_STATUS);の最後の引数に対応します。] を定義(define)します。下の例ではIDR_STATUSを130なる数値とします。#define _APS_NEXT_RESOURCE_VALUEに書かれている数値です。

#define IDR_MAINFRAME                   128
#define IDR_STATUS                      130
以下略

4. 130という数値は使ったので、#define _APS_NEXT_RESOURCE_VALUEの値を1つ増やします。

#define _APS_NEXT_RESOURCE_VALUE        131

ここで、プログラムを実行して、ステータス付きのウィンドウとなっていることを確認してください。

注:プログラムを実行してみると分かるのですが、"測定状況"と書かれたところがへこんでいるように見え、少々見栄えがよくありません。これを解消するには、ClassWizerdダイアログを表示させ(メニューで表示->ClassWizerdを選択)、そのメッセージ欄で、PreCreateWindowをマウスで選択して、関数の追加ボタンを押すと、spec25.cppの最後に関数PreCreateWindowが追加されます。その関数の内容を

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 
{
	//	3D枠を書かない様にする
	if(!CFrameWnd::PreCreateWindow(cs))
		return(TRUE);

	cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
	return(TRUE);
}
のように書き換えます。


アイコンの変更

私は、くまぞうさんのアイコン(http://homepage1.nifty.com/KUMAZO)を好んで使用しています。ここでは、その1つであるspec25.icoを使いましょう。このファイルを、spec25フォルダの中のresフォルダの中にspec25.icoがありますが、これと取り替えます。spec25フォルダの中のspec25.dswをダブルクリックしてVisual C++を立ち上げて、メニューで、ビルド->リビルドを選択します。リビルド(rebuild:再構築)が終了し、再度プログラムを実行するとアイコンが変更されます。好みのアイコンに変更してみてください。ただし、アイコン名はspec25.icoと変更しなければいけません。 参考までに、できあがったプログラムはspec25.zipです。


戻る