Cプログラミンの一環として始めた Windos API ですが、やってみたら面白かったので、もっと詳しく、かつ簡単に、ステップバイステップで学習するコーナーも作りました。
Windows API Primer
Primer は、入門書という意味です。
このサイトでは、ユーザーが操作できるGUI部品のことをコントロールと呼ぶことにしています。
Windows APIでは、ボタンなどのコントロールもウィンドウです。
ほとんどのコントロールは、WNDCLASSがデフォルトで登録されていますので、CreateWindow関数ですぐに作成できます。
#include <windows.h>
#define BEEP 100
#define QUIT 200
#define EDIT 300
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("ButtonControl");
RegisterClass(&wc);
hwnd = CreateWindow (TEXT("ButtonControl"),
TEXT("Button"),
WS_OVERLAPPEDWINDOW,
(GetSystemMetrics(SM_CXSCREEN) - 400) / 2,
(GetSystemMetrics(SM_CYSCREEN) - 250) / 2,
400,
250,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
static HWND beep, quit, edit;
RECT clientRc;
static HFONT font;
switch (msg)
{
case WM_CREATE:
GetClientRect(hwnd, &clientRc);
font = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
beep = CreateWindow(TEXT("Button"),
TEXT("ビープ"),
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
(clientRc.right - 170),
(clientRc.bottom - 30),
80, 25,
hwnd,
(HMENU) BEEP,
NULL,
NULL);
SendMessage(beep, WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
quit = CreateWindow(TEXT("Button"),
TEXT("終 了"),
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
(clientRc.right - 85),
(clientRc.bottom - 30),
80, 25,
hwnd,
(HMENU) QUIT,
NULL,
NULL);
SendMessage(quit, WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
edit = CreateWindow(TEXT("Edit"),
NULL,
WS_VISIBLE | WS_CHILD |WS_BORDER | ES_MULTILINE,
5, 5,
(clientRc.right - 10),
(clientRc.bottom - 40),
hwnd,
(HMENU) EDIT, // 今回の場合はNULLでも良い
NULL,
NULL);
SendMessage(edit, WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
break;
case WM_SIZE:
GetClientRect(hwnd, &clientRc);
SetWindowPos(beep, HWND_TOP,
(clientRc.right - 170),
(clientRc.bottom - 30), 0, 0, SWP_NOSIZE);
SetWindowPos(quit, HWND_TOP,
(clientRc.right - 85),
(clientRc.bottom - 30), 0, 0, SWP_NOSIZE);
SetWindowPos(edit, HWND_TOP,
0, 0,
(clientRc.right - 10),
(clientRc.bottom - 40),
SWP_NOMOVE);
break;
case WM_COMMAND:
if (LOWORD(wParam) == BEEP) MessageBeep(MB_OK);
if (LOWORD(wParam) == QUIT) PostQuitMessage(0);
break;
case WM_DESTROY:
DeleteObject(font);
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance,
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("CheckBox");
RegisterClass(&wc);
hwnd = CreateWindow (TEXT("CheckBox"),
TEXT("Check box"),
WS_OVERLAPPEDWINDOW,
(GetSystemMetrics(SM_CXSCREEN) - 400) / 2,
(GetSystemMetrics(SM_CYSCREEN) - 250) / 2,
400,
250,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
static HWND check;
RECT clrc;
static HFONT font;
UCHAR checked = 1;
switch (msg)
{
case WM_CREATE:
GetClientRect(hwnd, &clrc);
font = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
check = CreateWindow(TEXT("Button"),
TEXT("Show title"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
(clrc.right - 70) / 2,
(clrc.bottom - 20) / 2,
70, 20,
hwnd,
(HMENU) 1,
NULL,
NULL);
CheckDlgButton(hwnd, 1, BST_CHECKED);
SendMessage(check, WM_SETFONT, (WPARAM)font,
MAKELPARAM(FALSE, 0));
break;
case WM_SIZE:
GetClientRect(hwnd, &clrc);
SetWindowPos(check, HWND_TOP,
(clrc.right - 70) / 2,
(clrc.bottom - 20) / 2,
0, 0, SWP_NOSIZE);
break;
case WM_COMMAND:
checked = IsDlgButtonChecked(hwnd, 1);
if (checked)
{
CheckDlgButton(hwnd, 1, BST_UNCHECKED);
SetWindowText(hwnd, TEXT(""));
} else {
CheckDlgButton(hwnd, 1, BST_CHECKED);
SetWindowText(hwnd, TEXT("Check box"));
}
break;
case WM_DESTROY:
DeleteObject(font);
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Windows APIでは、スライダーのことをトラックバーと呼びます。
トラックバーは、コモンコントロールというグループに所属しています。コモンコントロールには、ツールバー・ステータスバー、リストビュー・ツリービューなども所属しています。
Visual Studioでコモンコントールを使うには、次のようなコードが必要になります。
// ヘッダーの読み込み
#include <commctrl.h>
// ライブラリーへのリンク
#pragma comment(lib, "ComCtl32.lib")
// コモンコントロールの初期化
InitCommonControls();
しかし、Msys2のMinGWのGNUコンパイラを使う場合は、ヘッダーの読み込みだけでOKです。
#include <windows.h>
#include <commctrl.h>
#include <stdio.h> // for snprintf
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("TrackBar");
RegisterClass (&wc);
hwnd = CreateWindow (TEXT("TrackBar"),
TEXT("TrackBar 50"),
WS_OVERLAPPEDWINDOW,
(GetSystemMetrics(SM_CXSCREEN) - 400) / 2,
(GetSystemMetrics(SM_CYSCREEN) - 250) / 2,
400,
250,
NULL,
NULL,
hInstance,
NULL);
ShowWindow (hwnd, nCmdShow);
UpdateWindow (hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND trackbar;
RECT clientRect;
static HFONT font;
int Pos;
char str[16];
switch(msg)
{
case WM_CREATE:
/* コモンコントロールの初期化 */
//InitCommonControls(); // なぜかいらない、逆に記述するとエラーになる
GetClientRect(hwnd, &clientRect);
trackbar =
CreateWindow (TEXT("msctls_trackbar32"), // TRACKBAR_CLASSでもOK
TEXT(""), WS_VISIBLE | WS_CHILD | TBS_AUTOTICKS,
//TBS_TOOLTIPS これも記述するとトラックバーのつまみの位置に現在の値が表示される
(clientRect.right - 360) / 2,
(clientRect.bottom - 20) / 2,
360, 20,
hwnd, (HMENU) 100, NULL, NULL);
SendMessage(trackbar, TBM_SETRANGE, TRUE, MAKELPARAM(0, 100));
SendMessage(trackbar, TBM_SETTICFREQ, 10, 0);
SendMessage(trackbar, TBM_SETPOS, TRUE, 50);
SendMessage(trackbar, TBM_SETPAGESIZE, 0, 10);
break;
case WM_SIZE:
GetClientRect(hwnd, &clientRect);
SetWindowPos(trackbar, HWND_TOP,
20, (clientRect.bottom - 20) / 2,
(clientRect.right - 40), 20,
SWP_NOZORDER); // SWP_SHOWWINDOWでも良い
break;
case WM_HSCROLL:
Pos = SendMessage(trackbar, TBM_GETPOS, 0, 0);
snprintf(str, -1, "TrackBar %d", Pos);
SetWindowText(hwnd, TEXT(str));
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
このサイトでは、Windowsアプリケーションを作成するためのIDE(統合開発環境)として、Code Blocksを紹介しています。Code Blocksでは前述の button.c、checkbox.c、trackbar.c のソースコードをそのまま使えます。
Code Blocksのダウンロードとインストール方法と設定方法は、 Environment / Windows で 詳しく説明しています。
上記コーナーを参考にして、Code Blocksで wxWidgets アプリケーションか GTK アプリケーションを作成できるようにしてください。その上で、Code Blocks で Windows API のアプリケーションを作成する方法を説明していきます。
Code Blocksを起動して「設定」メニューから「コンパイラ」を選びます。
「グローバルなコンパイラ設定」画面が開きましたら、「コンパイラを選択」で、ご自身で作られた「WX」か「GTK」を選択して、「コピー」をクリックします。
表示される「コンパイラを追加」ダイアログで、WINAPI などと名前をつけて「OK」をクリックします。
「リンカ設定」タブを選んで、「クリア」ボタンをクリックしてすべての設定を削除します。
「ディレクトリの検索」タブを選んで、「クリア」ボタンをクリックしてすべての設定を削除します。そして「OK」ボタンをクリックして、「グローバルなコンパイラ設定」画面を閉じます。
コンパイラの設定は以上です。
「ファイル」メニューから「新規」→「プロジェクト...」を選びます。
表示される「テンプレートから新規作成」画面で「Win32 GUI project」を選択して「Go」ボタンをクリックします。
次の画面では何もせずに「Next>」をクリックします。
次の画面では「Frame based」を選択して「Next>」をクリックします。
次の画面では「プロジェクトのタイトル」と「プロジェクトを作成するフォルダ」を決め「Nexe>」をクリックします。なおこの「プロジェクトのタイトル」がアプリケーションの名前になります。
次の画面の「コンパイラ」で、先ほど作った WINAPI を選び、「"Release"設定を作成」のみにチェックを入れます。そして「Finish」をクリックします。
Code Blocksのメイン画面に戻りますので、左ペインで「プロジェクト」タブを選び、プロジェクトの「Sources」の「main.cpp」を右クリックして「ファイルをプロジェクトから削除する」を選んで、main.cppを削除します。
次に「ファイル」メニューから「新規」→「空のファイル」を選びます。
「プロジェクトにファイルを追加」ダイアログが表示されますので、「はい」をクリックしてください。
次の画面で「ファイル名」に任意のファイル名を入力します。拡張子は .c にしてください。
Code Blocksのメイン画面に戻りますので、左ペインで「プロジェクト」タブを選びます。プロジェクトの「Sources」グループの中に、先ほど作成したファイルが出来ていますので、ダブルクリックします。
右ペインが編集画面になりますので、前述の button.c や checkbox.c や trackbar.c などのソースコードを記述してください。
ソースコードの記述が終わりましたら「ファイル」メニューから「すべてを保存」を選びます。
「ビルド」メニューから「ビルドして実行」を選びます。しばらくすると作成したアプリケーションが起動します。
また、プロジェクトフォルダの中の「bin」フォルダの中の「Release」フォルダの中に、.exe 実行ファイルが出来ていますので、それをダブルクリックしても実行できます。
Windows アプリケーションを作るなら、やっぱりMicrosoft社製のVisual Studioについて説明しないわけにはいかないだろうとのことで Visual Studio をいろいろ試してみました。
まず次のサイトからVisual Studio Express版をダウンロードします。
以前の Visual Studio ソフトウェアのダウンロード | Visual Studio - Visual Studio
私の環境では、Windows 7でVisual Studio 2010 Express、Windows 8.1とWindows 10ではVisual Studio 2012 Expressしか正しくインストールできませんでした。
Visual StudioにはVB(Visual Basic)版も存在しますので、Infoをよく読んでVC版であることを確認してダウンロードしてください。
なお、Visual Studio Expressは、Visual Studioの無料評価版です。
プログラミングの学習や、趣味としてアプリケーションを作ることは無料のExpress版でできます。しかし、作ったアプリケーションを配布したり販売する場合は、Visual Studioの有料正規版を購入しなければなりません。
Visual Studioを起動して、「新しいプロジェクト...」→「インストール済み」→「テンプレート」→「Visual C++」→「Win32」と進んで、「Win32 プロジェクト」を選び、「名前(N):」を決めて「OK」をクリックします。
Vsual Studio 2010では、「新しいプロジェクト...」→「インストールされたテンプレート」→「Visual C++」→「Win32」と進み、「Win32 プロジェクト」を選び、「名前(N):」を入力して「OK」をクリックしてください。
次の画面では「完了」を押さず「次へ>」をクリックします。
次の画面では、「空のプロジェクト」にチェックを入れて「完了」をクリックします。
次の画面の右ペインの「ソリューションエクスプローラ」で、作成したプロジェクトを右クリックして、「追加」→「新しい項目」を選びます。
なお、Visual Studio 2010では「ソリューションエクスプローラ」ペインは左側にあります。
次の画面では「C++ファイル(.cpp)」を選び、名前を trackbar.c などとします。この名前は任意で決められてます。拡張子は .c で大丈夫です。そして「追加」をクリックします。
上記の手順でプロジェクトを作成した場合、Visual Studioの画面は、ソースコードの編集画面になっていると思います。その編集画面に次のソースコードを記述してください。
#include <windows.h>
#include <commctrl.h>
#include <stdio.h> // for sprintf
#pragma comment(lib, "ComCtl32.lib")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("TrackBar");
RegisterClass (&wc);
hwnd = CreateWindow (TEXT("TrackBar"),
TEXT("TrackBar 50"),
WS_OVERLAPPEDWINDOW,
(GetSystemMetrics(SM_CXSCREEN) - 400) / 2,
(GetSystemMetrics(SM_CYSCREEN) - 250) / 2,
400,
250,
NULL,
NULL,
hInstance,
NULL);
ShowWindow (hwnd, nCmdShow);
UpdateWindow (hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND trackbar;
RECT clientRect;
static HFONT font;
int Pos;
char str[128] = "";
switch(msg)
{
case WM_CREATE:
InitCommonControls(); // コモンコントロールの初期化
GetClientRect(hwnd, &clientRect);
trackbar =
CreateWindow (TEXT("msctls_trackbar32"), // TRACKBAR_CLASSでもOK
TEXT(""), WS_VISIBLE | WS_CHILD | TBS_AUTOTICKS,
//TBS_TOOLTIPS これも記述するとトラックバーのつまみの位置に現在の値が表示される
(clientRect.right - 360) / 2,
(clientRect.bottom - 20) / 2,
360, 20,
hwnd, (HMENU) 100, NULL, NULL);
SendMessage(trackbar, TBM_SETRANGE, TRUE, MAKELPARAM(0, 100));
SendMessage(trackbar, TBM_SETTICFREQ, 10, 0);
SendMessage(trackbar, TBM_SETPOS, TRUE, 50);
SendMessage(trackbar, TBM_SETPAGESIZE, 0, 10);
break;
case WM_SIZE:
GetClientRect(hwnd, &clientRect);
SetWindowPos(trackbar, HWND_TOP,
20, (clientRect.bottom - 20) / 2,
(clientRect.right - 40), 20,
SWP_NOZORDER); // SWP_SHOWWINDOWでも良い
break;
case WM_HSCROLL:
Pos = SendMessage(trackbar, TBM_GETPOS, 0, 0);
sprintf(str, "TrackBar %d", Pos);
SetWindowText(hwnd, str);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
ソースコードの記述が終わりましたら、「ファイル」メニューから「[あなたが決めた任意の名前].cの保存」か「すべてを保存」を選びます。
「ビルド」メニューから「ソリューションのビルド」を選びます。そして左下の「出力」ペインに次のように表示されたらビルドは成功しています。
========== ビルド: 1 正常終了、0 失敗、0 更新不要、0 スキップ ==========
ビルドしたアプリケーションを実行するには、「デバッグ」メニューで「デバッグなしで開始」を選びます。また、Windowsの「Documents」→「Visual Stduio 2012(もしくは2010)」→「Projects」→「[プロジェクト名]」→「Debug(もしくはRelease)」に「[プロジェクト名].exe」という実行ファイルが作成されていますので、ダブルクリックで起動することができます。
もしアプリケーションの表示で文字化けが起こる場合は、ソリューションエクスプローラでプロジェクトを右クリックして「プロパティ」→「構成プロパティ」→「全般」→「文字セット」→「マルチバイト文字セットを使用する」を選び、再度ビルドしてください。
Visual Studio 2010の場合は、次の図のように緑色の右三角の右横を「Release」変えて、緑色の右三角をクリックします。
「ビルドしますか?」というダイアログが表示されますので、「はい」をクリックします。
しばらくするとアプリケーションがビルドされて実行されます。
また、Windowsの「Documents」→「Visual Studio 2010」→「[プロジェクト名]」→「Release」に「[プロジェクト名].exe」という実行ファイルが出来上がっていますので、それをダブルクリックして実行することもできます。もしアプリケーションの表示で文字化けが起こる場合は、ソリューションエクスプローラでプロジェクトを右クリックして「プロパティ」→「構成プロパティ」→「全般」→「文字セット」→「マルチバイト文字セットを使用する」を選び、再度ビルドしてください。
ラジオボタンは複数の項目の中から、一つだけを選択するに使われます。
#include <windows.h>
#define ID_BLUE 1
#define ID_YELLOW 2
#define ID_ORANGE 3
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hinst;
COLORREF g_color;
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLite,
int nCmdShow)
{
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("RadioButton");
g_hinst = hInstance;
RegisterClass(&wc);
hwnd = CreateWindow (TEXT("RadioButton"),
TEXT("Radio Button"),
WS_OVERLAPPEDWINDOW,
(GetSystemMetrics(SM_CXSCREEN) - 400) / 2,
(GetSystemMetrics(SM_CYSCREEN) - 250) / 2,
400,
250,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
RECT clientRect;
static HFONT font;
static HWND box, blue, yellow, orange;
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush, holdBrush;
HPEN hPen, holdPen;
switch(msg)
{
case WM_CREATE:
GetClientRect(hwnd, &clientRect);
font = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
box = CreateWindow(TEXT("Button"), TEXT("Choose color"),
WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
10, 10, 120, (clientRect.bottom - 20), hwnd, (HMENU) 0, g_hinst, NULL);
blue = CreateWindow(TEXT("Button"), TEXT("Blue"),
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
20, 30, 100, 30, hwnd, (HMENU) ID_BLUE, g_hinst, NULL);
yellow = CreateWindow(TEXT("Button"), TEXT("Yellow"),
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
20, 55, 100, 30, hwnd, (HMENU) ID_YELLOW, g_hinst, NULL);
orange = CreateWindow(TEXT("Button"), TEXT("Orange"),
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
20, 80, 100, 30, hwnd, (HMENU) ID_ORANGE, g_hinst, NULL);
SendMessage(box, WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
SendMessage(blue, WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
SendMessage(yellow, WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
SendMessage(orange, WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
break;
case WM_SIZE:
GetClientRect(hwnd, &clientRect);
SetWindowPos(box, HWND_TOP,
0, 0, 120, (clientRect.bottom - 20), SWP_NOMOVE);
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
case ID_BLUE:
g_color = RGB(0, 76, 255);
break;
case ID_YELLOW:
g_color = RGB(255, 255, 0);
break;
case ID_ORANGE:
g_color = RGB(255, 123, 0);
break;
}
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case WM_PAINT:
GetClientRect(hwnd, &clientRect);
hdc = BeginPaint(hwnd, &ps);
hBrush = CreateSolidBrush(g_color);
hPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0));
holdPen = SelectObject(hdc, hPen);
holdBrush = (HBRUSH) SelectObject(hdc, hBrush);
Rectangle(hdc, 140, 15, (clientRect.right - 10),
(clientRect.bottom - 10));
SelectObject(hdc, holdBrush);
SelectObject(hdc, holdPen);
DeleteObject(hPen);
DeleteObject(hBrush);
EndPaint(hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
トグルボタンは、押された状態と、押されていない状態があるボタンです。
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hinst;
COLORREF g_color;
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("ToggleButton");
g_hinst = hInstance;
RegisterClass(&wc);
hwnd = CreateWindow (TEXT("ToggleButton"),
TEXT("ToggleButton"),
WS_OVERLAPPEDWINDOW,
(GetSystemMetrics(SM_CXSCREEN) - 400) / 2,
(GetSystemMetrics(SM_CYSCREEN) - 250) / 2,
400,
250,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND red, green, blue;
static HFONT font;
static UCHAR r = 0;
static UCHAR g = 0;
static UCHAR b = 0;
UCHAR toggled = 1;
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush, holdBrush;
HPEN hPen, holdPen;
#define RED 1
#define GREEN 2
#define BLUE 3
switch (msg)
{
case WM_CREATE:
font = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
red = CreateWindow(TEXT("Button"),
TEXT("Red"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_PUSHLIKE,
20, 20,
100, 30,
hwnd,
(HMENU) RED,
NULL,
NULL);
green = CreateWindow(TEXT("Button"),
TEXT("Green"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_PUSHLIKE,
20, 70,
100, 30,
hwnd,
(HMENU) GREEN,
NULL,
NULL);
blue = CreateWindow(TEXT("Button"),
TEXT("Blue"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_PUSHLIKE,
20, 120,
100, 30,
hwnd,
(HMENU) BLUE,
NULL,
NULL);
CheckDlgButton(hwnd, RED, BST_UNCHECKED);
CheckDlgButton(hwnd, GREEN, BST_UNCHECKED);
CheckDlgButton(hwnd, BLUE, BST_UNCHECKED);
SendMessage(red, WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
SendMessage(green, WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
SendMessage(blue , WM_SETFONT, (WPARAM)font, MAKELPARAM(FALSE, 0));
break;
case WM_COMMAND:
if (LOWORD(wParam) == RED)
{
toggled = IsDlgButtonChecked(hwnd, RED);
if (toggled)
{
CheckDlgButton(hwnd, RED, BST_UNCHECKED);
r = 0;
} else {
CheckDlgButton(hwnd, RED, BST_CHECKED);
r = 255;
}
}
if (LOWORD(wParam) == GREEN)
{
toggled = IsDlgButtonChecked(hwnd, GREEN);
if (toggled)
{
CheckDlgButton(hwnd, GREEN, BST_UNCHECKED);
g = 0;
} else {
CheckDlgButton(hwnd, GREEN, BST_CHECKED);
g = 255;
}
}
if (LOWORD(wParam) == BLUE)
{
toggled = IsDlgButtonChecked(hwnd, BLUE);
if (toggled)
{
CheckDlgButton(hwnd, BLUE, BST_UNCHECKED);
b = 0;
} else {
CheckDlgButton(hwnd, BLUE, BST_CHECKED);
b = 255;
}
}
g_color = RGB(r, g, b);
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
hBrush = CreateSolidBrush(g_color);
hPen = CreatePen(PS_NULL, 1, RGB(r, g, b));
holdPen = SelectObject(hdc, hPen);
holdBrush = (HBRUSH) SelectObject(hdc, hBrush);
Rectangle(hdc, 140, 20, 365, 190);
SelectObject(hdc, holdBrush);
SelectObject(hdc, holdPen);
DeleteObject(hPen);
DeleteObject(hBrush);
EndPaint(hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
red = CreateWindow(TEXT("Button"),
TEXT("Red"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_PUSHLIKE,
・・・
if (LOWORD(wParam) == RED)
{
toggled = IsDlgButtonChecked(hwnd, RED);
if (toggled)
{
CheckDlgButton(hwnd, RED, BST_UNCHECKED);
r = 0;
} else {
CheckDlgButton(hwnd, RED, BST_CHECKED);
r = 255;
}
}