window控件:
控件是常见的窗口上的交互元素例如:一个按钮,一个复选框,一个列表框等。
当控件的特定功能被触发后,会主动发送消息通知父窗口,父窗口可以通过发送消息给控件控制控件的行为。
控件的本质是一个窗口
windows窗口风格
windows窗口从其特点是主要分为两大类
- 表明窗口和其他窗口关系的(WS_OVERLAPED(重叠)、WS_POPPUP(弹出)、WS_CHILD(子窗口))
- 表明窗口自身外观特征的(WS_BORDER、WS_CAPITON...)
windows标准控件:
窗口类名 | 控件名称 |
---|---|
WC_BUTTON | 按钮 |
WC_STATIC | 静态文本 |
WC_COMBOBOX | 复合框 |
WC_EDIT | 编辑框 |
WC_LISTBOX | 列表框 |
WC_SCROLLBAR | 滚动条 |
windows通用控件:
WC_LISTVIEW 列表框控件
WC_TREEVIEW 树控件
WC_TABCONTROL Tab控件
...
控件的响应
子控件通知父窗口一些事件,例如子控件被点击,需要通过以下两类消息
标准控件的消息:WM_COMMAND
通用控件的消息:WM_NOTIFY
添加一个按钮演示
cpp
{
static HINSTANCE hInstance = GetModuleHandleW(NULL);
switch (uMsg)
{
case WM_CREATE:
//添加控件
CreateWindowW(WC_BUTTON,L"按钮1",WS_CHILD|WS_VISIBLE,10,10,80,60,hwnd,(HMENU)0x100, hInstance,0);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
按钮消息处理
cpp
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
static HINSTANCE hInstance = GetModuleHandleW(NULL);
switch (uMsg)
{
case WM_CREATE:
//添加控件
CreateWindowW(WC_BUTTON,L"按钮1",WS_CHILD|WS_VISIBLE,10,10,80,60,hwnd,(HMENU)0x100, hInstance,0);
CreateWindowW(WC_BUTTON,L"按钮2",WS_CHILD|WS_VISIBLE,10,80,80,60,hwnd,(HMENU)0x101, hInstance,0);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
PostQuitMessage(0);
break;
case WM_COMMAND:
WORD ContrlId = LOWORD(wParam);
if (ContrlId==0x100)
{
MessageBoxW(hwnd, L"按钮1", L"提示", MB_OK);
}else if(ContrlId == 0x101)
{
MessageBoxW(hwnd, L"按钮2", L"提示", MB_OK);
}
break;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
窗口操作函数的使用
操作窗口的通用函数
函数 | 说明 |
---|---|
MoveWindow | 移动窗口 |
UpdateWindow | 更新窗口 |
GetWindowText | 获取窗口标题 |
SetWindowText | 设置窗口标题 |
FindWindow | 查找窗口返回句柄 |
GetClientRect | 获取窗口客户区大小 |
SetWindowPos | 设置窗口位置 |
EnumChildWindows | 枚举窗口下的所有子窗口 |
实现按钮(窗口)移动
cpp
#include<Windows.h>
#include<iostream>
#include<CommCtrl.h>
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
static HINSTANCE hInstance = GetModuleHandleW(NULL);
switch (uMsg)
{
case WM_CREATE:
//添加控件
CreateWindowW(WC_BUTTON,L"移动按钮",WS_CHILD|WS_VISIBLE,10,10,80,60,hwnd,(HMENU)0x100, hInstance,0);
CreateWindowW(WC_BUTTON,L"获取文本框内容",WS_CHILD|WS_VISIBLE,10,80,80,60,hwnd,(HMENU)0x101, hInstance,0);
CreateWindowW(WC_BUTTON,L"设置文本框内容",WS_CHILD|WS_VISIBLE,10,160,80,60,hwnd,(HMENU)0x102, hInstance,0);
CreateWindowW(WC_BUTTON,L"设置父窗口",WS_CHILD|WS_VISIBLE,10,240,80,60,hwnd,(HMENU)0x103, hInstance,0);
CreateWindowW(WC_EDIT,L"文本框内容",WS_CHILD|WS_BORDER|WS_VISIBLE,10,320,80,60,hwnd,(HMENU)0x104, hInstance,0);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
PostQuitMessage(0);
break;
case WM_COMMAND:
WORD ContrlId = LOWORD(wParam);
switch (ContrlId)
{
case 0x100:
{
RECT rect{ 0 };
GetClientRect(hwnd, &rect);
int x = rand() % rect.right;
int y = rand() % rect.bottom;
MoveWindow((HWND)lParam, x, y, 80, 60, TRUE);
}
}
break;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPreInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
//1、创建一个窗口类
WNDCLASSW myClass = { 0 };
myClass.lpszClassName = L"xiaowang";
myClass.lpfnWndProc = WindowProc;
myClass.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
//2、注册窗口类
RegisterClassW(&myClass);
//3、创建窗口
HWND hwindow=CreateWindowW(
myClass.lpszClassName,
L"xiaowang",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
NULL,
NULL,
hInstance,
0
);
//4、显示窗口
ShowWindow(hwindow,SW_SHOWNORMAL );
//5、获取消息
MSG msg = { 0 };
while (GetMessageW(&msg,0,0,0))
{
DispatchMessageW(&msg);//分发消息给消息处理函数
}
return 0;
}
实现获取文本框内容
cpp
case 0x101:
{
WCHAR buff[100]{ 0 };
HWND hedit = GetDlgItem(hwnd, 0x104);
GetWindowTextW(hedit, buff, 100);
MessageBoxW(hwnd, buff, L"提示", MB_OK);
break;
}
设置文本内容
cpp
case 0x102:
{
HWND hedit = GetDlgItem(hwnd, 0x104);
//SetWindowTextW(hedit, L"设置了文本内容");
SetDlgItemTextW(hedit, 0x104,L"设置了文本内容SetDlgItemTextW");
break;
}
设置父窗口
cpp
case 0x103:
{
HWND hnote = FindWindowW(NULL, L"记事本");
SetParent((HWND)lParam, hnote);
break;
}
使文本框内容可编辑
加上
TranslateMessage(&msg);
cpp
//4、显示窗口
ShowWindow(hwindow,SW_SHOWNORMAL );
//5、获取消息
MSG msg = { 0 };
while (GetMessageW(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);//分发消息给消息处理函数
}
return 0;
}
资源操作
无法直接定位到资源,并使用函数操作他们,和窗口一样,一般情况需要得到资源的句柄
LoadXXX:XXX是资源类型
LoadTcon 载入图标、LoadCursor载入光标 LoadMenu 载入菜单
图标资源:LoadIcon
光标资源:LoadCursor
菜单资源:
1、
lpszMenuName
2、
LoadMenu
CreateWindow();
3、
LoadMenu
GetSubMenu();
TrackPopupMenu()
图标
添加 一个资源
选择icon
载入图标
按钮点击后改变
cpp
#include"resource.h"
case 0x101:
{
//MAKEINTRESOURCEW为强制转换
//IDI_ICON1为资源视图中图标的名字
HICON hIcon=LoadIcon(hInstance,MAKEINTRESOURCEW(IDI_ICON1));
SetClassLongW(hwnd, GCL_HICON, (LONG)hIcon);
break;
}
窗口创建时改变图标
cpp
//1、创建一个窗口类
WNDCLASSW myClass = { 0 };
myClass.lpszClassName = L"xiaowang";
myClass.lpfnWndProc = WindowProc;
myClass.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
myClass.hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON1));
//系统提供图标
//myClass.hIcon = LoadIconW(0, IDI_ERROR);
//2、注册窗口类
RegisterClassW(&myClass);
光标
创建光标文件
载入光标
cpp
case 0x102:
{
HCURSOR hcursor = LoadCursorW(hInstance, MAKEINTRESOURCEW(IDC_CURSOR1));
SetClassLongW(hwnd, GCL_HCURSOR, (LONG)hcursor);
break;
}
窗口创建时改变光标
cpp
//1、创建一个窗口类
WNDCLASSW myClass = { 0 };
myClass.lpszClassName = L"xiaowang";
myClass.lpfnWndProc = WindowProc;
myClass.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
myClass.hCursor = LoadCursorW(hInstance, MAKEINTRESOURCEW(IDC_CURSOR1))
菜单
初始化时载入菜单
cpp
//1、创建一个窗口类
WNDCLASSW myClass = { 0 };
myClass.lpszClassName = L"xiaowang";
myClass.lpfnWndProc = WindowProc;
myClass.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
myClass.lpszMenuName = MAKEINTRESOURCEW(IDR_MENU1);
创建窗口时
cpp
//3、创建窗口
HMENU hmenu = LoadMenuW(hInstance, MAKEINTRESOURCEW(IDR_MENU1));
HWND hwindow=CreateWindowW(
myClass.lpszClassName,
L"xiaowang",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
NULL,
hmenu,
hInstance,
0
);
通过按钮载入
cpp
case 0x100:
{
HMENU hmenu = LoadMenuW(hInstance, MAKEINTRESOURCEW(IDR_MENU1));
SetMenu(hwnd, hmenu);
鼠标右键点击时出现菜单
cpp
switch (uMsg)
{
case WM_CREATE:
.....
case WM_RBUTTONDOWN:
{
POINT point{ 0 };
ClientToScreen(hwnd, &point);
GetCursorPos(&point);
HMENU hMenu = LoadMenuW(hInstance, MAKEINTRESOURCEW(IDR_MENU1));
HMENU hSubMenu = GetSubMenu(hMenu, 0);
TrackPopupMenu(hSubMenu, TPM_LEFTALIGN, point.x, point.y, 0, hwnd, NULL);
break;
}
捕获菜单被点击
cpp
case ID_40001:
{
MessageBoxW(hwnd, L"子菜单1被点击了",L"提示",MB_OK);
}
对话框资源
对话框资源可以创建一个对话框,以及其上的子控件。通过对话框可以进行可视化编辑。
对话框有两种形式:
模态对话框、非模态对话框
区别:模态对话框会阻塞主窗口,非模态对话框不会
添加一个对话框
创建非模态对话框
cpp
#include<Windows.h>
#include<CommCtrl.h>
#include"resource.h"
INT_PTR CALLBACK Dlgproc(
HWND hWnd,
UINT Umsg,
WPARAM wparam,
LPARAM lparam
) {
switch (Umsg)
{
case WM_INITDIALOG:
{
MessageBox(hWnd,L"窗口创建了",L"标题",MB_OK);
break;
}
case WM_CLOSE:
{
DestroyWindow(hWnd);
PostQuitMessage(0);
break;
}
default:
{
return FALSE;
}
}
return TRUE;
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPreInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
HWND hwnd=CreateDialogW(hInstance, MAKEINTRESOURCEW(IDD_DIALOG1),NULL,Dlgproc);
ShowWindow(hwnd, SW_SHOWNORMAL);
MSG msg{ 0 };
while (GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}