当前位置: 首页 > article >正文

【第五节】windows sdk编程:windows 控件基础

目录

一、控件概述

二、标准控件

三、通用控件

四、控件的创建

五、控件风格

六、控件相关的消息

6.1 控件控制消息

6.2 控件通知消息


一、控件概述

        控件是 Windows 系统内置的窗口类,它们只能是某个窗口的子窗口。因此,创建控件时必须使用 `WS_CHILD` 风格。控件的窗口类由系统预先注册,因此我们不需要手动注册窗口类。控件的消息响应函数由 Windows 提供,而不是我们自己编写的。

        控件的行为由其内置的窗口回调函数处理。当控件发生某些行为时(如被点击或需要重绘),它会向其父窗口发送通知消息。

二、标准控件

        标准控件是 Windows 提供的基本控件,使用方式简单。以下是常用的标准控件:

三、通用控件

        通用控件是 Windows 提供的较为复杂的控件,例如树形控件、列表框控件、选项步控件等。以下是常见的通用控件:

四、控件的创建

        控件的创建使用 `CreateWindow` 函数,但不需要手动注册窗口类。通常需要为控件指定 `WS_CHILD` 和 `WS_VISIBLE` 风格。由于子窗口没有菜单,`CreateWindow` 的菜单参数用于指定子窗口的 ID,以区分同一父窗口上的不同控件。
示例代码(标准与通用控件)

#include <windows.h>
#include <commctrl.h> // 公共控件头文件,包含列表视图、树形视图等控件的定义

