对MFC指手划脚(1)

我MFC没咋用过,虽然现在Java,C#等语言风头狠劲,Java,.Net平台也是逐渐取代Win32平台,但我认为,MFC也是有值得一学的必要,嗯,看在市场的面子上吧,明天我可是要去找工作了,:),

学win32 api + C++已经近2年,Delphi也有2个月了,相对于动则编程经验10年的老鸟来说,我可能连小鸟都算不上,没有任何VC项目的经验(Delphi的项目做过一些)。但初生牛犊不怕虎,但现在社会民风开放,在网络崇尚言论自由,我也想来言论自由一些。没有人敢说VC的不是,但提起MFC,大都说是垃圾,MFC是不是垃圾,最好要有真凭实据:正比如,你骂一个是笨蛋,还要拿出证据来说它是笨蛋!

嗯,从Delphi的TForm开始吧,在MFC中,与TForm类似的类有CView, CDialog, 先看看CView:
class CView : public CWnd
{
DECLARE_DYNAMIC(CView)

// Constructors
protected:
CView();                                       

// Attributes
public:
CDocument* GetDocument() const;

// Operations
public:
// for standard printing setup (override OnPreparePrinting)
BOOL DoPreparePrinting(CPrintInfo* pInfo);               

// Overridables
public:
virtual BOOL IsSelected(const CObject* pDocItem) const; // support for OLE

// OLE scrolling support (used for drag/drop as well)
virtual BOOL OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll = TRUE);
virtual BOOL OnScrollBy(CSize sizeScroll, BOOL bDoScroll = TRUE);


// OLE drag/drop support
virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject,
DWORD dwKeyState, CPoint point);
virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject,
DWORD dwKeyState, CPoint point);
virtual void OnDragLeave();
virtual BOOL OnDrop(COleDataObject* pDataObject,
DROPEFFECT dropEffect, CPoint point);
virtual DROPEFFECT OnDropEx(COleDataObject* pDataObject,
DROPEFFECT dropDefault, DROPEFFECT dropList, CPoint point);
virtual DROPEFFECT OnDragScroll(DWORD dwKeyState, CPoint point);


virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo = NULL);   

virtual void OnInitialUpdate(); // called first time after construct

protected:
// Activation
virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView);
virtual void OnActivateFrame(UINT nState, CFrameWnd* pFrameWnd);

// General drawing/updating
virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
virtual void OnDraw(CDC* pDC) = 0;                            

// Printing support
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
// must override to enable printing and print preview

virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnPrint(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// Advanced: end print preview mode, move to point
virtual void OnEndPrintPreview(CDC* pDC, CPrintInfo* pInfo, POINT point, CPreviewView* pView);

// Implementation
public:
virtual ~CView();
#ifdef _DEBUG
virtual void Dump(CDumpContext&) const;
virtual void AssertValid() const;
#endif //_DEBUG

// Advanced: for implementing custom print preview
BOOL DoPrintPreview(UINT nIDResource, CView* pPrintView,
CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState);

virtual void CalcWindowRect(LPRECT lpClientRect,
UINT nAdjustType = adjustBorder);
virtual CScrollBar* GetScrollBarCtrl(int nBar) const;
static CSplitterWnd* PASCAL GetParentSplitter(const CWnd* pWnd, BOOL bAnyState);

protected:
CDocument* m_pDocument;

public:
virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo);
protected:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
virtual void PostNcDestroy();

// friend classes that call protected CView overridables
friend class CDocument;
friend class CDocTemplate;
friend class CPreviewView;
friend class CFrameWnd;
friend class CMDIFrameWnd;
friend class CMDIChildWnd;
friend class CSplitterWnd;
friend class COleServerDoc;
friend class CDocObjectServer;

//{{AFX_MSG(CView)
afx_msg int OnCreate(LPCREATESTRUCT lpcs);
afx_msg void OnDestroy();
afx_msg void OnPaint();
afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
// commands
afx_msg void OnUpdateSplitCmd(CCmdUI* pCmdUI);
afx_msg BOOL OnSplitCmd(UINT nID);
afx_msg void OnUpdateNextPaneMenu(CCmdUI* pCmdUI);
afx_msg BOOL OnNextPaneCmd(UINT nID);

// not mapped commands - must be mapped in derived class
afx_msg void OnFilePrint();
afx_msg void OnFilePrintPreview();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

0:代码评释

protected:
CView();    // 表明CView只能用来继承,而不能实例化

BOOL DoPreparePrinting(CPrintInfo* pInfo);  //要取得打印效果,必须Override该函数,设置打印机

virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo = NULL);    

// 从该函数看来,设置打印机效果必须Override该函数  该函数和DoPreparePrinting()函数如何配合呢?

BOOL DoPreparePrinting(CPrintInfo* pInfo); //要取得打印效果,必须Override该函数,设置打印机

1:既然有virtual void OnDraw(CDC* pDC) = 0,虚函数,表示该类为抽象类,类的Constructor没有必要为Protected, Public也一样可以达到要求,不过使用Protected更严格遵守C++语言的语意。

2:CView的友元类:

friend class CDocument;
friend class CDocTemplate;
friend class CPreviewView;
friend class CFrameWnd;
friend class CMDIFrameWnd;
friend class CMDIChildWnd;
friend class CSplitterWnd;
friend class COleServerDoc;
friend class CDocObjectServer;

