<?xml version="1.0" encoding="utf-8"?><rss version="2.0">
<channel>
<title><![CDATA[]]></title>
<link>http://blog.pfan.cn/qiutao</link>
<description>编程爱好者博客</description>
<language>zh-cn</language>
			<item>
		<title><![CDATA[不在这里写了]]></title>
		<link>http://blog.pfan.cn/qiutao/34646.html</link>
		<description><![CDATA[重新搞了个空间http://hi.csdn.net/ToCpp]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2008-04-27 15:01:00</pubDate>
		</item>
				<item>
		<title><![CDATA[CWnd使用]]></title>
		<link>http://blog.pfan.cn/qiutao/33410.html</link>
		<description><![CDATA[一般情况下开始学习MFC时都知道CWnd是MFC窗口类的基类，稍微深入学习后突然想从最基本的学起，即自己从CWnd派生一个窗口类而不是总通过AppWizard产生一个预先定义好的窗口类，其实更加赤裸点就是直接把CWnd做为窗口类，以下为范例程序：
#include &lt;afxwin.h&gt;
class CMyApp:public CWinApp
{
public:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BOOL InitInstance();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual int ExitInstance();
};
CMyApp theApp;
&nbsp;
BOOL CMyApp::InitInstance()
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CWnd* pMainWnd=new CWnd;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pMainWnd-&gt;CreateEx(0,0,"MyWnd",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NULL, NULL);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this-&gt;m_pMainWnd=pMainWnd;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pMainWnd-&gt;ShowWindow(m_nCmdShow);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_pMainWnd-&gt;UpdateWindow();
&nbsp;&nb]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2008-03-17 16:24:00</pubDate>
		</item>
				<item>
		<title><![CDATA[又是指针和数组]]></title>
		<link>http://blog.pfan.cn/qiutao/33201.html</link>
		<description><![CDATA[#include &lt;stdio.h&gt;int main(){&nbsp;int a[5]={1,2,3,4,5};&nbsp;int i;&nbsp;int *ptr=(int*)(&amp;a+1);&nbsp;printf("ptr=%p\n",ptr);&nbsp;for(i=0;i&lt;5;i++)&nbsp;&nbsp;printf("%p\n",a+i);&nbsp;printf("%d,%d\n",*(a+1),*(ptr-1));}
以下是输出
ptr=0013FF640013FF500013FF540013FF580013FF5C0013FF602,5
哎，想了半天才发现是&amp;a+1而不是a+1真是粗心啊！]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2008-03-06 14:49:00</pubDate>
		</item>
				<item>
		<title><![CDATA[MFC&nbsp;is&nbsp;back]]></title>
		<link>http://blog.pfan.cn/qiutao/31062.html</link>
		<description><![CDATA[Hello again. My name is Ale Contenti, and I’m the Dev Lead for the VC++ Libraries. I’m writing this blog entry from my hotel room in Barcelona. Steve Teixeira and I are here for TechEd Developers Europe. Let me tell you that the atmosphere here is just great! Lots of people and a lot of Visual Studio and C++ users. Lots of interest in Visual Studio 2008 and all the new features and functionality we’ve added to the product.
&nbsp;
Kate Gregory, Steve and I covered more than 7 talks about different C++ topics, ranging from debugging to interop to MFC. My main talk was about “MFC Updates for Visual Studio 2008 and Beyond”. &nbsp;&nbsp;In this session I introduced the major new features we’re implementing for MFC.&nbsp; With these features, developers will be able to create modern applications that leverage the “look and feel” of Microsoft Office, Internet Explorer and Visual Studio.
&nbsp;
My MFC talk was in a pretty big room, and the audience was extremely interested! It was great to]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-11-21 12:09:00</pubDate>
		</item>
				<item>
		<title><![CDATA[google&nbsp;vs&nbsp;tencent]]></title>
		<link>http://blog.pfan.cn/qiutao/29726.html</link>
		<description><![CDATA[前些时看到Tencent发布了一个日程管理软件，当时觉得界面还蛮好看的，但是是个测试版好多东西还不能用，后来又在网上无意中发现google也有个在线日历，打开后发现两者的界面是如此相似，也不知道是谁模仿谁……]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-09-29 16:57:00</pubDate>
		</item>
				<item>
		<title><![CDATA[指针趣事]]></title>
		<link>http://blog.pfan.cn/qiutao/29511.html</link>
		<description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 今天是个大晴天，温暖的阳光透过窗子照进了这间宽敞的办公室，办公室里三三两两的人们正在各自的计算机前努力工作，一切都显得那么的安静、祥和、有条不紊 …… 
“啊～！救命啊！Solmyr 你又用文件夹砸我！” 
“愚蠢者是应该受到惩罚的。” 
画外音： …… 呃，好吧，我得承认有点小小的例外。这里是一家软件公司，发出惨叫的这位是 zero ，新进的大学生；这边一脸优雅，看上去很有修养一点也不象刚刚砸过人的这位，是 Solmyr ，资深程序员，负责 zero 这一批新人的培训。啊，故事开始了 …… 
“我干了什么啦？”zero 揉着鼻子问道，“这次你拿来砸我的文件夹又大了一号！” 
“你过来自己看看你犯下的错误。”Solmyr 翻出了 zero 刚刚交上来的一段代码： 
…… char* msg = “Connectting ... Please wait“ …… if( Status == S_CONNECTED ) strcpy(msg, “Connectted“); …… 
“我犯了什么错误啦？这是一个很平凡的字符串声明而已”，zero 不满的说到。 
“你看不出来吗？connect 这个单词的进行时和过去时你都拼错了，多打了一个 t”，Solmyr 不紧不慢地回答。 
“就为了这个你又用文件夹砸我 …… 啊！这次又是光盘盒！” 
“这是商用软件，你以为是在 QQ 上和 PPMM 聊天，有错别字不要紧啊？更糟糕的是，我故意留了这么长的时间给你，到现在你还没发现你真正的错误在什么地方。你可真不是一般的菜啊～”，Solmyr 故意拖了个长音，满意的看到 zero 处于爆发的边缘，“好吧，让我们从基础开始，C 语言中是怎样处理字符串的？” 
“这个我知道”，zero 显得很有自信，“C/C++ 语言中，字符串是一段连续的字符型内存单元，每个单元存放一个字符，并用 ＼0 作为结尾的标记。” 
“那么使用指针之前，我们应当 ……” 
“我们应当保证这个指针指向合法的内存，要么指向一块已经存在的内存，要么为它动态分配一块。”，zero 开始露出得意的笑容 —— 这种程度的问题，哈！ 
“好！那么你的代码中 msg 这个指针指向哪里？” 
笑容凝固了。 
“这个 …… 呃]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-09-18 23:53:00</pubDate>
		</item>
				<item>
		<title><![CDATA[Key&nbsp;Concept:&nbsp;Polymorphism&nbsp;in&nbsp;C++]]></title>
		<link>http://blog.pfan.cn/qiutao/29149.html</link>
		<description><![CDATA[The crucial point about references and pointers to base-class types is that the static typethe type of the reference or pointer, which is knowable at compile timeand the dynamic typethe type of the object to which the pointer or reference is bound, which is knowable only at run timemay differ.
The fact that the static and dynamic types of references and pointers can differ is the cornerstone of how C++ supports polymorphism.
When we call a function defined in the base class through a base-class reference or pointer, we do not know the precise type of the object on which the function is executed. The object on which the function executes might be of the base type or it might be an object of a derived type.
If the function called is nonvirtual, then regardless of the actual object type, the function that is executed is the one defined by the base type. If the function is virtual, then the decision as to which function to run is delayed until run time. The version of the virtual functi]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-09-05 22:35:00</pubDate>
		</item>
				<item>
		<title><![CDATA[转载&nbsp;MFC消息详解&nbsp;]]></title>
		<link>http://blog.pfan.cn/qiutao/29136.html</link>
		<description><![CDATA[MFC消息详解
1. 怎样使用MFC发送一个消息用MFC发送一个消息的方法是，&nbsp;&nbsp;&nbsp;&nbsp;首先，应获取接收消息的CWnd类对象的指针；&nbsp;&nbsp;&nbsp;&nbsp;然后,调用CWnd的成员函数SendMessage( )。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LRESULT Res=pWnd-&gt;SendMessage(UINT Msg, WPARAM wParam, LPARAM lParam);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pWnd指针指向目标CWnd类对象。变量Msg是消息，wParam和lParam变量包含消息的参数，如鼠标单击哪里或选择了什么菜单项。目标窗口返回的消息结果放在变量Res中。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;发送消息到一个没有CWnd类对象的窗口，可以用下列目标窗口的句柄直接调用Windows API：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LRESULT Res=::SendMessage(HWND hWnd, UINT Msg,&nbsp; WPARAM wParam, LPARAM lParam);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这里的hWnd是目标窗口的句柄。2. 怎样用MFC寄送一个消息&nbsp;&nbsp;&nbsp;&nbsp;用MFC寄送一个消息与发送一个消息几乎相同，但寄送时用PostMessage( ) ，而不是用SendMessage( )；返回值Res也不一样，Res不是一个由目标窗口返回的值，而是一个布尔值，用来表示消息是否成功地放到消息队列中。3. 检索一个寄送消息&nbsp;&nbsp;&nbsp;&nbsp;正常情况下，一旦消息被寄送后，应用程序在后台发送它。但是在特殊情况下，需要你自己去删除一个消息，例如想在应用程序接收到某种消息之前停止应用程序。有两种方法可以从应用程序消息队列中删除一个消息，但这两种方法都没有涉及MFC。■ 第一种方法：在不干扰]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-09-05 14:48:00</pubDate>
		</item>
				<item>
		<title><![CDATA[float&nbsp;ToolBar&nbsp;&amp;&amp;&nbsp;dock&nbsp;ToolBar]]></title>
		<link>http://blog.pfan.cn/qiutao/29026.html</link>
		<description><![CDATA[A docked toolbar is a child of the frame window it's docked to, but a floating toolbar is a child of the mini frame window that surrounds it. The mini frame window is a popup window owned by the frame window, but it's not a child of the frame window. (A popup window is a window with the style WS_POPUP; a child window has the WS_CHILD style instead.) The distinction is important because popup windows owned by a frame window are destroyed before the frame window is destroyed. Child windows, on the other hand, are destroyed after their parents are destroyed. A floating toolbar no longer exists when the frame window's OnDestroy function is called.]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-09-01 11:21:00</pubDate>
		</item>
				<item>
		<title><![CDATA[消息传递过程]]></title>
		<link>http://blog.pfan.cn/qiutao/29025.html</link>
		<description><![CDATA[据说是在Run中调用AfxWndProc（侯捷说的我在源码中找了会没找到，也不晓得是哪个间接调用的），在该函数里面接着调用AfxCallWndProc，然后AfxCallWndProc中有这么一段
// special case for WM_INITDIALOG
CRect rectOld;
DWORD dwStyle = 0;
if (nMsg == WM_INITDIALOG)
_AfxPreInitDialog(pWnd, &amp;rectOld, &amp;dwStyle);
&nbsp;
// delegate to object's WindowProc
lResult = pWnd-&gt;WindowProc(nMsg, wParam, lParam);
&nbsp;
// more special case for WM_INITDIALOG
if (nMsg == WM_INITDIALOG)
_AfxPostInitDialog(pWnd, rectOld, dwStyle);
如果不是WM_INITDIALOG消息则调用CWnd的WindowProc，这时就有点迷惑了，应该说CCmdTarget是处理消息的基类其中的OnCmdMsg为什么不先调用呢，其实我也不清楚，查看了源代码后发现在WindowProc中会判断消息的类型里面有这么段：
CWnd::WindowProc
if (message == WM_COMMAND)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (OnCommand(wParam, lParam))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lResult = 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto LReturnTrue;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nb]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-09-01 01:05:00</pubDate>
		</item>
				<item>
		<title><![CDATA[MDI,SDI创建过程中的一点不同]]></title>
		<link>http://blog.pfan.cn/qiutao/29010.html</link>
		<description><![CDATA[CMultiDocTemplate* pDocTemplate;&nbsp;pDocTemplate = new CMultiDocTemplate(&nbsp;&nbsp;IDR_MDISQUTYPE,&nbsp;&nbsp;RUNTIME_CLASS(CSquaresDoc),&nbsp;&nbsp;RUNTIME_CLASS(CChildFrame), // custom MDI child frame&nbsp;&nbsp;RUNTIME_CLASS(CSquaresView));&nbsp;AddDocTemplate(pDocTemplate);&nbsp;&nbsp;// create main MDI Frame window&nbsp;CMainFrame* pMainFrame = new CMainFrame;&nbsp;if (!pMainFrame-&gt;LoadFrame(IDR_MAINFRAME))&nbsp;&nbsp;return FALSE;&nbsp;m_pMainWnd = pMainFrame;
。。。。。。。。
&nbsp;&nbsp;// Dispatch commands specified on the command line&nbsp;if (!ProcessShellCommand(cmdInfo))&nbsp;&nbsp;return FALSE;
&nbsp;// The main window has been initialized, so show and update it.&nbsp;pMainFrame-&gt;ShowWindow(m_nCmdShow);&nbsp;pMainFrame-&gt;UpdateWindow();
上面为MDI，下面为SDI
CSingleDocTemplate* pDocTemplate;&nbsp;pDocTemplate = new CSingleDocTemplate(&nbsp;&nbsp;IDR_MAINFRAME,&nbsp;&nbsp;RUNTIME_CLASS(CSquaresDoc),&nbsp;&nbsp;RUNTIME_CLASS(CMainFrame),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-08-31 12:51:00</pubDate>
		</item>
				<item>
		<title><![CDATA[回调函数在MFC中的使用]]></title>
		<link>http://blog.pfan.cn/qiutao/28869.html</link>
		<description><![CDATA[回调函数的简单定义就是你定义的由Windows来调用。以下两个函数摘自《Programming Windows with MFC》，这里暂且不管函数的具体作用，在FillListBox中有一个API函数，它调用的回调函数是EnumFontFamProc，回调函数的声明形式一般都是相对固定的，具体可以参考MSDN。
static int CALLBACK EnumFontFamProc (ENUMLOGFONT* lpelf,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NEWTEXTMETRIC* lpntm, int nFontType, LPARAM lParam);
void CMainWindow::FillListBox ()
{
&nbsp;&nbsp;&nbsp; m_wndListBox.ResetContent ();
&nbsp;
&nbsp;&nbsp;&nbsp; CClientDC dc (this);
&nbsp;&nbsp;&nbsp; ::EnumFontFamilies ((HDC) dc, NULL, (FONTENUMPROC) EnumFontFamProc,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (LPARAM) this);
}
int CALLBACK CMainWindow::EnumFontFamProc (ENUMLOGFONT* lpelf,
&nbsp;&nbsp;&nbsp; NEWTEXTMETRIC* lpntm, int nFontType, LPARAM lParam)
{
&nbsp;&nbsp;&nbsp; CMainWindow* pWnd = (CMainWindow*) lParam;
&nbsp;
&nbsp;&nbsp;&nbsp; if ((pWnd-&gt;m_wndCheckBox.GetCheck () == BST_UNCHECKED) ||
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (nFontType &amp; TRUETYPE_FON]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-08-26 23:42:00</pubDate>
		</item>
				<item>
		<title><![CDATA[CWnd及窗口产生和销毁过程]]></title>
		<link>http://blog.pfan.cn/qiutao/28834.html</link>
		<description><![CDATA[昨天去新华书店看的今天趁还记得就写下了.
窗口创建：首先定义一个CWnd对象，然后调用CWnd::Create，其实Create又会调用CreateEx，与之对应的API函数也是这样，在CreateEx调用AfxCtxCreateWindowEx之前会调用PreCreateWindow，这个时候偶CWnd对应的窗口的句柄还未被Windows分配，之后调用AfxCtxCreateWindowEx，在调用这个函数的过程中会发送WM_CREATE消息从而引发OnCreate函数调用注意调用OnCreate时CWnd中的m_hWnd已经有值了，在OnCreate中可以进行一些初始化以及创建字窗口之类的事情。至此窗口创建完毕。
窗口销毁：可以发送一个WM_CLOSE消息给指定窗口使其调用OnClose函数，此函数中会发送WM_DESTROY从而引发OnDestroy的调用，该函数又会引发最后一个消息WM_NCDESTROY的发送，OnNcDestroy即被调用，在OnNcDestroy的最后会调用PostNcDestroy，CWnd的PostNcDestroy为
void CWnd::PostNcDestroy(){&nbsp;// default to nothing}，什么也不做，但是CFrameWnd重载了此函数
void CFrameWnd::PostNcDestroy(){&nbsp;// default for frame windows is to allocate them on the heap&nbsp;//&nbsp; the default post-cleanup is to 'delete this'.&nbsp;// never explicitly call 'delete' on a CFrameWnd, use DestroyWindow instead&nbsp;delete this;}即我们看到的在App中new的Frame没有删除就是这个原因，但是我们自己从CWnd派生的窗口就不同了，如果你new了就要delete，而且最好就是在这个函数里delete。]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-08-25 19:00:00</pubDate>
		</item>
				<item>
		<title><![CDATA[VC截取屏幕]]></title>
		<link>http://blog.pfan.cn/qiutao/28611.html</link>
		<description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一直对GID 不是很懂，今天狠下心来看了一天的GDI，主要是参照着MSDN看，感觉还是有点收获的。根据MSDN写了一个小小的程序，仅仅就是截取屏幕，另外可以将其保存到剪贴板里。
以下为源代码：
// Capturing_Image.cpp : 定义应用程序的入口点。//
#include "stdafx.h"#include "Capturing_Image.h"
#define MAX_LOADSTRING 100
// 全局变量:HINSTANCE hInst;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 当前实例TCHAR szTitle[MAX_LOADSTRING];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 标题栏文本TCHAR szWindowClass[MAX_LOADSTRING];&nbsp;&nbsp;&nbsp;// 主窗口类名
// 此代码模块中包含的函数的前向声明:ATOM&nbsp;&nbsp;&nbsp;&nbsp;MyRegisterClass(HINSTANCE hInstance);BOOL&nbsp;&nbsp;&nbsp;&nbsp;InitInstance(HINSTANCE, int);LRESULT CALLBACK&nbsp;WndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACK&nbsp;About(HWND, UINT, WPARAM, LPARAM);
void CaptureScreen(HWND,HDC);
int APIENTRY _tWinMain(HINSTANCE hInstance,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HINSTANCE hPrevInstance,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-08-18 01:23:00</pubDate>
		</item>
				<item>
		<title><![CDATA[MFC学习之--MFC窗口过程]]></title>
		<link>http://blog.pfan.cn/qiutao/28195.html</link>
		<description><![CDATA[所有的消息都送给窗口过程处理，MFC的所有窗口都使用同一窗口过程，消息或者直接由窗口过程调用相应的消息处理函数处理，或者按MFC命令消息派发路径送给指定的命令目标处理。
那么，MFC的窗口过程是什么？怎么处理标准Windows消息？怎么实现命令消息的派发？
&nbsp;
MFC窗口过程的指定 
从前面的讨论可知，每一个“窗口类”都有自己的窗口过程。正常情况下使用该“窗口类”创建的窗口都使用它的窗口过程。
MFC的窗口对象在创建HWND窗口时，也使用了已经注册的“窗口类”，这些“窗口类”或者使用应用程序提供的窗口过程，或者使用Windows提供的窗口过程（例如Windows控制窗口、对话框等）。那么，为什么说MFC创建的所有HWND窗口使用同一个窗口过程呢？
在MFC中，的确所有的窗口都使用同一个窗口过程：AfxWndProc或AfxWndProcBase（如果定义了_AFXDLL）。它们的原型如下：
LRESULT CALLBACK
AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
LRESULT CALLBACK
AfxWndProcBase(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
这两个函数的原型都如符合windows的窗口过程函数原型。
如果动态链接到MFC DLL(定义了_AFXDLL)，则AfxWndProcBase被用作窗口过程，否则AfxWndProc被用作窗口过程。AfxWndProcBase首先使用宏AFX_MANAGE_STATE设置正确的模块状态，然后调用AfxWndProc。
下面，假设不使用MFC DLL，讨论MFC如何使用AfxWndProc取代各个窗口的原窗口过程。
窗口过程的取代发生在窗口创建的过程时，使用了子类化(Subclass)的方法。所以，从窗口的创建过程来考察取代过程。从前面可以知道，窗口创建最终是通过调用CWnd::CreateEx函数完成的，分析该函数的流程:

CREATESTRUCT结构类型的变量cs包含了传递给窗口过程的初始化参数。CREATESTRUCT结构描述了创建窗口所需要的信息，定义如下：
typedef struct tagCREAT]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-08-05 00:23:00</pubDate>
		</item>
				<item>
		<title><![CDATA[MFC学习之--消息映射的定义和实现]]></title>
		<link>http://blog.pfan.cn/qiutao/28034.html</link>
		<description><![CDATA[MFC处理的三类消息 
&nbsp;
根据处理函数和处理过程的不同，MFC主要处理三类消息：
Windows消息，前缀以“WM_”打头，WM_COMMAND例外。Windows消息直接送给MFC窗口过程处理，窗口过程调用对应的消息处理函数。一般，由窗口对象来处理这类消息，也就是说，这类消息处理函数一般是MFC窗口类的成员函数。 
控制通知消息，是控制子窗口送给父窗口的WM_COMMAND通知消息。窗口过程调用对应的消息处理函数。一般，由窗口对象来处理这类消息，也就是说，这类消息处理函数一般是MFC窗口类的成员函数。 
需要指出的是，Win32使用新的WM_NOFITY来处理复杂的通知消息。WM_COMMAND类型的通知消息仅仅能传递一个控制窗口句柄(lparam)、控制窗ID和通知代码(wparam)。WM_NOTIFY能传递任意复杂的信息。
命令消息，这是来自菜单、工具条按钮、加速键等用户接口对象的WM_COMMAND通知消息，属于应用程序自己定义的消息。通过消息映射机制，MFC框架把命令按一定的路径分发给多种类型的对象（具备消息处理能力）处理，如文档、窗口、应用程序、文档模板等对象。能处理消息映射的类必须从CCmdTarget类派生。 
在讨论了消息的分类之后，应该是讨论各类消息如何处理的时候了。但是，要知道怎么处理消息，首先要知道如何映射消息。
&nbsp;
MFC消息映射的实现方法 
&nbsp;
MFC使用ClassWizard帮助实现消息映射，它在源码中添加一些消息映射的内容，并声明和实现消息处理函数。现在来分析这些被添加的内容。
在类的定义（头文件）里，它增加了消息处理函数声明，并添加一行声明消息映射的宏DECLARE_MESSAGE_MAP。
在类的实现（实现文件）里，实现消息处理函数，并使用IMPLEMENT_MESSAGE_MAP宏实现消息映射。一般情况下，这些声明和实现是由MFC的ClassWizard自动来维护的。看一个例子：
在AppWizard产生的应用程序类的源码中，应用程序类的定义（头文件）包含了类似如下的代码：
//{{AFX_MSG(CTttApp)
afx_msg void OnAppAbout();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
应用程序类的实现文件中]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-07-29 22:55:00</pubDate>
		</item>
				<item>
		<title><![CDATA[关于虚函数表的一点内容]]></title>
		<link>http://blog.pfan.cn/qiutao/27889.html</link>
		<description><![CDATA[还是用图表和代码能说明内容：
#include &lt;iostream&gt;using std::cout;using std::endl;
class Base{public: //为了便于取地址 &nbsp;&nbsp;&nbsp; int m_data1;&nbsp;&nbsp;&nbsp; int m_data2;&nbsp;&nbsp;&nbsp; int m_data3;public:&nbsp;&nbsp;&nbsp; void mem_fun1(); &nbsp;&nbsp;&nbsp; void mem_fun2();&nbsp;&nbsp;&nbsp; //注意虽然后面没用到这些虚函数 ，但是要使程序可以编译通过&nbsp;&nbsp;&nbsp; //需要实现他们，因为建立vtable会出错 &nbsp;&nbsp;&nbsp; virtual void vir_fun1(){}&nbsp;&nbsp;&nbsp; virtual void vir_fun2(){}&nbsp; };&nbsp;&nbsp;&nbsp; 
class Derive:public Base{public://为了便于取地址 &nbsp;&nbsp;&nbsp; int m_data1;&nbsp;&nbsp;&nbsp; int m_data3;&nbsp;&nbsp;&nbsp; int m_data4;public:&nbsp;&nbsp; &nbsp;void mem_fun1(); &nbsp;&nbsp;&nbsp; virtual void vir_fun2(){}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };
int main(){&nbsp;&nbsp;&nbsp; cout&lt;&lt;"sizeof(Base)=&gt; "&lt;&lt;sizeof(Base)&lt;&lt;endl;&nbsp;&nbsp;&nbsp; cout&lt;&lt;"sizeof(Derive)=&gt; "&lt;&lt;sizeof(Derive)&lt;&lt;endl;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Base b;&nbsp;&]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-07-26 00:37:00</pubDate>
		</item>
				<item>
		<title><![CDATA[MFC学习之--MFC和Win32]]></title>
		<link>http://blog.pfan.cn/qiutao/27888.html</link>
		<description><![CDATA[MFC Object和Windows Object的关系 
MFC中最重要的封装是对Win32 API的封装，因此，理解Windows Object和MFC Object (C++对象，一个C++类的实例)之间的关系是理解MFC的关键之一。所谓Windows Object（Windows对象）是Win32下用句柄表示的Windows操作系统对象；所谓MFC Object (MFC对象)是C++对象，是一个C++类的实例，这里（本书范围内）MFC Object是有特定含义的，指封装Windows Object的C++ Object，并非指任意的C++ Object。
MFC Object 和Windows Object是不一样的，但两者紧密联系。以窗口对象为例：
一个MFC窗口对象是一个C++ CWnd类（或派生类）的实例，是程序直接创建的。在程序执行中它随着窗口类构造函数的调用而生成，随着析构函数的调用而消失。而Windows窗口则是Windows系统的一个内部数据结构的实例，由一个“窗口句柄”标识，Windows系统创建它并给它分配系统资源。Windows窗口在MFC窗口对象创建之后，由CWnd类的Create成员函数创建，“窗口句柄”保存在窗口对象的m_hWnd成员变量中。Windows窗口可以被一个程序销毁，也可以被用户的动作销毁。
下面，对MFC Object和Windows Object作一个比较。有些论断对设备描述表(MFC类是CDC，句柄是HDC)可能不适用，但具体涉及到时会指出。
从数据结构上比较 
MFC Object是相应C++类的实例，这些类是MFC或者程序员定义的；
Windows Object是Windows系统的内部结构，通过一个句柄来引用；
MFC给这些类定义了一个成员变量来保存MFC Object对应的Windows Object的句柄。对于设备描述表CDC类，将保存两个HDC句柄。
从层次上讲比较 
MFC Object是高层的，Windows Object是低层的；
MFC Object封装了Windows Object的大部分或全部功能，MFC Object的使用者不需要直接应用Windows Object的HANDLE（句柄）使用Win32 API，代替它的是引用相应的MFC Object的成员函数。]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-07-25 23:22:00</pubDate>
		</item>
				<item>
		<title><![CDATA[MFC学习之----MFC概述]]></title>
		<link>http://blog.pfan.cn/qiutao/27818.html</link>
		<description><![CDATA[&nbsp;
MFC是一个编程框架 
MFC (Microsoft Foundation Class Library)中的各种类结合起来构成了一个应用程序框架，它的目的就是让程序员在此基础上来建立Windows下的应用程序，这是一种相对SDK来说更为简单的方法。因为总体上，MFC框架定义了应用程序的轮廓，并提供了用户接口的标准实现方法，程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。Microsoft Visual C++提供了相应的工具来完成这个工作：AppWizard可以用来生成初步的框架文件（代码和资源等）；资源编辑器用于帮助直观地设计用户接口；ClassWizard用来协助添加代码到框架文件；最后，编译，则通过类库实现了应用程序特定的逻辑。
封装 
构成MFC框架的是MFC类库。MFC类库是C++类库。这些类或者封装了Win32应用程序编程接口，或者封装了应用程序的概念，或者封装了OLE特性，或者封装了ODBC和DAO数据访问的功能，等等，分述如下。
（1）对Win32应用程序编程接口的封装
用一个C++ Object来包装一个Windows Object。例如：class CWnd是一个C++ window object，它把Windows window(HWND)和Windows window有关的API函数封装在C++ window object的成员函数内，后者的成员变量m_hWnd就是前者的窗口句柄。
（2）对应用程序概念的封装
使用SDK编写Windows应用程序时，总要定义窗口过程，登记Windows Class，创建窗口，等等。MFC把许多类似的处理封装起来，替程序员完成这些工作。另外，MFC提出了以文档-视图为中心的编程模式，MFC类库封装了对它的支持。文档是用户操作的数据对象，视图是数据操作的窗口，用户通过它处理、查看数据。
（3）对COM/OLE特性的封装
OLE建立在COM模型之上，由于支持OLE的应用程序必须实现一系列的接口（Interface），因而相当繁琐。MFC的OLE类封装了OLE API大量的复杂工作，这些类提供了实现OLE的更高级接口。
（4）对ODBC功能的封装
以少量的能提供与ODBC之间更高级接口的C++类，封装了ODBC API的大量的复杂的工作，提供了一种数据库编]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-07-24 12:26:00</pubDate>
		</item>
				<item>
		<title><![CDATA[MFC的一点感悟]]></title>
		<link>http://blog.pfan.cn/qiutao/27816.html</link>
		<description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 学习MFC的时间不长，但是感觉开始学习的方法不对，只知道随便摆摆几个控件然后想怎么把个控件弄漂亮点（不停的在网上下别人写的控件，但是看不懂），而忽视了基础的重要性，比如说MFC和API之间的关系，消息映射机制的实现，Windows窗口对象和CWnd的C++对象之间的联系等等。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样学习的结果可想而知，只懂皮毛，只会用ClassWizard弄点简单的小程序，遇到稍微需要自己写代码的地方就不知从何写起了。因此曾一度决定放弃MFC的，觉得这种编程方式太麻烦了，尤其是写UI时，自我觉得还是对JAVA，QT那种写界面的方式好接受点，知道自己写了哪些东西以及怎么写的。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前几天在网上发现一在线教程，感觉写得还蛮好的，比起那些各式各样的VC的书讲得好多了，尤其是当我看完消息映射后，发现这个对我真是受益匪浅，再结合源码看看，有些以前难以理解的东西现在觉得有点眉目了，还开始感叹写MFC那些人的技术之精，能写出如此庞大（看到网上有些人觉得MFC太臃肿，我暂时可能还没有发现这个的能力），效率又高的库真是不简单，觉得学习C++面向对象的思想，MFC源码是个不错的东东。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 想把自己现在对MFC的一些基础部分整理一个小的系列文章，:-)，当然绝大部分内容都是网上的，我可能只是修改一些错误的地方，可惜现在时间不是很多，尽力了，也算是对自己学习MFC的一点点初级的总结吧！]]></description>
		<author><![CDATA[whtuling]]></author>
		<pubDate>2007-07-24 12:15:00</pubDate>
		</item>
		</channel>
</rss>