WinX教程之我的实战(四)

我们已经慢慢可以用WINX做点小东西了。今天介绍的是WINX一个非常重要的特性——用户自定义控件。由于WINX在界面库中保留了窗口类这个概念,使得可以直接利用现在的IDE工具进行可视化开发。这次实战我们就要试试用户自定义控件的使用。


这次实战涉及超类概念,补充说一下:我们都听过子类化(Subclass),听过超类化(Superclass)要少一些。子类化最常见的应用就是我们在MFC中,派生一个控件类,更改它的行为。这里其实是修改了控件(一种窗口,当然)的窗口函数。而超类从开始就是不一样的,它自己注册了窗口类,当然窗口函数作为窗口类的一个成员也可以被更改。简单的说,超类化,我们可以做的更多。详细信息请参见xushiwei博客上的文章


本套教程实例共含有三个例子:

 

其中BasicCtrl讲述基本的用户自定义控件,它告诉我们如何自定义控件;Superclass讲述对已有控件进行超类化;而SuperDialog更是将对话框当成了控件处理,听起来是不是很有趣?我们还是一步一步来。


自定义控件

WinX自定义控件非常的简单,定义一个类(从最基本的Window类派生)就可以了,如下:

class CMyCtrl : public winx::Window< CMyCtrl >

{

WINX_CLASS(“MyCtrlClass”);

};

注意上面粗写的宏,该宏的作用就是“声明”一个名叫“MyCtrlClass”的窗口类,之所以称之为“声明”,是因为待会我们还需要注册这个窗口类,就像SDK程序中一样,不过你不用担心,一切都是那么自然和简单。


按:也许这里称之为为“定义”比较合适。称呼什么不重要,我们所要做的,就是在定义控件时,加上这个宏,并指明窗口类名。


我们既然定义了窗口类,那么我们还需要指定这个窗口类的窗口函数(不了SDK程序的人,可以查查窗口类的结构定义)。当然,我们不会像SDK程序那样定义窗口函数,我们需要做的只是定义相应的消息处理函数,比如要拦截WM_PAINT消息,我们就只需定义OnPaint函数就可以了。


消息处理函数一般都会有一个窗口句柄,这个句柄所指就是收到这个消息的窗口。


就像BasicCtrl中定义的一样:

class CMyView : public winx::Window<CMyView>

{

WINX_CLASS("MyView");


public:

VOID OnPaint(HWND hWnd)

{

winx::PaintDC dc(hWnd);

dc.TextOut(1, 1, _T("Hello, WINX!"));

}

};


这样CMyView就指代了以“MyView”为窗口类名的一类控件。这个控件可以处理其WM_PAINT消息,它会在收到WM_PAINT消息后,输出字符“Hello, WINX!”


超类化控件

超类化可以使我们利用现有成果。上一例中,我们是我们自定义控件也是要从其他类派生的,而这一例——超类化,我们直接从现有控件类派生,然后修改窗口类就可以了。从这个意义上讲,上一例——自定义控件是一种特殊的“超类化”,从最一般窗口上超类化。


那么我们如果要从现有控件上超类化,写法上和上例BasicCtrl相同,只是换个基类而已,如下:

class CMyCtrl : public winx::Edit< CMyCtrl >

{

WINX_CLASS(“MyCtrlClass”);

};


这样我们仍然自定义了一个控件,但我们利用了以前的“轮子”,这样做有什么好处呢?好处就是:我们没有拦截或修改的界面/行为,它默认就采用原控件的界面/行为。这一点好像和MFC中的子类化很像,这个问题留作后来再说。


我们看看例子Superclass中是如何超类化控件的:

class CMyEdit2 : public winx::Edit<CMyEdit2>

{

WINX_CLASS("MyEdit");

public:

VOID OnContextMenu(HWND hWnd, winx::CPoint pt)

{

//什么也不做,那就等于屏蔽了右键菜单

}

};


有一点和子类化不同的是,我们这里的控件自己拥有自己的窗口类,而不像子类化时,我们只是替换了那个“类”的窗口函数。换句话说,我们的超类化控件虽然和原控件(也许)长得像,但它们二者的地位是并列的,处于同一层次。我们都是有名字的,谁怕谁啊?