// 窗口过程函数,用于处理窗口消息
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE: // 窗口创建时触发
    {
        // 创建列表视图控件
        HWND hListView = CreateWindow(
            WC_LISTVIEW, // 列表视图的窗口类名
            L"ListView", // 控件初始文本
            WS_VISIBLE | WS_CHILD | LVS_REPORT, // 控件风格:可见、子窗口、报表视图
            10, 10, 300, 150, // 控件位置和大小
            hwnd, (HMENU)1, // 父窗口句柄和控件ID
            ((LPCREATESTRUCT)lParam)->hInstance, // 应用程序实例句柄
            NULL);

        // 添加列到列表视图
        LVCOLUMN lvColumn;
        lvColumn.mask = LVCF_TEXT | LVCF_WIDTH; // 设置列属性:文本和宽度
        lvColumn.cx = 100; // 列宽度
        lvColumn.pszText = L"Column 1"; // 列标题
        ListView_InsertColumn(hListView, 0, &lvColumn); // 插入第一列

        lvColumn.pszText = L"Column 2"; // 列标题
        ListView_InsertColumn(hListView, 1, &lvColumn); // 插入第二列

        // 添加项到列表视图
        LVITEM lvItem;
        lvItem.mask = LVIF_TEXT; // 设置项属性:文本
        lvItem.iItem = 0; // 第一行
        lvItem.iSubItem = 0; // 第一列
        lvItem.pszText = L"Item 1"; // 项文本
        ListView_InsertItem(hListView, &lvItem); // 插入项

        lvItem.iSubItem = 1; // 第二列
        lvItem.pszText = L"SubItem 1"; // 子项文本
        ListView_SetItem(hListView, &lvItem); // 设置子项文本

        // 创建树形视图控件
        HWND hTreeView = CreateWindow(
            WC_TREEVIEW, // 树形视图的窗口类名
            L"TreeView", // 控件初始文本
            WS_VISIBLE | WS_CHILD | TVS_HASLINES | TVS_HASBUTTONS, // 控件风格:可见、子窗口、带线条和按钮
            10, 170, 200, 150, // 控件位置和大小
            hwnd, (HMENU)2, // 父窗口句柄和控件ID
            ((LPCREATESTRUCT)lParam)->hInstance, // 应用程序实例句柄
            NULL);

        // 添加根节点
        TVINSERTSTRUCT tvInsert;
        tvInsert.hParent = NULL; // 根节点没有父节点
        tvInsert.hInsertAfter = TVI_LAST; // 插入到末尾
        tvInsert.item.mask = TVIF_TEXT; // 设置节点属性:文本
        tvInsert.item.pszText = L"Root"; // 根节点文本
        HTREEITEM hRoot = TreeView_InsertItem(hTreeView, &tvInsert); // 插入根节点

        // 添加子节点
        tvInsert.hParent = hRoot; // 子节点的父节点是根节点
        tvInsert.item.pszText = L"Child"; // 子节点文本
        TreeView_InsertItem(hTreeView, &tvInsert); // 插入子节点

        // 创建选项卡控件
        HWND hTabControl = CreateWindow(
            WC_TABCONTROL, // 选项卡控件的窗口类名
            L"TabControl", // 控件初始文本
            WS_VISIBLE | WS_CHILD, // 控件风格:可见、子窗口
            220, 170, 250, 150, // 控件位置和大小
            hwnd, (HMENU)3, // 父窗口句柄和控件ID
            ((LPCREATESTRUCT)lParam)->hInstance, // 应用程序实例句柄
            NULL);

        // 添加选项卡
        TCITEM tcItem;
        tcItem.mask = TCIF_TEXT; // 设置选项卡属性:文本
        tcItem.pszText = L"Tab 1"; // 选项卡标题
        TabCtrl_InsertItem(hTabControl, 0, &tcItem); // 插入第一个选项卡

        tcItem.pszText = L"Tab 2"; // 选项卡标题
        TabCtrl_InsertItem(hTabControl, 1, &tcItem); // 插入第二个选项卡

        // 创建热键控件
        HWND hHotKey = CreateWindow(
            HOTKEY_CLASS, // 热键控件的窗口类名
            NULL, // 控件初始文本
            WS_VISIBLE | WS_CHILD, // 控件风格:可见、子窗口
            10, 330, 200, 30, // 控件位置和大小
            hwnd, (HMENU)4, // 父窗口句柄和控件ID
            ((LPCREATESTRUCT)lParam)->hInstance, // 应用程序实例句柄
            NULL);

        // 创建按钮控件
        HWND hButton = CreateWindow(
            L"BUTTON", // 按钮控件的窗口类名
            L"Click Me", // 按钮文本
            WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, // 控件风格:可见、子窗口、标准按钮
            220, 330, 100, 30, // 控件位置和大小
            hwnd, (HMENU)5, // 父窗口句柄和控件ID
            ((LPCREATESTRUCT)lParam)->hInstance, // 应用程序实例句柄
            NULL);

        // 创建编辑框控件
        HWND hEdit = CreateWindow(
            L"EDIT", // 编辑框控件的窗口类名
            L"Type here", // 初始文本
            WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL | WS_BORDER, // 控件风格:可见、子窗口、自动水平滚动、带边框
            330, 330, 150, 30, // 控件位置和大小
            hwnd, (HMENU)6, // 父窗口句柄和控件ID
            ((LPCREATESTRUCT)lParam)->hInstance, // 应用程序实例句柄
            NULL);

        break;
    }
    case WM_COMMAND: // 处理控件通知消息
    {
        int ctrlID = LOWORD(wParam); // 获取控件ID
        int notifyCode = HIWORD(wParam); // 获取通知代码

        // 处理按钮点击事件
        if (ctrlID == 5 && notifyCode == BN_CLICKED)
        {
            MessageBox(hwnd, L"Button Clicked!", L"Notification", MB_OK); // 弹出消息框
        }
        break;
    }
    case WM_DESTROY: // 窗口销毁时触发
        PostQuitMessage(0); // 退出消息循环
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam); // 默认消息处理
    }
    return 0;
}