CView的友元类都是MVC架构中的,文档类,CDocument, COleServerDoc, CDocObjectServer, 框架类:CDocTemplate, CFrameWnd, CMDIFrameWnd, 控制器类:CMIDFrameWnd, CMDIChildWnd, 视图类有:CPreviewView  

3: CView类接受的消息

//{{AFX_MSG(CView)
afx_msg int OnCreate(LPCREATESTRUCT lpcs);
afx_msg void OnDestroy();
afx_msg void OnPaint();
afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
// commands
afx_msg void OnUpdateSplitCmd(CCmdUI* pCmdUI);
afx_msg BOOL OnSplitCmd(UINT nID);
afx_msg void OnUpdateNextPaneMenu(CCmdUI* pCmdUI);
afx_msg BOOL OnNextPaneCmd(UINT nID);

// not mapped commands - must be mapped in derived class
afx_msg void OnFilePrint();
afx_msg void OnFilePrintPreview();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()

该部分函数可以相当于Delphi的事件函数,OnCreate(),从名称看来,是刚创建是,用于设定View的外形,特性等,相当与TForm的procedure TForm1.FormCreate(Sender: TObject); FormCreate()事件, 而OnDestroy()则对等于:procedure TForm1.FormDestroy(Sender: TObject);

由于MFC的消息处理函数直接与WIN32消息是一一对应的,可以看出,CView类有关处理消息的函数极其缺乏的。而Delphi的TForm是极其丰富的,其实,TForm类对应的MFC类应该是CDialog,只是MFC并不打算把CDialog作为其它控件类的容器,所以在设计上,并没有处理其他的更多的消息。以下会接着讨论这个问题!

{ TForm }

TForm = class(TCustomForm)
public
...
    property OnActivate;
    property OnCanResize;
    property OnClick;
    property OnClose;
    property OnCloseQuery;
    property OnConstrainedResize;
    property OnContextPopup;
    property OnCreate;
    property OnDblClick;
    property OnDestroy;
    property OnDeactivate;
    property OnDockDrop;
    property OnDockOver;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnGetSiteInfo;
    property OnHide;
    property OnHelp;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnMouseWheel;
    property OnMouseWheelDown;
    property OnMouseWheelUp;
    property OnPaint;
    property OnResize;
    property OnShortCut;
    property OnShow;
    property OnStartDock;
    property OnUnDock;
end;

当然了,除了几个是对应Windows api消息外,其他的消息都是VCL自身的消息!

4: 滑稽的OnDraw和OnPaint

virtual void OnDraw(CDC* pDC) = 0;  

afx_msg void OnPaint();

从函数声明来看,好像OnDraw是一般的函数,而OnPaint正是WM_PAINT消息函数,可其实如果OnPaint不被Override时,OnPaint调用OnDraw来处理消息。这种手法有点接近Delphi的做法了。而不能一对一,否则,我还用MFC干吗,我直接用WIN32 API好了。

/

void CEx03aView::OnDraw(CDC* pDC)
{
pDC->TextOut(300, 500, "hello CEx03aView::OnDraw(CDC* pDC) function");
}

void CEx03aView::OnPaint() 
{
CPaintDC dc(this); // device context for painting
dc.TextOut(300, 400, "hello CEx03aView::OnPaint function");

}

OnPaint被Override之后,OnDraw就失去效果了。以上代码显示为“hello CEx03aView::OnPaint function”

5:Delphi的PME结构(属性方法事件)和VC的(M)FC结构(基础类),先进了整整一代,现在的Java和C#也都提供了PME结构,这是巧合吗?当然不是,Java的Javabean,正是Sun委托Borland做的,C#和.Net的设计师Anders更是Delphi的创始人。所以Java SDK和C#语言,.Net frameword和Delphi语言,VCL库神似,也就不奇怪了。至今,也没有什么消息说微软要出MFC.Net,我认为这是不可能,这不仅仅是市场原因,而是MFC的设计思想太落后了。而Delphi8的推出,VCL.Net的腾空出世,再一起证明VCL的良好设计一直都是领导Frameword的世界潮流。

6:MFC对api的封装极其落后,也极其丑陋,从技术从说就是一个失败的产品。可是它为什么成功了呢?这就说出了MFC的最大的优点:灵活,高效,简单。

    灵活:这是得益于C/C++语言的缘故。我也不用多说

    高效:还是得益于C/C++语言的缘故。C/C++语言的特点,灵活高效,相信大家不会忘记。

    简单:大家对比MFC和VCL,都会相信VCL确实比MFC难学,VCL里面的高级技巧鬼斧神工,VCL程序码里面甚至还有许多汇编。这都是令人望而却步的。而MFC呢,简单封装,简单使用,虽然丧失了RAD,不过,这也是大家喜欢的原因吧。

    MFC的成功很大程度是得益于C/C++这个语言中的日不落帝国,VCL成功在于Delphi这个优雅的,威力的,专利的OO语言

噢,MFC,当日不落帝国陨落时,还是把它放到历史的博物馆吧!

当然了,不能凭这点不像样的东西,来议论一个“伟大”的frameword---MFC,否则会让人晕倒,所以会有一系列的学习心得......

to be continued

--- 2004-7-2 by littleroy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值