WinX教程之我的实战(三)

来源:互联网 发布:北京音像大厦 知乎 编辑:程序博客网 时间:2024/05/18 03:03

今天我们来看看第三套教程实例——step003-commandWinX是越来越有意思了,通过这套实例,我们就已经可以处理命令消息。

 

命令消息

如果你用过MFC,那么你一定知道什么叫命令消息。说的通俗点,命令消息就是和控件、菜单相关的消息,一般命令消息都会和一个ID相关,即控件ID或者菜单的一个条目的ID,也由ID区分不同的命令消息。

 

实例中用到的命令消息处理宏

在实例CmdDisp中用到了:

l         WINX_CMDS_BEGIN

l         WINX_CMD

l         WINX_CMDS_END

 

用法是在类定义中,如这样写:

 

 

WINX_CMDS_BEGIN();
    WINX_CMD(IDC_TODO, OnCmdTodo);
    WINX_CMD(ID_HELP_ABOUT, OnCmdAbout);
WINX_CMDS_END();

 

WINX_CMD带有两个参数,前一个是控件ID,后一个是拦截此命令消息的函数。当该控件被单击时,就调用后一个函数。

 

我们在定义消息处理函数名前用到了winx_msg宏,winx_msg宏的定义如下:

  

#define winx_msg    winx_call

 

winx_call的定义如下:

  

#define winx_call   __fastcall

 

__fastcall是另一种不同于__cdecl__stdcall的函数调用规范,它速度快,使用寄存器来传递参数。要知道详细信息,可以网上搜索。不过我们不用关心它,我们只要在定义消息处理函数名前加上winx_msg宏就可以了。(注:WinX并不依赖于__fastcall,意思就是说,不写调用方式也可以)

 

在实例CmdState中用到了:

l         WINX_CMDS_BEGIN

l         WINX_CMD

l         WINX_CMDS_END

l         WINX_UPDATEUI_BEGIN

l         WINX_UPDATEUI

l         WINX_UPDATEUI_END

 

比第一个实例多了后面三个宏。用法就是在类定义中,如下这样写:

 

 

WINX_UPDATEUI_BEGIN()

       WINX_UPDATEUI(IDC_ALL, UPDUI_MENUPOPUP)

WINX_UPDATEUI_END();

 

引自WinX附带文件WinxPreview.ppt

l         WTL的命令状态维护机制不错,但是ModalDialog不完全支持该机制。主要的问题在于没有OnIdle消息。”

l         WINXUpdateUI基于WTL的命令状态维护机制实现,并作出改进。”

 

这一套消息用来维护命令状态,比如菜单某个条目状态(比如enable状态)改变了,可以自动更新。宏WINX_UPDATEUI带有两个参数,前一个是要维护命令状态的控件ID,后一个是界面元素类型。比如实例CmdState中,我们要更新的是菜单中的命令状态,那后一个参数就应该是UPDUI_MENUPOPUP

 

下面中列出了另外一些你可能会用到的界面元素类型:

界面元素类型

描述

UPDUI_MENUPOPUP,

菜单

UPDUI_MENUBAR

菜单条

UPDUI_CHILDWINDOW

子窗口

UPDUI_TOOLBAR

工具条

UPDUI_STATUSBAR

状态条

 

除此外,下面列出了一些命令状态及其设置/清楚状态的函数名:

状态

描述

设置/清楚函数

UPDUI_ENABLED

激活

UIEnable

UPDUI_DISABLED      

反激活

UPDUI_CHECKED

复选框

UISetCheck

UPDUI_CHECKED2     

有三种状态

UPDUI_RADIO

单选框

UISetRadio

UPDUI_TEXT

文本

UISetText

UPDUI_DEFAULT

默认按钮(对话框)

UISetDefault

 

UIEnable原型如下:

  

BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE);

 

 

UISetCheck原型如下:

 

BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE);
BOOL UISetCheck(
int nID, bool bCheck, BOOL bForceUpdate = FALSE);

 

前一个用于具有第三种状态(UPDUI_CHECKED2)的复选框,这时要求CheckBoxBS_3STATEBS_AUTO3STATE

 

UISetRadio原型如下:

  

BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE);

 

 

UISetText原型如下:

  

BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE);

 

 

UISetDefault原型如下:

  

BOOL UISetDefault(int nID, BOOL bDefault, BOOL bForceUpdate = FALSE);

 

 

其他WinX命令消息处理宏

WINX_CMDS_BEGIN_EX

WINX_CMD_EX

WINX_CMDS_END_EX

 

WINX_CMDS_BEGIN/END的区别是,如果消息自身没有处理,会发给活动的子视图处理。

 

其他问题

在实例CmdState中,还有三个地方需要提一下:

1

  

class CHelloDlg : 

       
public winx::ModalDialog<CHelloDlg, IDD_HELLO>,

       
public winx::UpdateUI<CHelloDlg>

 

当我们需要进行命令状态维护时,我们的类(窗口,对话框),需要添加另一个基类winx::UpdateUI<CHelloDlg>

2 

  