// 主函数,程序入口
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    // 初始化公共控件库
    INITCOMMONCONTROLSEX icc;
    icc.dwSize = sizeof(INITCOMMONCONTROLSEX); // 结构体大小
    icc.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_TAB_CLASSES | ICC_HOTKEY_CLASS; // 需要初始化的控件类型
    InitCommonControlsEx(&icc); // 初始化公共控件

    // 注册窗口类
    WNDCLASS wc = {0};
    wc.lpfnWndProc = WndProc; // 窗口过程函数
    wc.hInstance = hInstance; // 应用程序实例句柄
    wc.lpszClassName = L"MyWindowClass"; // 窗口类名

    if (!RegisterClass(&wc)) // 注册窗口类
    {
        MessageBox(NULL, L"Window Registration Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK); // 注册失败时弹出错误消息
        return 0;
    }

    // 创建窗口
    HWND hwnd = CreateWindow(
        L"MyWindowClass", // 窗口类名
        L"Common Controls Example", // 窗口标题
        WS_OVERLAPPEDWINDOW, // 窗口风格
        CW_USEDEFAULT, CW_USEDEFAULT, 500, 450, // 窗口位置和大小
        NULL, NULL, hInstance, NULL); // 父窗口句柄、菜单句柄、应用程序实例句柄、附加数据

    if (hwnd == NULL) // 窗口创建失败
    {
        MessageBox(NULL, L"Window Creation Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK); // 弹出错误消息
        return 0;
    }

    // 显示窗口
    ShowWindow(hwnd, nCmdShow); // 显示窗口
    UpdateWindow(hwnd); // 更新窗口

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) // 获取消息
    {
        TranslateMessage(&msg); // 翻译消息
        DispatchMessage(&msg); // 分发消息
    }

    return msg.wParam; // 返回程序退出码
}

五、控件风格

        每种控件除了通用的窗口风格(以 `WS_` 开头)外,还有自己的特定风格。以下是常见控件风格的前缀:

示例代码:

#include <windows.h>

// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
            // 创建按钮控件
            CreateWindow(
                "BUTTON",                     // 按钮类名
                "Click Me",                   // 按钮文本
                WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, // 按钮风格
                20, 20, 100, 30,             // 位置和大小
                hwnd,                         // 父窗口句柄
                (HMENU)1,                     // 控件ID
                ((LPCREATESTRUCT)lParam)->hInstance, // 实例句柄
                NULL
            );

            // 创建编辑框控件
            CreateWindow(
                "EDIT",                       // 编辑框类名
                "",                           // 初始文本
                WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, // 编辑框风格
                20, 60, 200, 30,              // 位置和大小
                hwnd,                         // 父窗口句柄
                (HMENU)2,                     // 控件ID
                ((LPCREATESTRUCT)lParam)->hInstance, // 实例句柄
                NULL
            );

            // 创建静态文本控件
            CreateWindow(
                "STATIC",                     // 静态文本类名
                "Hello, World!",              // 文本内容
                WS_VISIBLE | WS_CHILD | SS_CENTER, // 静态文本风格
                20, 100, 200, 30,             // 位置和大小
                hwnd,                         // 父窗口句柄
                (HMENU)3,                     // 控件ID
                ((LPCREATESTRUCT)lParam)->hInstance, // 实例句柄
                NULL
            );

            // 创建组合框控件
            CreateWindow(
                "COMBOBOX",                   // 组合框类名
                "",                           // 初始文本
                WS_VISIBLE | WS_CHILD | CBS_DROPDOWN, // 组合框风格
                20, 140, 200, 100,            // 位置和大小
                hwnd,                         // 父窗口句柄
                (HMENU)4,                     // 控件ID
                ((LPCREATESTRUCT)lParam)->hInstance, // 实例句柄
                NULL
            );

            // 创建列表框控件
            CreateWindow(
                "LISTBOX",                    // 列表框类名
                "",                           // 初始文本
                WS_VISIBLE | WS_CHILD | LBS_NOTIFY | WS_BORDER, // 列表框风格
                20, 180, 200, 100,            // 位置和大小
                hwnd,                         // 父窗口句柄
                (HMENU)5,                     // 控件ID
                ((LPCREATESTRUCT)lParam)->hInstance, // 实例句柄
                NULL
            );

            break;
        }
        case WM_COMMAND: {
            // 处理控件事件
            if (LOWORD(wParam) == 1) { // 按钮点击事件
                MessageBox(hwnd, "Button Clicked!", "Info", MB_OK);
            }
            break;
        }
        case WM_DESTROY: {
            PostQuitMessage(0);
            break;
        }
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // 注册窗口类
    WNDCLASS wc = {0};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = "MyWindowClass";
    RegisterClass(&wc);

    // 创建窗口
    HWND hwnd = CreateWindow(
        "MyWindowClass",                      // 窗口类名
        "Control Styles Example",             // 窗口标题
        WS_OVERLAPPEDWINDOW,                  // 窗口风格
        CW_USEDEFAULT, CW_USEDEFAULT, 300, 400, // 窗口位置和大小
        NULL, NULL, hInstance, NULL
    );

    if (hwnd == NULL) {
        return 0;
    }

    // 显示窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

