1. 窗口的三大风格

    窗口风格分为两大类:标准风格,扩展风格

    重叠窗口:WS_OVERLAPPEDWINDOW,一般作为主窗口,拥有一个窗口的所有元素

    弹出窗口:WS_POPUPWINDOW,一般是程序运行时的提示窗口,操作面板

    子窗口:WS_CHILD,一般是控件

  2. 控件

    创建控件使用的还是 CreateWindow 函数

    1. 标准控件:简单的一些控件,包括:按钮、单选框、文本框、下拉框、静态文本等

      当点击标准控件时,给父窗口发送 WM_COMMAD

      ID:LOWORD(wParam)Code:HWORD(wParam),控件句柄 IParam

    2. 通用控件:扩展的控件,有的比较复杂,包括:树、列表、选项卡

      当点击控件时,给父窗口发送:WM_NOTIFY

    创建控件示例代码:在回调函数中创建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
       static HWND hText1 = 0;
    static HWND hButton1 = 0;
    static HWND hButton2 = 0;
    static HWND hButton3 = 0;
    static HWND hButton4 = 0;
    switch (uMessage) {
    case WM_CREATE: {//一般进行一些初始化操作
    //WM_CREATE的lParam参数携带的是创建窗口时的信息
    LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
    //1创建按钮
    hButton1 = CreateWindow(_T("button"), _T("点击"),
    BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
    100, 100, 80, 30,
    hWnd, (HMENU)0x1001, //子窗口无菜单,故当创建时此参数代表ID
    pcs->hInstance, 0);

    hButton2 = CreateWindow(_T("button"), _T("别点击"),
    BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
    190, 100, 80, 30,
    hWnd, (HMENU)0x1002, pcs->hInstance, 0);

    hButton3 = CreateWindow(_T("button"), _T("获取文本"),
    BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
    100, 140, 80, 30,
    hWnd, (HMENU)0x1003, pcs->hInstance, 0);

    hButton4 = CreateWindow(_T("button"), _T("设置文本"),
    BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
    190, 140, 80, 30,
    hWnd, (HMENU)0x1004, pcs->hInstance, 0);
    //2.创建文本框
    hText1 = CreateWindow(_T("edit"), _T(""),
    WS_CHILD | WS_VISIBLE | WS_BORDER,
    100, 180, 200, 40,
    hWnd, (HMENU)0x2001,
    /*g_hInstance*/pcs->hInstance,
    NULL);
    }break;

控件响应示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//窗口上的标准控件被操作了,就会给父窗口发这个消息
case WM_COMMAND: {
int nCode = HIWORD(wParam);//控件的通知码
int nId = LOWORD(wParam); //控件的ID
switch (nId) {
case 0x1001://点击button1会弹出文本并移动button2
if (nCode == BN_CLICKED) {
MessageBox(0, L"111", L"000", 0);
MoveWindow(hButton2, 300, 100, 80, 80, TRUE);
}break;
case 0x1002: {
MessageBox(0, L"别点我", L"222", 0);
static int n = 0;
if (n == 0) {//显示文本窗口
ShowWindow((HWND)0x000100CE, SW_SHOW);
n = 1;
}
else {//隐藏窗口
ShowWindow((HWND)0x000100CE, SW_HIDE);
n = 0;
}
}break;
case 0x1003: {//获取文本框文本
TCHAR buf[100] = {};
GetWindowText(hText1, buf, 100);
MessageBox(0, buf, _T("提示"), 0);
}break;
case 0x1004: {//获取到文本并加1,再设置回去
TCHAR buf[100] = {};
int nNum = 0;
//1获取文本,转为数字
GetWindowText(hText1, buf, 100);
_stscanf_s(buf, _T("%d"), &nNum);
//2自增后转为文本并设置到文本框中
++nNum;
_stprintf_s(buf, _T("%d"), nNum);
SetWindowText(hText1, buf);
}break;
  1. 资源

    1. 图标

      1571467736931

      1571467767681

      1571467802852

      IDI_ICON1 就是次图标资源的 ID

      也可以导入光标资源

      1
      2
      wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));//窗口图标光标
      wc.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR1));//设置光标
  1. 菜单:程序运行期间可以动态添加选项或删除选项

    • 顶级菜单:用于弹出下拉菜单
    • 下拉菜单:有具体的消息产生

    1571468200769

  1. 窗口类

    1
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //3 创建窗口
    HMENU hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));
    HWND hWnd = CreateWindow(
    L"15PB", //类名
    L"第一个窗口", //窗口名
    WS_OVERLAPPEDWINDOW,//重叠窗口风格
    100, 100, 400, 600, //位置和大小
    NULL, //父窗口句柄
    hMenu, //菜单句柄
    hInstance, //实例句柄
    NULL //附加信息
    );
  1. 弹出菜单

    主要需要使用: TrackPopupMenu

    主要需要注意的2个点:

    1. 坐标要使用屏幕坐标
    2. 弹出的菜单,需要是下拉菜单句柄,最好不是顶级菜单
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    case WM_RBUTTONDOWN://鼠标右键单击
    {
    //这个坐标是相对于窗口的坐标
    int x = LOWORD(lParam);
    int y = HIWORD(lParam);
    //弹出的时候,使用是相对于屏幕的坐标
    //需要做一个转换
    POINT pt = { x,y };
    ClientToScreen(hWnd, &pt);

    //弹出菜单
    HMENU hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MENU1));
    //获取下拉菜单的句柄
    HMENU hSubMenu0 =GetSubMenu(hMenu, 0);
    HMENU hSubMenu1 = GetSubMenu(hMenu, 1);
    TrackPopupMenu(
    hSubMenu1, //要弹出的菜单的句柄
    TPM_LEFTALIGN,//对齐方式等属性
    pt.x, pt.y, //弹出的坐标
    0, //保留的参数 ,没有用
    hWnd, //菜单的响应窗口是谁
    NULL
    );
    }break;
  1. 对话框编辑

    添加一个 Dlg 资源

    1571472387986

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//创建一个非模态对话框,不阻塞父窗口,需自己编写消息循环,真正的函数是CreateDialogParamW
void CreateDialog(
hInstance, //实例句柄
lpName, //资源ID
hWndParent, //父窗口句柄
lpDialogFunc //消息回调函数
);

