复习

  1. 描述窗口间关系的属性有三大类:重叠窗口、弹出窗口、子窗口

  2. 操作窗口的函数:

    MoveWindow 将窗口移动到指定位置

    ShowWindow 显示或隐藏窗口

    GetWindowText 获取窗口标题(若是控件,则获取控件内容)

    SetWindowText 设置窗口标题

    FindWindow 根据窗口名获取其句柄

    GetParent 获取窗口的父句柄

    ……

  3. 创建一个控件使用 CreateWindow 函数,一般使用以下两个属性:

    WS_CHILD WS_VISIABLE

  4. 控件目前分为2类:

    标准控件:被操作时会给父窗口发送 WM_COMMAD,包括:按钮、单选框、复选框、编辑框、静态文本、静态图片、下拉框

    通用控件,包括:树、列表、选项卡

  5. 资源:图标、光标、菜单

    基本使用方式:通过LoadIconLoadCursorLoadMenu 得到句柄,填到窗口类相应字段上

    菜单相关的注意点:菜单可以将句柄填到 CreateWindow 相应参数上;菜单项在程序运行期间可以动态添加选项或删除选项;菜单可以弹出来,TrackPopupMenu 函数,弹出的菜单句柄需要一个下拉菜单的句柄

    1
    2
    3
    4
    5
    6
    7
    TrackPopupMenu(
    hSubMenu1, //要弹出的菜单的句柄
    TPM_LEFTALIGN, //对齐方式等属性
    pt.x, pt.y, //弹出的坐标,这个坐标是相对于屏幕的
    0, //保留的参数 ,没有用
    hWnd, //菜单的响应窗口是谁(重要)
    NULL);
  1. 对话框的创建,使用 Dlg 类型的资源去创建对话框,有两大类对话框:

    模态对话框 DialogBox :函数会阻塞住父窗口,自带消息循环,对话框被关闭函数返回

    非模态对话框 CreateDialog :不会阻塞父窗口,调用时直接返回,自己写消息循环

今日内容

