Win32 API Menus and Controls

control

Control concept

Control: a special kind of "child" window, the system has defined the window type
Create like create window, call CreateWindow, each control has its own ID
When a control event occurs, a notification message is sent to the parent window where it is located
SendMessage and PostMessage can be used to send messages to controls
Note: Two properties must be added when creating the window

  • WS_CHILD: Controls are placed on our windows and naturally act as subwindows of windows, WS_ The same is true for CHILDWINDOW
  • WS_VISIBLE: Set visible

Create Control Functions

HWND WINAPI CreateWindow( Class name, show contents,  style,  int x,   int y,   
               int nWidth,  int nHeight,  parent window,  control ID,  
               HINSTANCE hInstance,  LPVOID lpParam  );

Button

Window Class Name BUTTON

Button Category:

  • Push button BS_PUSHIBUTTON / BS_DEFPUSHIBUTTON
  • Checkbox BS_ CHECKBOX (you need to maintain your selection status when you click on a selection)/ BS_AUTOCHECKBOX (system maintains selection status automatically when clicking on selection)/ BS_3STATE (three states of graying)/ BS_AUTO3STATE (three states of automatic processing)
  • Radio Box BS_RADIOBUTTON / BS_AUTORADIOBUTTON
  • Groupbox BS_GROUPBOX

Button message: WM_COMMAND

  • LOWORD(wParam) saves the button ID
  • HIWORD(wparam) Notification Code BN_CLICKED
  • lParam Subwindow Handle

    Set button text
  • WM_SETTEXT
  • SetWindowText

Demo

// ButtonDemo.cpp: Defines the entry point for the application.
//

#include "framework.h"
#include "ButtonDemo.h"

#define MAX_LOADSTRING 100

#define DN_ID_PUSH_BUTTON					WM_USER + 1
#define DN_ID_DEF_PUSH_BUTTON				DN_ID_PUSH_BUTTON + 1
#define DN_ID_CHECK_BOX						DN_ID_DEF_PUSH_BUTTON + 1
#define DN_ID_AUTO_CHECK_BOX				DN_ID_CHECK_BOX + 1
#define DN_ID_3_STATE						DN_ID_AUTO_CHECK_BOX + 1
#define DN_ID_AUTO_3_STATE					DN_ID_3_STATE + 1
#define DN_ID_RADIO_BUTTON					DN_ID_AUTO_3_STATE + 1
#define DN_ID_AUTO_RADIO_BUTTON				DN_ID_RADIO_BUTTON + 1
#define DN_ID_GROUP_BOX						DN_ID_AUTO_RADIO_BUTTON + 1

// Global variables:
HINSTANCE hInst;                                // Current instance
WCHAR szTitle[MAX_LOADSTRING];                  // Title bar text
WCHAR szWindowClass[MAX_LOADSTRING];            // Main window class name
HWND g_hPushButton;
HWND g_hDefPushButton;
HWND g_hCheckBox;
HWND g_hAutoCheckBox;
HWND g_h3State;
HWND g_hAuto3State;
HWND g_hRadioButton;
HWND g_hAutoRadioButton;
HWND g_hGroupBox;


// Forward declarations of functions contained in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
void				CreateButton(HWND hwnd, HINSTANCE hInstance);


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place your code here.

    // Initialize global string
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_BUTTONDEMO, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_BUTTONDEMO));

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  Function: MyRegisterClass()
//
//  Target: Register window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BUTTONDEMO));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_BUTTONDEMO);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   Function: InitInstance(HINSTANCE, int)
//
//   Target: Save instance handle and create main window
//
//   Notes:
//
//        In this function, we save the instance handle in the global variable and
//        Create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handles in global variables

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   CreateButton(hWnd, hInstance);

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