可视化与资源文件

我们一直只是在讨论代码,虽然提到了可视化开发和对话框资源ID,但我们还没有讲讲资源文件。让我们看看例子中的资源文件是什么样子,看看第一个例子BasicCtrl

在对话框上drag(不想说“拉”)了一个自定义控件,并对它的属性进行了编辑,设置其Class属性(鼠标指向的位置)为“MyView”,这正是例子BasicCtrl中定义并注册的窗口类。经过这么一设置,我们就将这一对话框上的自定义控件和我们的自定义控件类连接在一起,自定义控件的行为/界面由我们定义的类控制。


超类化对话框

对话框不同于控件,一般的理解是,对话框是种容器(Container),上面可以放置控件。而有了超类化,这种理解发生了改变。因为我们可以基于已有的对话框,重新定义一种“类”。这种“类”和我们上面介绍的超类化控件没有任何区别。那么也就是说,我们可以把新定义的这种 “对话框控件”当作普通控件来用,即放置到对话框上。


有点绕,让我们先看看如何定义超类化的对话框类,和上例Superclass类似,只是把基类换成了对话框类,如下:

class CMyCtrl : public winx:: ModalessDialog< CMyCtrlIDD_MYCTRL >

{

WINX_CLASS(“MyCtrlClass”);

};

ModalessDialog类是WINX内部定义的无模式对话框,要做别的对话框上的控件,只能是无模式对话框,要是换成ModalDialog是要出错的。


注意:派生时多了一个参数,就是IDD_MYCTRL,它就是我们超类化对话框的资源ID。对话框嘛,需要它。


超类化的对话框同样可以处理自己上控件的消息,看看例子SuperDialog中的代码:

class MyDialog : public winx::ModalessDialog<MyDialog, IDD_MYVIEW>

{

WINX_CLASS("MyDialog");

WINX_CMDS_BEGIN();

WINX_CMD(ID_HELP_ABOUT, OnCmdAbout);

WINX_CMDS_END();

public:

VOID OnCmdAbout(HWND hWnd)

{

winx::MsgBox(hWnd, _T("Insert dialogs into another dialog as child controls!"), _T("SuperDialog"));

}

};


对话框做控件,这简直太奇妙了,


需要注意的是,当我们为我们的超类化对话框设置资源(资源文件)时,我们需要将其风格属性设置为Child窗口,并将边框最好(建议)设置为Thin或者None(这取决于你和你的客户的审美观)。如图:

注意:超类化对话框的资源文件中,其对话框资源中,也和自定义控件和超类化控件一样,drag一个自定义控件,然后将Class属性设置为我们代码中注册的那个窗口类的名字即可。 记得要将资源文件中的要超类化的那个对话框的Visible属性选中哦。J


注册窗口类

刚才我们讲三个例子时都没有讲一个很重要的问题:我们只是“定义”了窗口类,而没有进行注册。我们都知道没有注册的窗口类,系统是不“认识”的,我们也就不能用。所以我们需要在使用自定义控件前,对其窗口类进行注册,一个不错的位置是主程序开始执行:

MyDialog::RegisterClass();

看看例子中的位置。


WinX通用控件

下图摘自WinX附带文档WinxPreview.ppt中:

如果你想基于某个通用控件进行超类化,可以选择上图中的控件。WinX通用控件和Windows通用控件接口一致,由于接口太多,这里就不一一列出了,需要用到哪个具体的控件,可以到这里查询,:)。


实战一下

功能定义:

在对话框上放置一个自定义控件、一个基于Button的超类化控件(左键可以拖动)和一个超类化的对话框,这个超类化的对话框中放置一个Button,单击后(命令消息)弹出一个对话框。


步骤和上篇BLOG中介绍的类似。这次你可以自己做做,然后下载代码和我的比对一下,看看有什么地方一样和什么地方不一样。代码下载。上篇BLOG最后留下了一个问题,就是看看界面上有什么问题?这里说一下,就是在将所有控件的背景色设置为透明后,Button的表面的颜色没有变,不像Static。因为对于Button,按钮上不算是它的背景,:)。

似乎好像大概也许可能我的代码里有个bug,你发现了吗?如何解决?

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值