65.9K
CodeProject 正在变化。 阅读更多。
Home

MFC 停靠框架

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.37/5 (19投票s)

2007年10月12日

CPOL

3分钟阅读

viewsIcon

126089

downloadIcon

5347

易于使用的 MFC 停靠框架等等...它还展示了一种混合 WTL 和 MFC 的适用方法。

目录

屏幕截图

简介

一个漂亮的 UI 是一个好的应用程序的重要组成部分,除此之外还有其他标准,例如性能、稳定/可靠性...就个人而言,我非常喜欢 CodeProject 很久以前发布的以下库。

这些列出的库是用 WTL 编写的。但是,将 MFC 和 WTL 混合在一起非常困难。显然,要求开发人员或团队放弃 MFC 并迁移到 WTL 世界是不合理的,仅仅因为有一些用 WTL 编写的优秀控件或视觉框架(有很多因素需要考虑,尤其是在像我工作的公司这样拥有数百名开发人员的公司)。不幸的是,直到现在 MFC 中还没有这样好且免费的视觉框架。无论有什么困难,我仍然希望能够使用它们,现在我的努力与您分享。

幕后

技术决策

有两种可能的方案

  1. 完全移植 WTL 源代码到 MFC:这种方法存在一些问题。首先,这需要我花费大量时间(仅仅是为了重写别人已经做过的事情)。其次,原始作者的错误修复和增强将无法及时更新。第三,如果有一天发布了另一个好的针对 WTL 的库,我将不得不再次移植。考虑到这些原因,我决定不采取这种方向。
  2. 混合 MFC 和 WTL:我知道这种方法有很多问题,正如文章 混合 WTL 与 MFC 的论坛中所显示的。由于我无意拥有一个通用的方法来集成所有(现在和未来)针对 WTL 的库,而仅仅是为了上面列出的这些库,我相信这是可能的。

它是如何工作的?

这是 MFC 包装器的核心

template<class TMFCWnd, class TWTLCWindow>
class ATL_NO_VTABLE CWTL4MFCWndT : public TMFCWnd
{
public:
    typedef TWTLCWindow WTLClass;
    WTLClass m_wndWTLPeer;

    virtual void PreSubclassWindow()
    {
        m_wndWTLPeer.m_hWnd = m_hWnd;
        __super::PreSubclassWindow();
    }

    virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
    {
        LRESULT lResult = 0;
        if(FALSE == m_wndWTLPeer.ProcessWindowMessage
            (m_hWnd, nMsg, wParam, lParam, lResult))
        {
            ASSERT(::IsWindow(m_hWnd));
            lResult = TMFCWnd::WindowProc(nMsg, wParam, lParam);
        }
        return lResult;
    }

    __if_exists(TWTLCWindow::PreTranslateMessage) {
    virtual BOOL PreTranslateMessage(MSG* pMsg)
    {
        BOOL blRes1 = __super::PreTranslateMessage(pMsg);
        BOOL blRes2 = m_wndWTLPeer.PreTranslateMessage(pMsg);

        // if both WTL & MFC handle this message

        // there maybe a problem, consider to override 

        // this method in derived class

        ASSERT(FALSE == (blRes2 && blRes1));

        return (blRes1 | blRes2);
    }}
};

没什么可说的;对于每个窗口消息(WM_xxx),如果相应的 WTL 对等体不处理它,MFC 包装器就会处理。

潜在问题

当 WTL 对等体处理了窗口消息(WM_xxx)(从 ProcessWindowMessage 返回 TRUE)但该消息对 MFC 框架也很重要时,就会出现问题。为了解决这个问题,我选择了一个非常简单的方法:**逐个进行测试和解决**。

使用代码

将此库应用于现有 MFC 项目很容易;以演示项目为例,作为您的起点。这是类图供快速参考。

支持的编译器

  • Visual Studio 2003
  • Visual Studio 2005 - 由于此编译器版本中的一些更改,请将预编译头内存分配限制设置为 200 或更高值,以避免错误 C3859。

错误修复和更新

  • 基本上,一个错误或一个功能请求可能属于这个 MFC 包装器(1),或者原始 WTL 代码(2),或者两者兼有(3)。我将尝试修复属于类别(1)和(3)的错误,并将其他错误转交给相应的作者(我将尽量不触碰 WTL 代码,除非确实有必要,当然,需要征得原始作者的同意)。
  • 由于该库只是一个包装器,请记住也要从其他作者那里获取更新,并从WTL 库获取更新。

致谢

我想感谢 Daniel BowenSergey KlimovIgor Katrayev 为他们出色的 WTL 库。也感谢他们同意允许我在本文中重新分发他们的源代码(稍作修改)。

历史

  • 2007 年 10 月 12 日:初始版本
© . All rights reserved.