Home  Contents

Windows controls I

Controls are basic building blocks of a windows application. Controls are called widgets in UNIX environment.

Static control

The static control displays text and graphics. The static control cannot be selected. It cannot have keyboard focus.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow)
{
  MSG  msg;    
  WNDCLASSW wc = {0};
  wc.lpszClassName = L"Static Control";
  wc.hInstance     = hInstance;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor       = LoadCursor(0,IDC_ARROW);

  
  RegisterClassW(&wc);
  CreateWindowW(wc.lpszClassName, L"Criminal",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                100, 100, 330, 270, 0, 0, hInstance, 0);

  while( GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam)
{
  static wchar_t *lyrics =  L"I know you told me I should stay away\n\
I know you said he's just a dog astray\n\
He is a bad boy with a tainted heart\n\
And even I know this ain't smart\n\
\n\
But mama, I'm in love with a criminal\n\
And this type of love isn't rational, it's physical\n\
Mama, please don't cry, I will be alright\n\
All reason aside, I just can't deny, love the guy\n\
";

  switch(msg)  
  {
      case WM_CREATE:
      
        CreateWindowW(L"STATIC", lyrics, 
            WS_CHILD | WS_VISIBLE | SS_LEFT,
            20, 20, 300, 230,
            hwnd, (HMENU) 1, NULL, NULL);
        break;

      case WM_DESTROY:

        PostQuitMessage(0);
        break;
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}

We show lyrics of a song on a window.

CreateWindowW(L"STATIC", lyrics, 
    WS_CHILD | WS_VISIBLE | SS_LEFT,
    20, 20, 300, 230,
    hwnd, (HMENU) 1, NULL, NULL);
break;

Here we create the static control. We display text. It is aligned to the left.

Static control
Static control

Button

A button is a simple control. It has a text label. It is used to trigger an action. When we click on a button, it sends a WM_COMMAND message to its parent window. The low-order word of the wParam parameter contains the control identifier.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow)
{
  MSG  msg;
  WNDCLASSW wc = {0};
  wc.lpszClassName = L"Buttons";
  wc.hInstance     = hInstance;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor       = LoadCursor(0, IDC_ARROW);

  RegisterClassW(&wc);
  CreateWindowW(wc.lpszClassName, L"Buttons",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                150, 150, 230, 150, 0, 0, hInstance, 0);

  while( GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam)
{    
  switch(msg)  
  {
    case WM_CREATE:

      CreateWindowW(L"button", L"Beep",
          WS_VISIBLE | WS_CHILD ,
          20, 50, 80, 25,
          hwnd, (HMENU) 1, NULL, NULL);

      CreateWindowW(L"button", L"Quit",
          WS_VISIBLE | WS_CHILD ,
          120, 50, 80, 25,
          hwnd, (HMENU) 2, NULL, NULL);
      break;

    case WM_COMMAND:

      if (LOWORD(wParam) == 1) {
        Beep(40, 50);
      }

      if (LOWORD(wParam) == 2) {
        PostQuitMessage(0);
      }

      break;

    case WM_DESTROY:

      PostQuitMessage(0);
      break;
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}

In our example we have created two buttons. On button will beep. The other one will close the window.

case WM_COMMAND:

  if (LOWORD(wParam) == 1) {
    Beep(40, 50);
  }

  if (LOWORD(wParam) == 2) {
    PostQuitMessage(0);
  }

  break;

The control id is in the LOWORD of the wParam. Depending on the control id, we call the Beep() function or the PostQuitMessage() function.

Button controls
Button controls

Check box

A check box control is a box that you can click to turn an option on or off.

#include <windows.h>
#include <stdbool.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow)
{
  MSG  msg;    
  WNDCLASSW wc = {0};
  wc.lpszClassName = L"Check Box";
  wc.hInstance     = hInstance ;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor       = LoadCursor(0, IDC_ARROW);

  RegisterClassW(&wc);
  CreateWindowW(wc.lpszClassName, L"Check Box",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                150, 150, 230, 150, 0, 0, hInstance, 0);

  while( GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam)
{
  bool checked = true;

  switch(msg)  
  {
    case WM_CREATE:

      CreateWindowW(L"button", L"Show Title",
          WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
          20, 20, 185, 35, hwnd, (HMENU) 1, 
          NULL, NULL);

      CheckDlgButton(hwnd, 1, BST_CHECKED);
      break;

    case WM_COMMAND:

      checked = IsDlgButtonChecked(hwnd, 1);

      if (checked) {

        CheckDlgButton(hwnd, 1, BST_UNCHECKED);
        SetWindowTextW(hwnd, L"");

      } else {

        CheckDlgButton(hwnd, 1, BST_CHECKED);
        SetWindowTextW(hwnd, L"Check Box");
      }
      break;

    case WM_DESTROY:

      PostQuitMessage(0);
      break;
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}	

In our example, we show or hide the window title depending on the state of the check box. In Windows, check box is a special kind of a button. We create a check box, if we set a specific style to the button class. In our example, it is BS_CHECKBOX.

checked = IsDlgButtonChecked(hwnd, 1);

We determine the state of the check box using the IsDlgButtonChecked() function.

CheckDlgButton(hwnd, 1, BST_UNCHECKED);

We check and uncheck the check box using the CheckDlgButton() function.

SetWindowTextW(hwnd, L"");

The SetWindowTextW() function sets the title of the window.

Checkbox control
Checkbox control

Edit Control

Edit control is a rectangular child window. Edit control is used to enter and edit text. It can be single line or multiline.

#include <windows.h>

#define ID_EDIT 1
#define ID_BUTTON 2

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow )
{
  MSG  msg;    
  WNDCLASSW wc = {0};
  wc.lpszClassName = L"Edit Control";
  wc.hInstance     = hInstance;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor       = LoadCursor(0,IDC_ARROW);

  RegisterClassW(&wc);
  CreateWindowW(wc.lpszClassName, L"Edit control",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                220, 220, 280, 200, 0, 0, hInstance, 0);  

  while(GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam)
{
  static HWND hwndEdit;
  HWND hwndButton;

  switch(msg)
  {
    case WM_CREATE:

      hwndEdit = CreateWindowW(L"Edit", NULL, 
        WS_CHILD | WS_VISIBLE | WS_BORDER,
        50, 50, 150, 20, hwnd, (HMENU) ID_EDIT,
        NULL, NULL);

      hwndButton = CreateWindowW(L"button", L"Set Title",
        WS_VISIBLE | WS_CHILD, 50, 100, 80, 25,
        hwnd, (HMENU) ID_BUTTON, NULL, NULL);

      break;

    case WM_COMMAND:	

      if (HIWORD(wParam) == BN_CLICKED) {

         int len = GetWindowTextLengthW(hwndEdit) + 1;
         wchar_t text[len];

         GetWindowTextW(hwndEdit, text, len);
         SetWindowTextW(hwnd, text);
      }
      break;

      case WM_DESTROY:
        PostQuitMessage(0);
      break;
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}

In our example, we have an edit control and a button. We can put some text into the edit control. If we click on the button, the entered text will be displayed in the titlebar of the main window.

if (HIWORD(wParam) == BN_CLICKED) {

   int len = GetWindowTextLengthW(hwndEdit) + 1;
   wchar_t text[len];

   GetWindowTextW(hwndEdit, text, len);
   SetWindowTextW(hwnd, text);
}

The GetWindowTextLengthW() returns the text length entered. Notice, that we add 1 to the length. This is to include the zero terminator. Try to omit it and see what happens. The GetWindowTextW() receives the text from the edit control. We use hwndEdit as an id. The SetWindowTextW() sets the text for the window. In this context, it is a title of the main window.

Edit control
Figure: Edit control

In this part of the Winapi tutorial, we have covered Windows controls.