六、控件相关的消息

控件与父窗口的交互通过两种消息实现:
        1. 控件控制消息:用于控制控件行为。
        2. 控件通知消息:用于通知父窗口用户行为。

6.1 控件控制消息

        每种控件除了接收通用窗口消息(以 `WM_` 开头)外,还有自己的专属消息。通过发送这些消息,可以控制控件的行为,而无需关心其内部处理逻辑。

6.2 控件通知消息

        控件通知消息用于子控件向父窗口通知事件,例如子控件被点击或需要重绘。常见的控件通知消息分为两类:
- `WM_COMMAND`:标准控件的通知消息。
- `WM_NOTIFY`:通用控件的通知消息。

示例代码:

#include <windows.h>

// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_COMMAND:
    {
        // 获取控件ID和通知代码
        int ctrlID = LOWORD(wParam);
        int notifyCode = HIWORD(wParam);

        // 处理按钮点击事件
        if (ctrlID == 1 && notifyCode == BN_CLICKED)
        {
            MessageBox(hwnd, L"Button Clicked!", L"Notification", MB_OK);
        }
        break;
    }
    case WM_NOTIFY:
    {
        // 获取NMHDR结构体指针
        NMHDR* pNmHdr = (NMHDR*)lParam;

        // 处理来自通用控件的通知
        if (pNmHdr->code == NM_CLICK)
        {
            MessageBox(hwnd, L"Control Clicked!", L"Notification", MB_OK);
        }
        break;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    // 注册窗口类
    WNDCLASS wc = {0};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = L"MyWindowClass";

    if (!RegisterClass(&wc))
    {
        MessageBox(NULL, L"Window Registration Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // 创建窗口
    HWND hwnd = CreateWindow(
        L"MyWindowClass", L"My Window", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
        NULL, NULL, hInstance, NULL);

    if (hwnd == NULL)
    {
        MessageBox(NULL, L"Window Creation Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // 创建按钮控件
    CreateWindow(
        L"BUTTON", L"Click Me", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
        50, 50, 100, 30, hwnd, (HMENU)1, hInstance, NULL);

    // 显示窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

 

        本节介绍了 Windows 控件的基础知识,包括标准控件、通用控件、控件的创建、风格以及消息处理机制。通过示例代码,展示了如何创建按钮和编辑框,并处理控件通知消息。


http://www.kler.cn/a/584542.html

相关文章:

  • WPS的Excel文档如何利用VB脚本批量替换超链接的内容
  • Flutter:跑马灯公告栏
  • 如何使用logrotete定时切割mysql的慢日志
  • “量超融合”突破 澳Quantum Brilliance融资2000万美元探索量子与超算协同
  • 如何用AI轻松制作高效又专业的PPT演示文稿
  • 【WPF】在System.Drawing.Rectangle中限制鼠标保持在Rectangle中移动?
  • 电商网站价格监控:动态价格数据的实时抓取案例
  • XMI(XML Metadata Interchange)和XML之间的关系
  • 【工具】jdk与jmeter下载与安装
  • [ NodeJs ] worker pool
  • TCP网络协议
  • MySQL(社区版)安装过程
  • 上下文微调(Contextual Fine-Tuning, CFT)提高大型语言模型(LLMs)在特定领域的学习和推理能力
  • 高级java每日一道面试题-2025年2月22日-数据库篇[Redis篇]-Redis是什么?
  • LangGraph 构建的工作流调用数据库的时候怎么添加重试机制
  • 基于Spring Boot的牙科诊所管理系统的设计与实现(LW+源码+讲解)
  • 上下文学习思维链COTPrompt工程
  • ClickHouse SQL优化:从原理到实战的深度指南
  • 【Grok3 deepseek-R1】利用伪逆方法求解机械臂速度级的运动方案
  • Unity知识总结——算法