void CreateButton(HWND hwnd, HINSTANCE hInstance)
{
	//Grouping box
	g_hGroupBox = CreateWindow(_T("BUTTON"), _T("GroupBox"), WS_VISIBLE | WS_CHILD | BS_GROUPBOX,
		20, 20, 200, 500, hwnd, (HMENU)(DN_ID_GROUP_BOX), hInstance, NULL);

	g_hPushButton = CreateWindow(L"BUTTON", L"PushButotn", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
		50, 50, 80, 30, hwnd, (HMENU)(DN_ID_PUSH_BUTTON), hInstance, NULL);

	g_hDefPushButton = CreateWindow(_T("BUTTON"), _T("DefPushButotn"), WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
		50, 100, 150, 30, hwnd, (HMENU)(DN_ID_DEF_PUSH_BUTTON), hInstance, NULL);

	g_hCheckBox = CreateWindow(_T("BUTTON"), _T("CheckBox"), WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
		50, 150, 150, 30, hwnd, (HMENU)(DN_ID_CHECK_BOX), hInstance, NULL);

	g_hAutoCheckBox = CreateWindow(_T("BUTTON"), _T("AutoCheckBox"), WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX,
		50, 200, 150, 30, hwnd, (HMENU)(DN_ID_AUTO_CHECK_BOX), hInstance, NULL);

	g_h3State = CreateWindow(_T("BUTTON"), _T("3State"), WS_VISIBLE | WS_CHILD | BS_3STATE,
		50, 250, 150, 30, hwnd, (HMENU)(DN_ID_3_STATE), hInstance, NULL);

	g_hAuto3State = CreateWindow(_T("BUTTON"), _T("Auto3State"), WS_VISIBLE | WS_CHILD | BS_AUTO3STATE,
		50, 300, 150, 30, hwnd, (HMENU)(DN_ID_AUTO_3_STATE), hInstance, NULL);
	//Radio
	g_hRadioButton = CreateWindow(_T("BUTTON"), _T("RadioButton"), WS_VISIBLE | WS_CHILD | BS_RADIOBUTTON,
		50, 350, 150, 30, hwnd, (HMENU)(DN_ID_RADIO_BUTTON), hInstance, NULL);
	//Radio box auto-change state
	g_hAutoRadioButton = CreateWindow(_T("BUTTON"), _T("AutoRadioButton"), WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
		50, 400, 150, 30, hwnd, (HMENU)(DN_ID_AUTO_RADIO_BUTTON), hInstance, NULL);

}


//
//  Function: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  Target: Processes messages from the main window.
//
//  WM_COMMAND - Processing Application Menu
//  WM_PAINT - Draw main window
//  WM_DESTROY - Send exit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Analysis menu selection:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
			case DN_ID_PUSH_BUTTON:  //Handling of button single machine events
				SendMessage((HWND)lParam, WM_SETTEXT, NULL, (WPARAM)_T("I was clicked"));
				break;
			case DN_ID_DEF_PUSH_BUTTON://Handling of button single machine events
				SetWindowText((HWND)lParam, _T("I was clicked"));
				break;
			case DN_ID_RADIO_BUTTON:  //Radio
			{
				//Get the checked state of the radio box
				LRESULT nRet = SendMessage(g_hRadioButton, BM_GETCHECK, 0, 0);
				if (nRet == BST_CHECKED) //If selected
				{
					SendMessage(g_hRadioButton, BM_SETCHECK, BST_UNCHECKED, 0); //Set to Unselected
				}
				else if (nRet == BST_UNCHECKED) //If unchecked
				{
					SendMessage(g_hRadioButton, BM_SETCHECK, BST_CHECKED, 0); //Set to Selected State
				}
				else if (nRet == BST_INDETERMINATE)  //Is in ashing state
				{
				}
			}
				break;
			case DN_ID_CHECK_BOX:	//check box
			{
				HWND hCheckBox = GetDlgItem(hWnd, DN_ID_CHECK_BOX);  //By id or control handle
				LRESULT nRet = SendMessage(hCheckBox, BM_GETCHECK, 0, 0);
				if (nRet == BST_CHECKED) //If selected
				{
					SendMessage(hCheckBox, BM_SETCHECK, BST_UNCHECKED, 0); //Set to Unselected
				}
				else if (nRet == BST_UNCHECKED) //If unchecked
				{
					SendMessage(hCheckBox, BM_SETCHECK, BST_CHECKED, 0); //Set to Selected State
				}
				else if (nRet == BST_INDETERMINATE)  //Is in ashing state
				{
				}
			}
				break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: Add any drawing code using hdc here...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for About box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

