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;
}

获取文本框的内容

首先获得文本框的句柄,再从句柄里获取消息即可:

两种方法:

  1. GetDlgItem:获取句柄;GetWindowTextW:从指定的句柄里获取消息
  2. 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;
}

自动设置文本框内容

任务:从一个文本框里输入信息,然后经过一个按钮点击,把这个消息发送到另一个文本框,相当于复制内容.

两种方法:

  1. 获取读取的原始文本框句柄, 然后得到其文本,然后根据此文本直接放入另一个文本框。
  2. 再次获取目标句柄,然后再发送文本。
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;
}

在这里插入图片描述

posted @   hugeYlh  阅读(104)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示