基本控件的使用
标准控件的创建
在我们创建窗口并且在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;
}