ダイアログ
■概要
ダイアログとはGUI(Graphical User Interface)で、
ユーザーに入力を求めたり、通知を行うために表示するウィンドウのことです。
Windowsのプログラムでよく利用されるメッセージボックスもダイアログの一種です。
■自作ダイアログの基本
ダイアログもリソースとして扱われていますので、
リソースファイルを用意することで自作のダイアログの作成が可能です。
ただ、ダイアログは「ボタン」や「テキスト」など、複数のアイテムから
構成されているので、ファイル作成はResEditなどのツールを使用した方が
効率はいいと思います。
●サンプル用ダイアログリソース
今回使用するダイアログのリソースとヘッダファイルを
以下のリンクからダウンロードして下さい。
ダイアログリソース
ヘッダファイル
●自作ダイアログの使用方法
・サンプルコード
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock.h>
#include "resource.h"
#pragma comment(lib, "Ws2_32.lib")
// ② ダイアログ用のウィンドウプロシージャの作成
LRESULT CALLBACK ServerProc(HWND, UINT, WPARAM, LPARAM);
// ② ダイアログ用のウィンドウプロシージャの作成
LRESULT CALLBACK ServerProc(HWND dialog_handle,
UINT message,
WPARAM wp,
LPARAM lp)
{
HWND send_button;
switch (message)
{
// ④.ダイアログの初期化
case WM_INITDIALOG:
send_button = GetDlgItem(dialog_handle, IDC_SENDBTN);
EnableWindow(send_button, FALSE);
break;
// ⑤.ダイアログ終了
case WM_CLOSE:
// ダイアログ終了
EndDialog(dialog_handle, WM_CLOSE);
break;
default:
return false;
}
return true;
}
int WINAPI WinMain(HINSTANCE instance_handle,
HINSTANCE prev_instance_handle,
LPSTR cmd_line,
int cmd_show)
{
// ③ ダイアログ作成
DialogBox(instance_handle,
TEXT("SERVER_DLG"),
NULL,
(DLGPROC)ServerProc);
return 0;
}
・手順
①.プロジェクトにリソースファイルとresource.hを追加する
自作ダイアログを使用するプロジェクトに
ダイアログの情報をコーディングしているリソースファイルと
そこで使用しているリソースIDを定義しているresource.hを追加します。
②.ダイアログウィンドウ用のプロシージャを作成する
ダイアログウィンドウのボタンをクリックされた場合などの
メッセージイベントを処理するためのプロシージャを作成します。
・ダイアログプロシージャの基本形
LRESULT CALLBACK 関数名(HWND, UINT, WPARAM, LPARAM)
戻り値:
LRESULT:
基本的に自分でメッセージを処理した場合はtrue、
何もしなかったらfalseを返す
CALLBACK:
WINAPIと同様の呼び出し規約
引数:
HWND:
ウィンドウハンドル
UINT:
メッセージ
WPARAM、LPARAM:
メッセージに対する付加情報
メッセージの内容で情報は異なる
③.DialogBox関数でダイアログを作成する
自作ダイアログの作成はDialogBox関数を使用します。
・DialogBox関数
int DialogBox(HINSTANCE, LPCTSTR, HWND, DLGPROC)
関数名:
DialogBox
戻り値:
成功:
EndDialogの第二引数の値
失敗:
0 or -1
引数:
HINSTANCE
アプリのインスタンスハンドル
LPCSTR
ダイアログの名前
HWND
親のウィンドウハンドル
DLGPROC
ダイアログ用プロシージャ
内容:
Dialogを作成する
使用するダイアログは第二引数のダイアログの名前で決める
作成に成功した場合、ダイアログが閉じられるまで、
コード上の処理が進まなくなるので、注意が必要
④.ダイアログの初期化
ダイアログが作成された直後、プロシージャに「WM_INITDIALOG」という
メッセージが送信されるので、この時にダイアログの初期化処理を行いないます。
処理の内容はダイアログごとに違うので、必ずやることはありませんが、
何もしなかった場合は「false」を返すようにして下さい。
・何もしなかった場合:
switch (message)
{
// ダイアログの初期化
case WM_INITDIALOG:
return false;
break;
}
・何かしらの処理を行った場合:
HWND send_button;
switch (message)
{
// ダイアログの初期化
case WM_INITDIALOG:
// 送信ボタン取得後、非アクティブ設定
send_button = GetDlgItem(dialog_handle, IDC_SENDBTN);
EnableWindow(send_button, FALSE);
return true;
break;
}
⑤.ダイアログの終了
ダイアログの終了はEndDialog関数を使用します。
ですが、ダイアログの終了タイミングはダイアログによって異なりますので、
ここでは「×」ボタンを押した際の終了の流れで説明したいと思います。
・EndDialog関数
BOOL EndDiaDlog(HWND, INT_PTR)
関数名:
EndDialog
戻り値:
成功:0
失敗:非0
引数:
HWND:このダイアログのハンドル
INT_PTR:アプリケーションへ返したい値(intの値で可)
内容:
引数で指定されたハンドルのダイアログを終了する
その際、DialogBox関数への戻り値の設定として
第二引数に値を設定する
・具体例:
switch (message)
{
// 「×」ボタンクリック
case WM_CLOSE:
// ダイアログを閉じる
EndDialog(dialog_handle, WM_CLOSE);
return true;
break;
}
■自作ダイアログの応用
上記は自作ダイアログの作成と終了のみ記述していますので、
ここからは自作ダイアログで設定しているボタンやテキストの情報の取得方法や
プロシージャで通知されるイベントメッセージについて記述していきたいと思います。
●イベントメッセージ
ダイアログ内のボタンをクリックした際のイベントメッセージは
「WM_COMMAND」としてプロシージャに通知されます。
どのボタンが押されたかについての情報は「WPARAM」に格納されており、
LOWORDマクロを使用することで取得できます。
このLOWORDで取得できる情報は「resource.h」で宣言しているIDです。
例:
switch (message)
{
// ダイアログの初期化
case WM_INITDIALOG:
return FALSE;
break;
// 「×」ボタンクリック
case WM_CLOSE:
// ダイアログ終了
EndDialog(dialog_handle, WM_CLOSE);
break;
// イベントメッセージ
case WM_COMMAND:
switch (LOWORD(wp))
{
// 送信ボタン
case IDC_SENDBTN:
MessageBox(dialog_handle,
TEXT("送信"),
TEXT("送信ボタンクリック"),
MB_OK);
break;
// 開始ボタン
case IDC_STARTBTN:
MessageBox(dialog_handle,
TEXT("開始"),
TEXT("開始ボタンクリック"),
MB_OK);
break;
// 終了ボタン
case IDC_ENDBTN:
MessageBox(dialog_handle,
TEXT("終了"),
TEXT("終了ボタンクリック"),
MB_OK);
break;
}
break;
default:
return false;
}
●ダイアログ情報の取得
エディットテキストに設定している情報は「GetDlgItem~」関数で取得することができます。
・GetDlgItem
HWND GetDlgItem(HWND, int)
関数名:
GetDlgItem
戻り値:
成功:ハンドル
失敗:NULL
引数:
HWND:
アイテムを取得するダイアログボックスのハンドル
int:
アイテムのID
内容:
指定したダイアログボックスからアイテムを取得する
そのアイテムをアクティブ、非アクティブ化する場合などに使用する
具体例:
// 送信ボタンのハンドルの取得
HWND send_button = GetDlgItem(dialog_handle, IDC_SENDBTN);
・GetDlgItemInt
UINT GetDlgItemInt(HWND, int, BOOL *, BOOL);
戻り値:
成功:第三引数にTRUEが設定され、
アイテムに設定されている数値が取得される
失敗:第三引数にFALSEが設定され、
0が返される
引数:
HWND:
取得したいアイテムのあるダイアログボックスのハンドル
int:
取得したい数値の入った文字列のあるアイテムのID
BOOL *:
成功か失敗を判断するBOOL値
BOOL:
符号有りかなしか
TRUE:
符号有り
※戻り値をキャストする必要有り
FALSE:
符号無し
内容:
指定したダイアログのアイテムの情報を数値として取得する
具体例:
// ポート番号入力項目に設定されている数値を取得
BOOL is_get_item = false;
int num = (int)GetDlgItmInt(
dialog_handle,
IDC_PORT,
&is_get_item,
true);
・GetDlgItemText
UINT GetDlgItemText(HWND, int, LPTSTR, int);
関数名:
GetDlgItemText
戻り値:
成功:文字列の長さ
失敗:0
引数:
HWND:
取得したいアイテムのあるダイアログボックスのハンドル
int:
文字列を取得したいアイテムのあるID
LPTSTR:
取得する文字列のバッファ(TCHAR単位)
int:
文字列の長さ
内容:
指定したダイアログのアイテムの情報を文字列として取得する
具体例:
// 送信文をエディットテキストから取得
TCHAR buff[1024];
UINT str_len = GetDlgItmInt(
dialog_handle,
IDC_SEND,
buff,
1024);
●サンプルコード
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock.h>
#include "resource.h"
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
LRESULT CALLBACK ServerProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE instance_handle,
HINSTANCE prev_instance_handle,
LPSTR cmd_line,
int cmd_show)
{
WSADATA wsadata;
DialogBox(instance_handle, TEXT("SERVER_DLG"), NULL, (DLGPROC)ServerProc);
return 0;
}
LRESULT CALLBACK ServerProc(HWND dialog_handle, UINT message, WPARAM wp, LPARAM lp)
{
HWND end_button;
int port_no;
TCHAR buff[1024];
BOOL is_success = false;
switch (message)
{
// ダイアログの初期化
case WM_INITDIALOG:
return FALSE;
break;
// 「×」ボタンクリック
case WM_CLOSE:
// ダイアログ終了
EndDialog(dialog_handle, WM_CLOSE);
break;
// イベントメッセージ
case WM_COMMAND:
switch (LOWORD(wp))
{
case IDC_SENDBTN:
// 送信文を取得して表示
GetDlgItemText(dialog_handle,
IDC_SEND,
buff,
1024);
MessageBox(dialog_handle, buff, TEXT("送信"), MB_OK);
break;
case IDC_STARTBTN:
// ポート番号を取得して表示
port_no = GetDlgItemInt(dialog_handle,
IDC_PORT,
&is_success,
true);
wsprintf(buff, TEXT("port_no = %d"), port_no);
MessageBox(dialog_handle,
buff,
TEXT("開始"),
MB_OK);
break;
case IDC_ENDBTN:
// アイテムを取得して非アクティブ設定
end_button = GetDlgItem(dialog_handle, IDC_ENDBTN);
EnableWindow(end_button, false);
break;
}
break;
default:
return false;
}
return true;
}