Edit Box

Window Class Name EDIT

Classification:

  • Text edit box: single line / multiple lines
  • Password edit box: ES_PASSWORD, display password

Window Style

Notification message

In WM_ Processing this parameter under COMMAND case
if (HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == nEditID)

WM_GETTEXT - Get Edit Box Text
Size of wPararm-buffer lPararm-buffer's first address
SendMessage( (WPARAM) wParam, // number of characters to copy

WM_GETTEXTLENGTH - Get Text Length
SendMessage( (WPARAM) 0, (LPARAM) 0)

WM_SETTEXT settings
wParam - No use, lParam - Prepare the first address of the buffer for content
Supplement:
· SendMessage( hWndEdit, WM_CUT, 0, 0 );
· SendMessage( hWndEdit, WM_COPY, 0, 0 );
· SendMessage( hWndEdit, WM_CLEAR, 0, 0 )

Static box

The window name STATIC is used to display text and load pictures (set property SS_ICON/SS_BITMAP)

Window message: sendMessage is sent to a control such as STM_SETICON

combo box

Combo Box Classification
Simple Combo Box CBS_SIMPLE (optional for input)
Drop-down Combo Box CBS_DROPDOWN (can be entered, can be selected)
Drop-down List Combo Box CBS_DROPDOWNLIST (only optional but not input)

Combo Box Send Message
CB_ADDSTRING - Add Item (WPARAM - No LPARAM - String Pointer)
CB_INSERTSTRING Add Item
CB_DELETESTRING Delete Developer Item
CB_RESETCONTENT Clears All Items
CB_SETCURSEL Sets Current Item
CB_GETCURSLE Gets Current Item
CB_FINDSTRING Finds a String
CB_GETLBTEXTLEN Gets the selected character length
CB_ A character content for GETLBTEXT get option
CB_DIR Displays the file and directory names under the specified path in the combo box
CB_SETITENDATA Saves Data to Specified Options
CB_GETITEMDATA Gets Data from Specified Options

menu

Get menu handle
:: LoadMenu (program instance, resource handle);
The resource handle uses MAKEINTRESOURCE (menu ID);ID is defined in resource.h.
This function returns a menu handle

hwnd = CreateWindowEx ( 
       0,   
       szClassName,         
       "Code::Blocks Template Windows App", 
       WS_OVERLAPPEDWINDOW,  
       CW_USEDEFAULT,       
       CW_USEDEFAULT,       
       544,                  
       375,                  
       HWND_DESKTOP,        
       LoadMenu(hThisInstance,MAKEINTRESOURCE(IDR_MENU)), // MENU 
       hThisInstance,       /* Program Instance handler */ 
       NULL                 
       ); 

Register window class is to provide menu handles

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BUTTONDEMO));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName = NULL;//MAKEINTRESOURCEW(IDC_BUTTONDEMO); // Get menu handle
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

Manual Add

HMENU CreateMyMenu()
{
	HMENU hRoot = CreateMenu();
	HMENU pop1 = CreatePopupMenu();

	AppendMenu(hRoot, MF_POPUP, (UINT_PTR)pop1, L"file");
	// One way is to use the AppendMenu function  
	AppendMenu(pop1, MF_STRING, DN_ID_MENU_OPEN, L"open");

	// Another way is to use the InsertMenuItem function  
	MENUITEMINFO mif;
	mif.cbSize = sizeof(MENUITEMINFO);
	mif.cch = 100;
	mif.dwItemData = NULL;
	mif.dwTypeData = (TCHAR*)L"Preservation";
	mif.fMask = MIIM_ID | MIIM_STRING | MIIM_STATE;
	mif.fState = MFS_ENABLED;
	mif.fType = MIIM_STRING;
	mif.wID = DN_ID_MENU_SAVE;

	InsertMenuItem(pop1, DN_ID_MENU_SAVE, FALSE, &mif);

	return hRoot;
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handles in global variables

   HMENU hRoot = CreateMyMenu();
   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, hRoot, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   CreateButton(hWnd, hInstance);

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

Keywords: C++ Linux Windows

Added by dmcdivitt on Fri, 26 Nov 2021 19:23:59 +0200