Windows API Primer   ボタン

ホーム   目次

コントロール

ウィンドウ内に表示するボタンや文字列などといった GUI 部品のことを、Windows API ではコントロールと言います。コントロールもウィンドウです。コントロールのウィンドウクラスは、あらかじめシステム(Windows OS)に登録されています。

ボタン

GUI 部品と言えば、まずボタンが浮かびます。ボタンは、CreateWindow関数の第1引数に BUTTON というウィンドウクラス名を指定して作成します。BUTTON ウィンドウクラスは、あらかじめシステム(Windows OS)に登録されています。

button.c


#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         = NULL;
  wc.hCursor       = NULL;
  wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND + 1;
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = TEXT("WINDOW");

  RegisterClass(&wc);

  hwnd             = CreateWindow(TEXT("WINDOW"),
				  TEXT("Windows API Primer"),
				  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
				  CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
				  NULL, NULL, hInstance, NULL);

  while (GetMessage(&msg, NULL, 0, 0))
    {
      DispatchMessage(&msg);
    }
  
  return   msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  static HWND  button;
         RECT  rect;
	 HFONT font;
	 
  switch (msg)
    {
    case WM_CREATE:
      GetClientRect(hwnd, &rect);
      font   = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
      button = CreateWindow(TEXT("BUTTON"),
			    TEXT("Button"),
			    WS_CHILD | WS_VISIBLE,
			    (rect.right  - 70) / 2,
			    (rect.bottom - 25) / 2,
			    70, 25, hwnd, NULL, NULL, NULL);
      SendMessage(button, WM_SETFONT, (WPARAM)font, 0);
      break;
    case WM_SIZE:
      GetClientRect(hwnd, &rect);
      SetWindowPos (button, HWND_TOP,
		    (rect.right  - 70) / 2,
		    (rect.bottom - 25) / 2,
		    0, 0, SWP_NOSIZE);
      break;
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}
    


実行結果


ウィンドウのサイズを変更しても、ボタンに常に中央に表示されます。


コード説明

  1. button = CreateWindow(TEXT("BUTTON"),
    CreateWindow関数の第1引数に BUTTON というウィンドウクラス名を指定すると、ボタンコントロールが作成されます。BUTTON ウィンドウクラスは、あらかじめシステム(Windows OS)に登録されています。

ボタンに役割を持たせる

前述の button.c はボタンをクリックしても何も起こりません。次の greeting.c ではボタンをクリックすると挨拶をするようにします。

greeting.c


#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         = NULL;
  wc.hCursor       = NULL;
  wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND + 1;
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = TEXT("WINDOW");

  RegisterClass(&wc);

  hwnd             = CreateWindow(TEXT("WINDOW"),
				  TEXT("Windows API Primer"),
				  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
				  CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
				  NULL, NULL, hInstance, NULL);

  while (GetMessage(&msg, NULL, 0, 0))
    {
      DispatchMessage(&msg);
    }
  
  return   msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  static HWND  button, label;
         RECT  rect;
	 HFONT font;
  static BOOL  isHello = FALSE;
	 
  switch (msg)
    {
    case WM_CREATE:
      GetClientRect(hwnd, &rect);
      font   = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
      button = CreateWindow(TEXT("BUTTON"),
			    TEXT("Greeting"),
			    WS_CHILD | WS_VISIBLE,
			    rect.right  - 80,
			    rect.bottom - 35,
			    70, 25, hwnd, (HMENU)44, NULL, NULL);
      SendMessage(button, WM_SETFONT, (WPARAM)font, 0);
      label  = CreateWindow(TEXT("STATIC"),
			    TEXT("♪( ´▽`)"),
			    WS_CHILD | WS_VISIBLE | SS_CENTER,
			    (rect.right  - 50) / 2,
			    (rect.bottom - 15) / 2,
			    50, 15, hwnd, NULL, NULL, NULL);
      SendMessage(label, WM_SETFONT, (WPARAM)font, 0);
      break;
    case WM_SIZE:
      GetClientRect(hwnd, &rect);
      SetWindowPos (button, HWND_TOP,
		    rect.right  - 80,
		    rect.bottom - 35,
		    0, 0, SWP_NOSIZE);
      SetWindowPos (label,  HWND_TOP,
		    (rect.right  - 50) / 2,
		    (rect.bottom - 15) / 2,
		    0, 0, SWP_NOSIZE);
      break;
    case WM_COMMAND:
      if (LOWORD(wParam) == 44)
	{
	  if (isHello)
	    {
	      SendMessage(label, WM_SETTEXT, 0, (LPARAM)TEXT("Goodbye"));
	      isHello = FALSE;
	    }
	  else
	    {
	      SendMessage(label, WM_SETTEXT, 0, (LPARAM)TEXT("Hello"));
	      isHello = TRUE;
	    }
	}
      break;
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}
    


実行結果


Greeting ボタンをクリックするたびに、Hello と Goodbye という挨拶を繰り返します。ウィンドウのサイズを変更してもボタンは右下に、文字列は中央に表示されます。


コード説明

  1. static BOOL isHello = FALSE;
    Windows API では、typedef によって BOOL という型と、define によって TRUE、FALSE という定数が定義されています。

  2. 70, 25, hwnd, (HMENU)44, NULL, NULL);
    GUI 部品に何かの役割を持たせる場合には、CreateWindow関数の第9引数にHMENU型の整数値を指定します。この整数値が、そのコントロールを表す ID になります。

  3. case WM_COMMAND:
    ユーザーによってコントロールに何かの操作がされた場合は、WM_COMMND メッセージが送られます。

  4. if (LOWORD(wParam) == 44)
    メッセージを送った GUI 部品を、CreateWindow関数の第9引数に指定した整数値で確認します。整数値は、WPARAME引数の下位16bitに格納されています。下位16bitを取り出すにはLOWORDマクロを使います。

  5. SendMessage(label, WM_SETTEXT, 0, (LPARAM)TEXT("Goodbye"));
    SendMessage関数で label にメッセージを送ります。引数は次のとおりです。
    1. 第1引数には、メッセージを送るウィンドウ(GUI 部品)を指定します。
    2. 第2引数には、メッセージの種類を指定します。WM_SETTEXT 定数は、文字列を設定するメッセージであることを表しています。
    3. 第3引数には、WPARAM 型のデータを指定します。ここでは第3引数を使わないので 0 を指定しています。
    4. 第4引数には、文字列を指定して、LPARAM型にキャストしています。


4938 visits
Posted: Jun. 02, 2020
Update: Jun. 03, 2020

ホーム   目次