• WS_TABSTOP 与 BS_DEFPUSHBUTTON 第一次使有


    关于 WS_TABSTOP,我一直没搞明白,为何加了 WS_TABSTOP ,当按下 Tab 键时,窗口中的控件还是不能自动的切换焦点。

    为何 SetFocus(hwnd); 后,虽然按钮已获得焦点,但焦点的虚线框不显示。

    关于 BS_DEFPUSHBUTTON,为何加了,在窗体上按下【回车】什么反应都没有。

    过去几年,我一直都是通过编写 WM_KEYDOWN 代码来实现 WS_TABSTOP 和 BS_DEFPUSHBUTTON,今天无意发现一篇文章上有这样的写法: 

    while (GetMessage(&msg, NULL, 00)) 
    {
            if (!IsDialogMessage(hWnd, &msg))
            {
                TranslateMessage(&msg);
    
                DispatchMessage(&msg);            
            }
    }

    关于 IsDialogMessage() 介绍:https://docs.microsoft.com/zh-cn/windows/desktop/api/winuser/nf-winuser-isdialogmessagea

    通过下面几段代码,就可实现在窗口上按 Tab 键自动切换焦点, 同时也能实现 【默认按钮】效果:

    CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",
                                          WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER | WS_TABSTOP,
                                          221,   // xpos
                                          101,  // ypos
                                          60, //width
                                          22, //height
                                          hwnd_dialog_four_squares, (HMENU) NULL,   hThisInst,   NULL);
    
    CreateWindowEx(0, "button", "确定",
                                    WS_CHILD | WS_VISIBLE |  BS_DEFPUSHBUTTON | WS_TABSTOP, // | WS_DISABLED
                                    66, // xpos
                                    151, // ypos
                                    75, //width
                                    25, //height
                                    hwnd_dialog_four_squares, (HMENU) IDOK, hThisInst,  NULL);  /** IDOK: 表示这个按钮是当前窗口中的默认按钮, 按下 【回车键】 触发 **/
    
    
    CreateWindowEx(0, "button", "取消",
                                        WS_CHILD | WS_VISIBLE | WS_TABSTOP,  // | WS_DISABLED
                                        165, // xpos
                                        151, // ypos
                                        75, //width
                                        25, //height
                                        hwnd_dialog_four_squares, (HMENU) IDCANCEL, hThisInst,  NULL);  /** IDCANCEL: 表示这个按钮是当前窗口中的【取消按钮】, 按下 【ESC】 触发 **/
    dialog_init(hwnd_parent_frame, lpData);
    
    SendMessage(hwnd_b_cancel, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); //如果上一次用户点了【取消】按钮,再次显示窗口的时候,这个【取消】按钮会有边框, 重置一下状态
    SendMessage(hwnd_b_ok, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); //设置【默认按钮】样式
    while (GetMessage(&msg, NULL, 0, 0)) 
    {
            /*
    
            提示: IsDialogMessage() + WS_TABSTOP 就可以让窗口上每一个带 WS_TABSTOP 样式的控件自动获取焦点
    
            ------------------------------------------------------------------------------------------------------------------------
    
            IsDialogMessage() 资料: https://docs.microsoft.com/zh-cn/windows/desktop/api/winuser/nf-winuser-isdialogmessagea
    
            尽管 IsDialogMessage 函数适用于无模式对话框,但您可以将其用于包含控件的任何窗口,从而使窗口能够提供与对话框中使用的相同的键盘选择。
    
            当 IsDialogMessage 处理消息时,它会检查键盘消息并将其转换为相应对话框的选择。例如,按下TAB键时,选择下一个控件或一组控件,按下DOWN ARROW键,选择组中的下一个控件。
    
            由于 IsDialogMessage 函数执行所有必要的消息转换和分派,因此不能将 IsDialogMessage 处理的消息传递给 TranslateMessage 或 DispatchMessage 函数。
    
            */
            if(IsDialogMessage(hWnd, &msg))
            {
                 // 由对话管理器自动处理
    
                 /** Tab 键自动切换焦点, BS_DEFPUSHBUTTON (默认按钮) 等工作在这里自动完成。 **/
            }
            else
            {
                TranslateMessage(&msg);
    
                DispatchMessage(&msg);
            }
    }

    如果窗口中有多个嵌套子窗口,在 Tab 键切换焦点的时候,需要给子窗口的父窗口设置为:WS_EX_CONTROLPARENT,相关资料:https://stackoverrun.com/cn/q/338463

    CreateWindowEx(WS_EX_CONTROLPARENT, "static", "",
                                          WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
                                          221,   // xpos
                                          101,  // ypos
                                          60, //width
                                          22, //height
                                          hwnd_dialog_four_squares, (HMENU) NULL,   hThisInst,   NULL);
  • 相关阅读:
    Django各个文件中常见的模块导入
    js模板(template.js)实现页面动态渲染
    Netty 源码 Channel(一)概述
    Netty 源码 NioEventLoop(三)执行流程
    Netty 源码(一)Netty 组件简介
    Netty 源码(二)NioEventLoop 之 Channel 注册
    Java 算法(一)贪心算法
    Netty Reator(三)Reactor 模型
    Netty Reator(二)Scalable IO in Java
    Reactor 模型(一)基本并发编程模型
  • 原文地址:https://www.cnblogs.com/personnel/p/9416393.html
Copyright © 2020-2023  润新知