//创建一个模态对话框,会阻塞父窗口,只有在窗口关闭后才会返回,自带消息循环,这是一个宏,真正的函数是DialogBoxParamW
void DialogBox(
hInstance,
lpName,
hWndParent,
lpDialogFunc
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<windows.h>
#include<tchar.h>
#include "resource.h"
//创建模态对话框
LRESULT CALLBACK DlgBoxProc(HWND hwnd, UINT uMessage,
WPARAM wparam, LPARAM lparam)
{
switch (uMessage) {
case WM_INITDIALOG://对话框的初始化函数,不是WM_CREATE
break;
case WM_CLOSE:
EndDialog(hwnd, 0);//关闭对话框使用的函数
break;
default: break;

}
return 0;//对话框不使用DefWndProc返回,默认处理直接返回0就行
}
//创建非模态对话框
LRESULT CALLBACK CreateDlgProc(HWND hwnd, UINT uMessage,
WPARAM wparam, LPARAM lparam)
{
switch (uMessage) {
case WM_INITDIALOG://对话框的初始化函数,不是WM_CREATE
break;
case WM_CLOSE:
EndDialog(hwnd, 0);//关闭对话框使用的函数
break;
default: break;

}
return 0;
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPreInstance, LPTSTR lpCmdLine,
int nCmdShow)
{
//创建模态对话框
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgBoxProc);

//创建非模态对话框,自己编写消息循环
HWND hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, CreateDlgProc);
//更新显示
UpdateWindow(hWnd);
ShowWindow(hWnd, SW_SHOW);
MSG msg = { 0 };
while (GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}