windows编程 标准控件的使用(按钮,文本框)
基本控件的使用
标准控件的创建
在我们创建窗口并且在CREATE的时候创建。
case WM_CREATE: CreateWindowW(WC_BUTTON, L"移动按钮", WS_CHILD | WS_VISIBLE, 50, 20, 200, 50,hwnd, (HMENU)0x100, hInstance, NULL); CreateWindowW(WC_BUTTON, L"获取文本框内容", WS_CHILD | WS_VISIBLE, 50, 100, 200, 50, hwnd, (HMENU)0x101, hInstance, NULL); CreateWindowW(WC_BUTTON, L"设置文本框内容", WS_CHILD | WS_VISIBLE, 50, 160, 200, 50, hwnd, (HMENU)0x102, hInstance, NULL); CreateWindowW(WC_BUTTON, L"设置父窗口", WS_CHILD | WS_VISIBLE, 50, 220, 200, 50, hwnd, (HMENU)0x103, hInstance, NULL); CreateWindowW(WC_BUTTON, L"枚举所有窗口", WS_CHILD | WS_VISIBLE, 350, 300, 200, 50, hwnd, (HMENU)0x105, hInstance, NULL); CreateWindowW(WC_EDIT, L"文本编辑框", WS_CHILD | WS_BORDER | WS_VISIBLE, 50, 300, 200, 50, hwnd, (HMENU)0x104, hInstance, NULL); CreateWindowW(WC_EDIT, L"文本输入框", WS_CHILD | WS_BORDER | WS_VISIBLE, 50, 360, 200, 50, hwnd, (HMENU)0x106, hInstance, NULL); break;
标准控件我们使用 WM_COMMAND来处理消息,其中wParam的高字节存储控制消息的通知代码,低字节存储控件的表示符,lParam存储控件的句柄。
处理WM_COMMAND消息,并且获取每个部件的标识符
case WM_COMMAND: { WORD Controlid = LOWORD(wParam); switch (Controlid) { case .... } }
移动按钮
我们要实现点击按钮,然后让按钮随机在窗口内移动,该如何操作?
我们只需获取其句柄,然后指定其在窗口的范围内Move即可,注意,我们需要获取其能移动的最大距离,不能越界,我们可以获取整个窗口的长和宽,存储在RECT的结构体中,然后MOVE移动,让他在这个范围MOVE即可:
case 0x100: { //随机获取坐标: 来一个区间范围 RECT rect{ 0 }; GetClientRect(hwnd, &rect); int x = rand() % (rect.right - 200); int y = rand() % (rect.bottom - 50); MoveWindow((HWND)lParam, x, y, 200, 50, TRUE); break; }
获取文本框的内容
首先获得文本框的句柄,再从句柄里获取消息即可:
两种方法:
- GetDlgItem:获取句柄;GetWindowTextW:从指定的句柄里获取消息
- GetDlgItemTextW:直接从句柄里获取消息
case 0x101: { /* 获取文本框的内容 */ WCHAR str_dst[100]{ 0 }; HWND hedit=GetDlgItem(hwnd,0x104); //首先获取文本框窗口的句柄 //GetDlgItemTextW(hwnd, 0x104, str_dst, 100); GetWindowTextW(hedit, str_dst, 100); //根据得到的子窗口的句柄得到字符串并且放入一个字符数组中 MessageBoxW(hwnd, str_dst, L"提示", MB_OK); //读取文本框的内容 break; }
自动设置文本框内容
任务:从一个文本框里输入信息,然后经过一个按钮点击,把这个消息发送到另一个文本框,相当于复制内容.
两种方法:
- 获取读取的原始文本框句柄, 然后得到其文本,然后根据此文本直接放入另一个文本框。
- 再次获取目标句柄,然后再发送文本。
case 0x102: { /* 根据读取的文本框的内容再复制到另一个文本框 */ WCHAR wchar_buff[100]{ 0 }; //获取文本框的句柄 HWND handle=GetDlgItem(hwnd, 0x104); //获取目标编辑框句柄 GetWindowTextW(handle, wchar_buff,100); //获取读入的内容 SetDlgItemTextW(hwnd, 0x106, wchar_buff); //HWND dst_HWND = GetDlgItem(hwnd, 0x106); //SetWindowTextW(dst_HWND, wchar_buff); break; }
注意:
SetDlgItemTextW 等价于:首先GetDlgItem,然后再SetWindowTextW。
设置父窗口
打开记事本,保证记事本的名字正确,运行代码,你就会发现你的0x103标识的按钮跑到记事本窗口上去了。
case 0x103: { HWND handle=FindWindowW(NULL, L"无标题 - 记事本"); SetParent((HWND)lParam, handle); //原窗口句柄和新的父窗口句柄 break; }
枚举出所有窗口
怎么知道你的主窗口上有多少个子窗口?
可以枚举来显示一下:
case 0x105: { EnumChildWindows(hwnd, EnumChildProc, 0); break; }
//枚举子窗口的回调函数 BOOL CALLBACK EnumChildProc( HWND hwnd, LPARAM lparam ) { WCHAR wchar_buff[100]{ 0 }; GetWindowText(hwnd, wchar_buff, 100); println(L"子窗口: %s\n", wchar_buff); return TRUE; }
注意,我们需要一个格式化输出的函数,以便于我们能够获取其输出内容:
//格式化输出函数 void println(LPCWSTR format, ...) { WCHAR wchar_buff[100]{ 0 }; va_list args; //参数列表拷贝到args变量中 va_start(args, format); //保存参数列表 wvsprintfW(wchar_buff, format, args); //格式化输出到wchar_buff va_end(args); //清理工作 OutputDebugStringW(wchar_buff); //内容发送到Debug进行调试 }
测试代码
#include <iostream> #include <Windows.h> #include <CommCtrl.h> //格式化输出函数 void println(LPCWSTR format, ...) { WCHAR wchar_buff[100]{ 0 }; va_list args; //参数列表拷贝到args变量中 va_start(args, format); //保存参数列表 wvsprintfW(wchar_buff, format, args); //格式化输出到wchar_buff va_end(args); //清理工作 OutputDebugStringW(wchar_buff); //内容发送到Debug进行调试 } //枚举子窗口的回调函数 BOOL CALLBACK EnumChildProc( HWND hwnd, LPARAM lparam ) { WCHAR wchar_buff[100]{ 0 }; GetWindowText(hwnd, wchar_buff, 100); println(L"子窗口: %s\n", wchar_buff); return TRUE; } LRESULT CALLBACK Wndproc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static HINSTANCE hInstance = GetModuleHandleW(NULL); //获取当前窗口句柄 switch (uMsg) { case WM_CREATE: CreateWindowW(WC_BUTTON, L"移动按钮", WS_CHILD | WS_VISIBLE, 50, 20, 200, 50,hwnd, (HMENU)0x100, hInstance, NULL); CreateWindowW(WC_BUTTON, L"获取文本框内容", WS_CHILD | WS_VISIBLE, 50, 100, 200, 50, hwnd, (HMENU)0x101, hInstance, NULL); CreateWindowW(WC_BUTTON, L"设置文本框内容", WS_CHILD | WS_VISIBLE, 50, 160, 200, 50, hwnd, (HMENU)0x102, hInstance, NULL); CreateWindowW(WC_BUTTON, L"设置父窗口", WS_CHILD | WS_VISIBLE, 50, 220, 200, 50, hwnd, (HMENU)0x103, hInstance, NULL); CreateWindowW(WC_BUTTON, L"枚举所有窗口", WS_CHILD | WS_VISIBLE, 350, 300, 200, 50, hwnd, (HMENU)0x105, hInstance, NULL); CreateWindowW(WC_EDIT, L"文本编辑框", WS_CHILD | WS_BORDER | WS_VISIBLE, 50, 300, 200, 50, hwnd, (HMENU)0x104, hInstance, NULL); CreateWindowW(WC_EDIT, L"文本输入框", WS_CHILD | WS_BORDER | WS_VISIBLE, 50, 360, 200, 50, hwnd, (HMENU)0x106, hInstance, NULL); break; case WM_CLOSE: DestroyWindow(hwnd); PostQuitMessage(NULL); break; case WM_COMMAND: { WORD Controlid = LOWORD(wParam); switch (Controlid) { case 0x100: { //随机获取坐标: 来一个区间范围 RECT rect{ 0 }; GetClientRect(hwnd, &rect); int x = rand() % (rect.right - 200); int y = rand() % (rect.bottom - 50); MoveWindow((HWND)lParam, x, y, 200, 50, TRUE); break; } case 0x101: { /* 获取文本框的内容 */ WCHAR str_dst[100]{ 0 }; HWND hedit=GetDlgItem(hwnd,0x104); //首先获取文本框窗口的句柄 GetDlgItemTextW(hwnd, 0x104, str_dst, 100); //GetWindowTextW(hedit, str_dst, 100); //根据得到的子窗口的句柄得到字符串并且放入一个字符数组中 MessageBoxW(hwnd, str_dst, L"提示", MB_OK); //读取文本框的内容 break; } case 0x102: { /* 根据读取的文本框的内容再复制到另一个文本框 */ WCHAR wchar_buff[100]{ 0 }; //获取文本框的句柄 HWND handle=GetDlgItem(hwnd, 0x104); //获取目标编辑框句柄 GetWindowTextW(handle, wchar_buff,100); //获取读入的内容 SetDlgItemTextW(hwnd, 0x106, wchar_buff); //HWND dst_HWND = GetDlgItem(hwnd, 0x106); //SetWindowTextW(dst_HWND, wchar_buff); break; } case 0x103: { HWND handle=FindWindowW(NULL, L"无标题 - 记事本"); SetParent((HWND)lParam, handle); //原窗口句柄和新的父窗口句柄 break; } case 0x105: { EnumChildWindows(hwnd, EnumChildProc, 0); break; } } break; } } return DefWindowProcW(hwnd, uMsg, wParam, lParam); } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { //1. 创建窗口类 WNDCLASSW myClassWindow{ 0 }; myClassWindow.lpszClassName = L"ylh"; myClassWindow.lpfnWndProc = Wndproc; //回调函数 myClassWindow.hbrBackground = CreateSolidBrush(RGB(205, 156, 29)); //2. 注册窗口 RegisterClassW(&myClassWindow); //3. 创建窗口 HWND hWIndow = CreateWindowW( myClassWindow.lpszClassName, L"dasd", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL ); //4. 显示窗口 ShowWindow(hWIndow, SW_SHOWNORMAL); //5. 处理消息事件 MSG msg{ 0 }; while (GetMessageW(&msg, NULL, NULL, NULL)) { TranslateMessage(&msg); DispatchMessageW(&msg); } return 0; }
本文来自博客园,作者:hugeYlh,转载请注明原文链接:https://www.cnblogs.com/helloylh/p/17209690.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?