标准控件:

  1. 复选框

    BM_GETCHECK 获取单选框或复选框的检查状态,

    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
    53
    INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMessage, 
    WPARAM wParam, LPARAM lParam){//回调函数
    switch (uMessage){
    case WM_CLOSE://关闭窗口
    EndDialog(hWnd, 0);
    break;
    case WM_INITDIALOG://对话框程序的初始化消息
    break;
    case WM_COMMAND:{
    int nCode = HIWORD(wParam);//控件的响应码
    int nId = LOWORD(wParam);//控件的ID

    //复选框的使用
    case IDC_B_CLEAN://选择某项进行清除的按钮
    {
    //1 检测复选框,哪些被选中
    // 获取复选框的句柄
    HWND hCheck1 = GetDlgItem(hWnd, IDC_CHECK1);
    HWND hCheck2 = GetDlgItem(hWnd, IDC_CHECK2);
    HWND hCheck3 = GetDlgItem(hWnd, IDC_CHECK3);
    //2 获取状态,去清理磁盘
    BOOL bCheck = 0;
    bCheck = SendMessage(hCheck1, BM_GETCHECK, 0, 0);
    if (bCheck==TRUE)
    {
    MessageBox(0, L"开始清理C盘", 0, 0);
    }
    bCheck = SendMessage(hCheck2, BM_GETCHECK, 0, 0);
    if (bCheck == TRUE)
    {
    MessageBox(0, L"开始清理D盘", 0, 0);
    }
    bCheck = SendMessage(hCheck3, BM_GETCHECK, 0, 0);
    if (bCheck == TRUE)
    {
    MessageBox(0, L"开始清理E盘", 0, 0);
    }
    }
    break;
    case IDC_B_ALLSEL://全选按钮
    {
    //1 检测复选框,哪些被选中
    // 获取复选框的句柄
    HWND hCheck1 = GetDlgItem(hWnd, IDC_CHECK1);
    HWND hCheck2 = GetDlgItem(hWnd, IDC_CHECK2);
    HWND hCheck3 = GetDlgItem(hWnd, IDC_CHECK3);
    SendMessage(hCheck1, BM_SETCHECK, 1, 0);//第3个参数表示是否被选中
    SendMessage(hCheck2, BM_SETCHECK, 1, 0);
    SendMessage(hCheck3, BM_SETCHECK, 1, 0);
    }
    }break;
    }
    }

    1571638048355

  1. 单选框

    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
    case IDC_B_LOGIN:
    {
    HWND hRadio1 = GetDlgItem(hWnd, IDC_RADIO1);
    HWND hRadio2 = GetDlgItem(hWnd, IDC_RADIO2);
    HWND hRadio3 = GetDlgItem(hWnd, IDC_RADIO3);
    HWND hRadio4 = GetDlgItem(hWnd, IDC_RADIO4);
    BOOL bCheck = 0;
    bCheck = SendMessage(hRadio1, BM_GETCHECK, 0, 0);
    if (bCheck ==TRUE )
    {
    MessageBox(0, L"登录联通服务器", 0, 0);
    }
    bCheck = SendMessage(hRadio2, BM_GETCHECK, 0, 0);
    if (bCheck == TRUE)
    {
    MessageBox(0, L"登录电信服务器", 0, 0);
    }
    bCheck = SendMessage(hRadio3, BM_GETCHECK, 0, 0);
    if (bCheck == TRUE)
    {
    MessageBox(0, L"登录移动服务器", 0, 0);
    }
    bCheck = SendMessage(hRadio4, BM_GETCHECK, 0, 0);
    if (bCheck == TRUE)
    {
    MessageBox(0, L"登录教育网服务器", 0, 0);
    }
    }break;

    1571638524364

    所有的 Radio 选项只能选一个,若有2组就会出问题,故需要将 Radio 分组

    Ctr+D,然后编辑,使同一组的 Radio 序号连续,再将每一组第一个 RadioGroup 属性设为 True

    1571639482735

    1571639493737

  1. 静态文本:没什么操作,只是起到提示作用

  2. 静态图片

    拖拽一个图片控件

    1571639634968

    将其类型修改为 Bitmap

    1571639687587

    然后找一张 Bitmap 图片,bmp 格式,导入进来

    1571639756741

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    case IDC_B_SHIFT://变换图片的按钮
    {
    static int sel = 0;
    //1 获取图片控件的句柄
    HWND hPic = GetDlgItem(hWnd, IDC_STATIC1);
    //2 获取位图资源的句柄
    HINSTANCE hInstance = GetModuleHandle(NULL);//实例句柄
    HBITMAP Bit1 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));//图1句柄
    HBITMAP Bit2 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2));//图2句柄
    //3 给图片控件发消息,携带位图资源的句柄,然后就能显示出来了
    if (sel==0)
    {
    SendMessage(hPic, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)Bit1);
    sel = 1;
    }
    else
    {
    SendMessage(hPic, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)Bit2);
    sel = 0;
    }
    }break;
  1. 下拉框(ComboBox

    注意:下拉框的高度需要点击小三角才能调整

    1571640076926

    添加选项:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    case IDC_B_ADDCOMBO:
    {
    wchar_t Buf[8][10] =
    { L"三里屯",L"南锣鼓巷",L"十三陵",L"五道口",L"十五派" };
    static int nIndex = 0;//下标
    //1 获取ComboBox的句柄
    HWND hCombo = GetDlgItem(hWnd, IDC_COMBO1);
    //2 添加一个选项
    ComboBox_AddString(hCombo, Buf[nIndex]);
    nIndex++;
    }break;

    获取选项:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    case IDC_B_GETCOMBO:
    {
    //1 获取ComboBox的句柄
    HWND hCombo = GetDlgItem(hWnd, IDC_COMBO1);
    //2 再获取选项
    int n = ComboBox_GetCurSel(hCombo);
    //3 获取选择的文本
    WCHAR szText[64] = { 0 };
    ComboBox_GetText(hCombo, szText, 64);
    //4 输出出来
    _MyMessageBox(L"选择的是第%d项,内容为%s", n, szText);
    }break;

通用控件

  1. 进度条

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    case IDC_B_PROGINC:
    {
    static int n = 0;
    //1 获取进度条控件的句柄
    HWND hPro = GetDlgItem(hWnd, IDC_PROGRESS1);
    //2 设置进度
    SendMessage(hPro, PBM_SETPOS, n, 0);
    n += 5;
    if (n>=100)
    n = 0;
    }break;

    1571640656409

  1. 滑块

    滑块在拖动时会给父窗口发送 WM_HSCROLL 消息,以及 WM_VSCROLL

    检测滑动:

    1
    2
    3
    4
    5
    6
    7
    8
    case WM_HSCROLL:
    {
    //1 获取滑块的句柄
    HWND hSlider = GetDlgItem(hWnd, IDC_SLIDER1);
    //2 获取滑块的当前位置
    int nLoc = SendMessage(hSlider, TBM_GETPOS, 0, 0);
    _trace(L"%d\n", nLoc);
    }break;

    设置滑块位置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    case IDC_B_SETSLIDER:
    {
    //1 获取滑块的句柄
    HWND hSlider = GetDlgItem(hWnd, IDC_SLIDER1);
    //2 获取滑块的当前位置
    int nLoc = SendMessage(hSlider, TBM_GETPOS, 0, 0);
    //3 +5再设置上去
    SendMessage(hSlider, TBM_SETPOS,TRUE , nLoc + 5);
    }break;
  1. 列表框控件

    ListView 的基本操作:添加列、添加行、删除行

    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
    case IDC_B_INSERT_COL://给列表框添加列
    {
    LVCOLUMN lc = { 0 };
    // 姓名 年龄 性别 身高
    //1 获取控件的句柄
    HWND hList = GetDlgItem(hWnd, IDC_LIST2);
    //2 添加
    lc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
    lc.fmt = LVCFMT_LEFT;
    lc.cx = 100;
    lc.pszText = (LPWSTR)L"姓名";
    ListView_InsertColumn(hList, 0, &lc);
    lc.pszText = (LPWSTR)L"年龄";
    ListView_InsertColumn(hList, 1, &lc);
    lc.pszText = (LPWSTR)L"性别";
    ListView_InsertColumn(hList, 2, &lc);
    lc.pszText = (LPWSTR)L"身高";
    ListView_InsertColumn(hList, 3, &lc);
    }break;
    case IDC_B_INSERT_ITEM://给列表框添加行
    {
    LVITEM li = {};
    //1 获取控件的句柄
    HWND hList = GetDlgItem(hWnd, IDC_LIST2);
    //2 添加一行
    li.mask = LVIF_TEXT;
    li.pszText = (LPWSTR)L"小芳";
    li.iItem = 0;
    ListView_InsertItem(hList, &li);
    //3 给行内单元格设置文本
    ListView_SetItemText(hList, 0, 1, (LPWSTR)L"20");
    ListView_SetItemText(hList, 0, 2, (LPWSTR)L"女");
    ListView_SetItemText(hList, 0, 3, (LPWSTR)L"170");
    //2 添加一行
    li.mask = LVIF_TEXT;
    li.pszText = (LPWSTR)L"小明";
    li.iItem = 1;
    ListView_InsertItem(hList, &li);
    //3 给行内单元格设置文本
    ListView_SetItemText(hList, 1, 1, (LPWSTR)L"20");
    ListView_SetItemText(hList, 1, 2, (LPWSTR)L"男");
    ListView_SetItemText(hList, 1, 3, (LPWSTR)L"170");
    }break;
    case IDC_B_DELETE_ITEM://给列表框删除一行
    {
    //1 获取控件的句柄
    HWND hList = GetDlgItem(hWnd, IDC_LIST2);
    //2 删除一行
    ListView_DeleteItem(hList, 1);
    }break;

    1571641398648

    将属性调整为报表模式

    1571641437131

    高级用法:

    通过设置扩展属性,能够让列表框控件具有更多特性

    1
    2
    3
    4
    5
    6
    case IDC_B_SETLISTEX:
    {
    HWND hList = GetDlgItem(hWnd, IDC_LIST2);
    ListView_SetExtendedListViewStyle(hList,
    LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
    }

    处理列表框的 WM_NOTIFY 消息:

    其中 wParam 是发生 WM_NOTIFY 消息的控件ID,lParamNMHDR 指针

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    case WM_NOTIFY://我们在这里仅响应了一个列表框的右键点击
    {
    switch (wParam)
    {
    case IDC_LIST2:
    {
    NMHDR* pNm = (NMHDR*)lParam;
    if (pNm->code == NM_RCLICK)//右键点击
    {
    wchar_t buf[64] = {};
    LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
    //HWND hList = GetDlgItem(hWnd, IDC_LIST2);
    HWND hList = lpnmitem->hdr.hwndFrom;//发送消息的控件句柄
    ListView_GetItemText(hList, lpnmitem->iItem,
    lpnmitem->iSubItem, buf, 64);
    MessageBox(0, buf, 0, 0);
    }
    }break;