BOOL OnContextMenu(HWND hWnd, winx::CPoint pos)
{
       winx::PopupMenu(hWnd, pos.x, pos.y, IDR_MAINMENU);

        
return TRUE;
}

 

 

在实战一中我们已经介绍过拦截系统消息时,只需定义相应函数就可以,不用写消息拦截代码。这里OnContextMenu就是处理系统消息WM_CONTEXTMENU的函数,即当右键单击对话框时。这里的操作是调用WinX内置函数PopupMenu,指定相应菜单资源ID,弹出菜单。

3

  

winx::SimpleDialog dlg;

dlg.DoModal(hWnd, IDD_ABOUT);

 

当我们只是需要一个简单对话框,即我们不需要拦截任何消息,只需要将相应的控件放好(资源文件,对话框设计器),直接像这里调用DoModal就可以了。一个区别是,这里的对话框资源ID是在DoModal函数中指定的,而非自己定义对话框时在模板参数中指定。

 

我们不妨实战一下

我们做一个简单的例子,利用一下我们学习前几个教程实例的成果。

功能:

1、  设定背景色为白色;

2、  设定窗口上所有控件背景色为透明;

3、  具有菜单和命令状态维护功能,用Check

4、  弹出右键菜单。

 

假设我们的项目名为Example3

步骤一:打开VC 6.0 英文版,:p

步骤二:利用Wizard创建Win32 Application,选择“A Simple Win32 Application”;

步骤三:添加资源文件,如下图,

步骤四:添加对话框,Insert即可,如下图:

(请高手们保持耐心,:))

之后选择对话框类别,New即可,生成对话框资源后,将对话框资源ID修改为IDD_MYEXAMPLE3。其他按钮控件我们一会再加。

步骤五:定义主窗口类(直接在主程序文件Example3.cpp定义中即可),我们的主窗口类是一个模式对话框,而且我们要做命令状态维护,所以别忘了要多加一个基类winx::UpdateUI,如下,

  

class CMyExample3Dlg : 
       
public winx::ModalDialog< CMyExample3Dlg, IDD_MYEXAMPLE3>,
       
public winx::UpdateUI< CMyExample3Dlg >

{

};

 

这里的IDD_MYEXAMPLE3就是我们刚才创建的对话框的资源ID

步骤六:添加其他资源,如菜单、按钮、静态文本框等,结果如下,

步骤七:添加代码。

将窗口背景设置为白色,代码为:

WINX_BKGND_BRUSH(WHITE_BRUSH);

将窗口上所有控件的背景设置为透明,代码为:

WINX_CTLBKGND_NULL_ALL();

设置右键菜单,代码为:

BOOL OnContextMenu(HWND hWnd, winx::CPoint pos)
{
       winx::PopupMenu(hWnd, pos.x, pos.y, IDR_MENU1_);

       
return TRUE;

}

 

拦截命令消息,并维护命令状态,代码如下:

WINX_CMDS_BEGIN();
WINX_CMD(IDM_ABOUTAPP, OnAboutApp);
WINX_CMD(IDM_ITEM1, OnItem1);
WINX_CMD(IDM_ITEM2, OnItem2);
WINX_CMD(IDM_UNCHECKALL, OnUnCheckAll);
WINX_CMDS_END();

WINX_UPDATEUI_BEGIN()
WINX_UPDATEUI(IDM_ITEM1, UPDUI_MENUPOPUP)
WINX_UPDATEUI(IDM_ITEM2, UPDUI_MENUPOPUP)
WINX_UPDATEUI_END();
public:
    VOID OnAboutApp(HWND hWnd)
    {
        winx::SimpleDialog dlg;
        dlg.DoModal(hWnd, IDD_ABOUTAPP);
    }

    VOID OnItem1(HWND hWnd)
    {
        UISetCheck(IDM_ITEM1, TRUE);
    }
    
    VOID OnItem2(HWND hWnd)
    {
        UISetCheck (IDM_ITEM2, TRUE);
    }
    VOID OnUnCheckAll(HWND hWnd)
    {
        UISetCheck (IDM_ITEM1, FALSE);
        UISetCheck (IDM_ITEM2, FALSE);
    }

 

 

 

步骤八:添加主程序代码,如下:

CMyExample3Dlg dlg;
dlg.DoModal();

 

运行结果:

注意1、不知大家注意没有,每个WINX_CMDS_xx宏后面都有分号,而并非每个WINX_UPDATEUI_xx宏有,只有最后一个WINX_UPDATEUI_END();有。2、对话框的主菜通过在资源中直接设定。

 

不知大家在上面运行结果图中发现什么问题没有?有奖问答!J

 

源代码下载

 

END

关于上面提到的分号“;”问题,咨询xushiwei后补充如下:

winx旧的习惯是所有的宏后加上;(如上面的WINX_CMD),而wtl的习惯是不带;(如上面的WINX_UPDATEUI是依赖wtl实现的), 这就就出现了不一致的情况。目前winx没有消除这种不一致。考虑到可能给用户造成困惑,winx决定在下一个release全部统一为不带;号。不过我们会兼容目前的文法,也就是说,winx的宏允许带不带;均可。

END AGAIN

原创粉丝点击