`
in355hz
  • 浏览: 230083 次
社区版块
存档分类
最新评论

浅谈 MFC 的子类化机制和该机制的一个应用(1)

MFC 
阅读更多

浅谈 MFC 的子类化机制和该机制的一个应用

众所周知:

afx_msg int CWnd::OnCreate( LPCREATESTRUCT lpCreateStruct );

 

是一个经常被重载的 MFC 窗体函数,他负责处理窗体的 WM_CREATE 消息,这个消息的发送时机在窗体刚刚创建以后, CreateWindow(Ex) 返回之前。

 

可以发现在 MFC 里,系统控件和对话框也可以得到这个消息,例如 CEdit CPrintDialog CFileDialog ,他们内部调用 CreateWindowEx PrintDlg GetOpen Save FileName 完全掩盖了窗体创建的过程,这些函数返回时,窗体已经收到过 WM_CREATE 消息而且不会得到第二次通知。

 

因此,为了得到这些窗体的 WM_CREATE 通知,必须采用有点特殊的方法,能够在 CreateWindowEx 返回之前就替换掉窗体的 WindowProc

 

使用 WH_CBT 钩子是不错的选择。当一个窗体产生, CBTProc 会在 WindowProc 收到 WM_CREATE 之前得到 HCBT_CREATEWND 通知,如果此时子类化窗体,就能在子类化后的窗体过程中得到 WM_CREATE 通知。

 

MFC 的做法和这类似:

void AfxHookWindowCreate( CWnd *pWnd );

 

负责安装 WH_CBT 钩子,其参数 pWnd 指向一个创建中的 CWnd 实例, MFC 通过某种全局变量把这个实例的指针传给执行中的 CBTProc


BOOL AfxUnhookWindowCreate();

 

它卸下 WH_CBT 钩子,并且复原 AfxHookWindowCreate 改变过的 MFC 全局状态 消息。

LRESULT CALLBACK _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam);

 

这个就是 MFC 安装的 CBTProc 回调。他只处理 HCBT_CREATEWND 通知,然后 Attach 之前得到的 CWnd 实例到正在创建的窗体句柄、替换掉窗体的 WindowProc ,最后 CallNextHookEx

 

现在来考虑如何应用 MFC 给我们提供的这个便利。 AfxHookWindowCreate AfxUnhookWindowCreate 之间创建的第一个非 IME (输入法)窗体可以被所给的 CWnd 实例子类化。我们可以这样调用一些 API ,把自己的 CWnd 实例与 API 创建的窗体连结起来,如果我给的是一个 CWnd 派生类的实例,重载过的消息就可以改变原有窗体的行为。以下的代码示例如何按照这样的思路创建一个带 Dump 输出的 MessageBox

 

class CDumpMsgBox : public CWnd

{

DECLARE_DYNAMIC(CDumpMsgBox)

 

// Constructors

public:

CDumpMsgBox();

 

// Attributes

public:

CEdit m_editDump; // Dumping edit control added to the message box.

 

CMemFile m_fileDump; // Dumping context's target file.

 

CDumpContext m_dumpContext; // The dump context object.

 

// Operations

public:

int DoMessageBox(UINT nIDPrompt, UINT nType = MB_OK, UINT nIDHelp = (UINT)-1);

 

AFX_INLINE CDumpContext& GetDumpContext() { return m_dumpContext; };

 

AFX_INLINE void RemoveAll() { m_fileDump.SetLength(0); };

 

// Implementations

public:

virtual ~CDumpMsgBox();

 

virtual void DoDumpObject(CObject* pDumpObject);

 

virtual int DoMessageBox(LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0);

 

#ifdef _DEBUG

virtual void AssertValid() const;

 

virtual void Dump(CDumpContext& dc) const

#endif

 

protected:

virtual BOOL OnDumpOut(LPSTR pszDumpBuffer, UINT nBufferSize);

 

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CChildFrame)

//}}AFX_VIRTUAL

 

// Generated message map functions

protected:

//{{AFX_MSG(CMainFrame)

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

// NOTE - the ClassWizard will add and remove member functions here.

// DO NOT EDIT what you see in these blocks of generated code!

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

 

// Identify of the edit control CDumpMsgBox::m_editDump.

#define IDC_DUMPMSGBOX_EDITBOX 1047

 

//////////////////////////////////////////////////////////////////////

// CDumpMsgBox

 

IMPLEMENT_DYNAMIC(CDumpMsgBox, CWnd)

 

BEGIN_MESSAGE_MAP(CDumpMsgBox, CWnd)

//{{AFX_MSG_MAP(CWnd)

// NOTE - the ClassWizard will add and remove mapping macros here.

// DO NOT EDIT what you see in these blocks of generated code !

ON_WM_CREATE()

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

////////////////////////////////////////////////////////////////////////////

// CDumpMsgBox construction/destruction

 

CDumpMsgBox::CDumpMsgBox() : m_fileDump(512),

m_dumpContext(&m_fileDump)

{

m_fileDump.AssertValid();

 

m_dumpContext.SetDepth(1);

m_dumpContext << "Dump From Objects: \r\n========================================\r\n";

}

 

CDumpMsgBox::~CDumpMsgBox()

{

BYTE* pszDumpBuffer = (BYTE*)m_fileDump.Detach();

 

if (pszDumpBuffer)

free(pszDumpBuffer);

 

m_dumpContext.m_pFile = NULL;

}

 

////////////////////////////////////////////////////////////////////////////

// CDumpMsgBox Implementations

 

int CDumpMsgBox::OnCreate(LPCREATESTRUCT lpcs)

{

if (CWnd::OnCreate(lpcs) == -1)

{

TRACE0("CDumpMsgBox::OnCreate error: call CWnd::OnCreate return FALSE.\n");

return -1;

}

 

CRect rectBox;

 

GetWindowRect(&rectBox);

 

// adjust message box sizes to fill a dump edit control.

if (rectBox.Width() < 350)

rectBox.right = rectBox.left + 350;

 

rectBox.bottom += 130;

 

MoveWindow(&rectBox, FALSE);

 

// create edit control to display dump texts

ScreenToClient(&rectBox);

 

CRect rectEdit(rectBox.left + 8, rectBox.bottom - 132,

rectBox.right - 8, rectBox.bottom - 8);

 

if (!m_editDump.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP |

ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL,

rectEdit, this, IDC_DUMPMSGBOX_EDITBOX))

{

TRACE0("CDumpMsgBox::OnCreate error: m_editDump.Create return FALSE.\n");

 

return -1;

}

 

// set WS_EX_CLIENTEDGE style to edit control (let it has a drop edge)

m_editDump.ModifyStyleEx(0L, WS_EX_CLIENTEDGE,

SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);

 

// set edit control's font to DEFAULT_GUI_FONT.

CFont Font;

 

Font.Attach((HFONT)GetStockObject(DEFAULT_GUI_FONT));

 

m_editDump.SetFont(&Font);

 

// write end-dump text and flush all data to file

m_dumpContext << "\r\n========================================\r\nDump End";

m_dumpContext.Flush();

 

m_fileDump.Write("\0", sizeof(CHAR));

 

UINT nBufferSize = m_fileDump.GetLength();

 

LPSTR pszDumpBuffer = (LPSTR)m_fileDump.Detach();

 

if (!OnDumpOut(pszDumpBuffer, nBufferSize))

{

TRACE0("CDumpMsgBox::OnCreate error: OnDumpOut return FALSE.\n");

 

m_fileDump.Attach((BYTE*)pszDumpBuffer, nBufferSize, 512);

 

return -1;

}

 

// attach used dump buffer for next dump.

m_fileDump.Attach((BYTE*)pszDumpBuffer, nBufferSize, 512);

 

return 0;

}

 

未完,剩余部分请参考 浅谈 MFC 的子类化机制和该机制的一个应用( 2 )。

 

分享到:
评论

相关推荐

    走出MFC子类化的迷宫子类化,SUBCLASSWINDOW ,MFC消息机制

    在这篇文章中,我们将深入探讨 MFC 子类化机制的原理和实现方式,并提供一个实际的示例来演示如何使用子类化机制来实现一个只能输入 A、B、C 的 EDIT 控件。 什么是 Windows 子类化? -------------------- 在 ...

    走出MFC子类化的迷宫

    MFC提供了`SubclassDlgItem`函数,它允许你将一个MFC控件类与对话框中的控件ID关联起来,自动完成子类化过程。例如,我们创建一个派生自CEdit的自定义控件类`CSuperEdit`,并在其中覆盖`OnChar`消息处理函数,以便...

    vc++6.0 MFC 窗口子类化

    在VC++ 6.0中,MFC(Microsoft Foundation Classes)是一个强大的库,它为Windows应用程序开发提供了便利。MFC库基于面向对象的设计,简化了Windows API的使用,使得开发者可以更加专注于业务逻辑而非底层系统调用。...

    mfc_子类化+双缓冲

    例如,如果要对一个标准按钮进行子类化,首先创建一个继承自`CButton`的自定义类,然后在运行时调用`SubclassWindow`函数,传入要子类化的窗口句柄: ```cpp CMyButton myButton; myButton.SubclassWindow(HWND_of_...

    子类化 超类化 技术分析

    在MFC库中,子类化和超类化被广泛应用于窗口类和控件类的设计。例如,MFC提供了CWnd类作为所有窗口类的基类,开发者可以通过子类化CWnd来创建自定义的窗口类。在子类中,可以重写CWnd的成员函数以实现特定的功能,如...

    MFC和QT的子类化与常用控件1

    总的来说,无论是MFC还是Qt,子类化控件都是一种增强控件功能的有效手段,而这两者都提供了丰富的控件和API,使得开发者能够轻松创建出符合需求的用户界面。在实际开发中,可以根据项目的具体需求和技术栈来选择合适...

    我收集的MFC资料,包括子类化,消息映射机制,MFC关键技术,常用数据转化

    1. **子类化**:在Windows编程中,子类化是指一个窗口类继承另一个窗口类的行为,通常是为了扩展或修改默认的行为。MFC通过`ON_WM_*`宏来实现窗口消息的子类化,使得你可以定制控件的事件处理。`MFC的子类化技术.doc...

    MFC的消息机制的实现原理和消息处理的过程

    - 这个宏为类定义了私有成员变量`_messageEntries`,这是一个静态数组,用于存储消息映射表中的元素。此外,还定义了`GetMessageMap()`成员函数,该函数返回消息映射表的指针。 2. **消息映射的实现**: - 在类的...

    深入浅出MFC 深入浅出MFC 深入浅出MFC

    此外,还会讲解如何创建一个基本的MFC应用程序,以及事件处理机制。 2. **dissecting MFC 2e part2.pdf**:这一部分可能会深入到窗口类和控件的使用,如CWnd、CFrameWnd、CMDIChildWnd等,以及标准控件如按钮、编辑...

    深入浅出MFC 深入浅出MFC之初始化过程 Visual Studio 2008版

    《深入浅出MFC》是一本专注于Microsoft Foundation Classes (MFC) 库的权威书籍,旨在帮助开发者深入了解和熟练运用MFC进行Windows应用程序开发。在Visual Studio 2008环境下,MFC提供了丰富的类库和工具,简化了C++...

    MFC序列化应用示例

    4. **子类化CDocument和CDocumentView**:在MFC应用程序框架中,通常会有一个CDocument类代表数据,一个CView类用于显示数据。这两个类也需要支持序列化。在CDocument中,你需要重写OnNewDocument和OnOpenDocument...

    Windows-MFC程序-07.MFC序列化机制和序列化类对象

    在Windows编程领域,MFC...总之,MFC的序列化机制为开发人员提供了便捷的方式来持久化和恢复对象状态,是构建Windows应用程序的重要组成部分。通过理解并熟练掌握这一机制,我们可以创建更强大、更灵活的应用程序。

    MFC消息响应机制分析

    CCmdTarget 类提供了一个基本的消息处理机制,允许派生类来重写消息处理函数。这样,程序员可以方便地处理 Windows 的各种消息,并实现更加灵活和高效的程序。 小结 MFC 的消息响应机制是 Windows 下程序设计中最...

    深入浅出MFC

    MFC是微软公司开发的一个C++类库,它为Windows应用程序开发提供了强大的支持,使得开发者能够更容易地利用Windows API进行编程。侯俊杰作为本书的作者,以其深厚的编程经验和对MFC的独到理解,为读者呈现了一部全面...

    深入浅出.MFC

    接着,书中会详细讲解MFC的文档/视图模型,这是MFC应用程序设计中的一个重要概念。通过这个模型,开发者可以将数据存储和显示逻辑分离,使得代码更加模块化。同时,还会涉及对话框、控件、菜单、工具栏、状态栏等...

    深入浅出MFC--侯捷 深入浅出MFC--侯捷 深入浅出MFC--侯捷

    MFC是微软公司开发的一个C++类库,它封装了Windows API,为开发者提供了一种更加面向对象的方式来编写Windows应用程序。本书旨在帮助读者理解和掌握MFC的核心概念、设计模式以及实际应用技巧。 在MFC中,最重要的...

    深入浅出MFC(PDF)

    MFC是微软公司提供的一个C++类库,它封装了Windows API,使得开发者能用面向对象的方式来编写Windows应用程序。这本书深入剖析了MFC的设计原理和实现机制,旨在帮助读者掌握MFC的核心概念和实践技巧。 1. MFC基础 ...

    深入浅出mfc

    1. **MFC框架**:MFC提供了一个事件驱动的编程模型,它包含了消息映射机制。当用户在界面上进行操作时,Windows会产生消息,MFC框架通过消息映射将这些消息转发到相应的处理函数。这简化了对用户输入的响应和处理。 ...

Global site tag (gtag.js) - Google Analytics