科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Windows精解:超类与子类

Windows精解:超类与子类

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

子类化(Subclass)是指替换窗口过程(WNDPROC)。 超类(Superclass)是替换窗口过程

作者:许式伟 来源: CSDN 2008年1月3日

关键字: 子类 超类 Windows

  • 评论
  • 分享微博
  • 分享邮件

超类与子类(Superclass & Subclass)

Q: 我看了WINX开发包中的文档中,你提到了超类,它是什么概念?我平常只听过子类(Subclass)。

A: 子类化(Subclass)是指替换窗口过程(WNDPROC)。
    超类(Superclass)是替换窗口过程(WNDPROC),并且替换ClassName。
   Subclass不太象继承,而像是一种外挂(Hook)行为。
   Superclass则更像继承,因为生成了新的窗口类,并且继承了行为。
   winx中Subclass和Superclass用同一个类实现。都是winx::SubclassWindow。
   其他界面库一般不提供Superclass。
  
Q: 你说其他界面库不提供Superclass?MFC里继承应该属于Superclass吧?

A: 不,MFC中用的是Subclass。

Q: 我怎么感觉不出二者的区别?我是说用法上和结果上。

A: 两者在用法上有异,但获得的结果确实无太大差别。
   我们以Button为例。如果是Subclass,那么用户先要有一个Button,然后Subclass它。
   也就是说Subclass发生在CreateWindow之后。
   如果是Superclass,那么用户CreateWindow的时候直接传入新的窗口类名称,根本就没有Button被生成。
   当然,这要求CreateWindow之前调用过该窗口类的RegisterClass。
   MFC用的是Subclass。因为CButton类通过DDX技术和对话框上的Button关联的。
   也就是说,MFC中是先有了Button,然后由DDX技术Subclass它。
   所以,一般你看不到Subclass流程。
  
Q: 什么情况下需要用SuperClass?
   哦,我明白了,是不是有了SuperClass技术,用户可以很方便的创建自己的Control?
  
A: 对了。不需要从零开始。

Q: 对。感觉多数用户自定义控件还是和系统控件有关系的。

A: 是的。这正是Superclass存在的意义。
   你可以想象一下:在以前,你提供一个控件,你要告诉它,先创建Button,然后调用我的Subclass函数。
   而有了Superclass,现在你只需要告诉它窗口类的名字就可以了。
   因为Superclass隐蔽了你从Button继承这个事实。
  
Q: 对。

A: 之所以winx可以有superclass而其他界面库没有,究其原因,还是与屏蔽“窗口类”这个出发点有关。

Q: 对,对,对。以后自己定义的控件也可以可视化开发。

A: 是的。

Q: 指定一下我们自己的窗口类就可以了。
   WINX这种控件感觉是介于系统控件和ActiveX控件之间的一种控件。

A: 是的。这种控件其实就是Windows系统控件的实现方式。
   只是系统控件不需要你主动注册,Windows已经帮你注册好了。
  
Q: 系统实现这些系统控件不是通过SuperClass吧?它应该是从最一般化的窗口继承而来。

A: 呵呵,当然不是。它们没有什么可以借用的,只好从最基础的winx::Window继承。

Q: 不管是白手起家,还是有点基础,做法都是SuperClass。
   因为winx::Window的基础是DefWindowProc,也是一个窗口过程。
  
A: 可以这么理解。

Q: 是不是可以这样理解,SubClass只是更改了WndProc,而SuperClass还更改了其他窗口属性?

A: 是的。你的理解完全正确,这正是Subclass与Superclass最本质的区别。
   Superclass可以改窗口类(WNDCLASSEX)的任何数据。WINX就是这么实现的。

附录

样例参见:

tutorials/winx/step004-user-ctrl/2.superclass/hello.cpp

子类化样例代码:

// -------------------------------------------------------------------------
// class CMyEdit - 使用子类化(Subclass)技术

class CMyEdit : public winx::Edit<CMyEdit>
{
public:
    VOID OnContextMenu(HWND hWnd, winx::CPoint pt)
    {
        
//禁止了右键菜单...
    }
};

// -------------------------------------------------------------------------
// CHelloDlg

class CHelloDlg : public winx::ModalDialog<CHelloDlg, IDD_HELLO>
{
public:
    BOOL OnInitDialog(HWND hDlg, HWND hWndDefaultFocus)
    {
        CMyEdit::DoSubclassDlgItem(hDlg, IDC_EDIT1);
        
return TRUE;
    }
};

// -------------------------------------------------------------------------

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     
int       nCmdShow)
{
    CHelloDlg dlg;
    dlg.DoModal();
    
return 0;
}

// -------------------------------------------------------------------------

超类化样例代码:

// -------------------------------------------------------------------------
// class CMyEdit2 - 使用超类化(Superclass)技术

class CMyEdit2 : public winx::Edit<CMyEdit2>
{
    WINX_CLASS(
"MyEdit");
public:
    VOID OnContextMenu(HWND hWnd, winx::CPoint pt)
    {
        
//禁止了右键菜单...
    }
};

// -------------------------------------------------------------------------
// CHelloDlg

class CHelloDlg : public winx::ModalDialog<CHelloDlg, IDD_HELLO>
{
};

// -------------------------------------------------------------------------

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     
int       nCmdShow)
{
    CMyEdit2::RegisterClass();
    CHelloDlg dlg;
    dlg.DoModal();
    
return 0;
}

// -------------------------------------------------------------------------
查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章