孙鑫VC学习笔记:第三讲
2006-07-25 16:15
381 查看
第三讲2个半小时,听得好累啊!
在网上找到了别人做得笔记,非常好,于是拿过来用,在他的基础上增加一些内容。
不然全部自己写的话,估计写不到他那么好!
在MFC生成的应用程序口,窗口的生成跟第一讲不太一样,是怎样生成的?
1,寻找WinMain入口:(MFC向导生成的程序找不到WinMain函数,它是在编译的时候由链接器链接到程序当中的)
在安装目录下找到MFC文件夹下的SRC文件夹,SRC下是MFC源代码。
路径:MFC/SRC/APPMODUL.CPP:
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
//_tWinMain其实是一个宏 #define _tWinMain WinMain
LPTSTR lpCmdLine, int nCmdShow)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
注意:(#define _tWinMain WinMain)
2,C++中,全局对象的构造函数在main()开始执行之前被调用,全局对象被创建。全局构造函数按照它们在同一个文件中的声明顺序被调用。全局函数析构函数在main()函数结束后按照相反的顺序被调用。同样地,在VC++中,全局对象或全局变量来,在程序运行即WINMAIN函数加载的时候,已经为全局对象或全局变量分配了内存和赋初值。
所以:CTEApp theApp;->CTEApp ::CTEApp(){}->_tWinMain(){}
说明:每一个MFC程序,有且只有一个从WinApp类派生的类(应用程序类),也只有一个从应用程序类所事例化的对象,表示应用程序本身。在WIN32程序当中,表示应用程序是通过WINMAIN入口函数来表示的(通过一个应用程序的一个事例号这一个标识来表示的)。在基于MFC应用程序中,是通过产生一个应用程序对象,用它来唯一的表示了应用程序。
3,通过构造应用程序对象过程中调用基类CWinApp的构造函数,在CWinApp的构造函数中对程序包括运行时一些初始化工作完成了。[派生类构造之前先构造基类]
CWinApp构造函数:MFC|SRC|APPCORE.CPP
CWinApp::CWinApp(LPCTSTR lpszAppName){...}//带参数,而CTEApp构造函数
//没有显式向父类传参,难道CWinApp()有默认参数?见下:
(在CWinApp类定义中, CWinApp(LPCTSTR lpszAppName = NULL); )
注意:CWinApp()函数中:
pThreadState->m_pCurrentWinThread = this;
pModuleState->m_pCurrentWinApp = this
//this 指向那里?是CWinApp对象还是CTestApp对象?
(this指向的是派生类CTEApp对象,即theApp)
//???非常奇怪,我测试的this 指针指向基类呀!
调试:CWinApp::CWinApp();->CTEApp theApp;(->CTEApp ::CTEApp())->CWinApp::CWinApp()->CTEApp ::CTEApp()->_tWinMain(){}
4,_tWinMain 函数中通过调用AfxWinMain()函数来完成它要完成的功能。(Afx*前缀代表这是应用程序框架函数,是一些全局函数,应用程序框架是一套辅助生成应用程序的框架模型,把一些类做一些有机的集成,我们可根据这些类函数来设计自己的应用程序,Af是应用程序的框架的缩写)。
AfxWinMain()函数路径:MFC / SRC / WINMAIN.CPP:
而WinMain()函数并不在WINMAIN.CPP文件里。
在AfxWinMain()函数中:
CWinApp* pApp = AfxGetApp();
说明:AfxGetApp()获取一个指向CWinApp派生类对象(theApp)的指针。
pApp调用三个函数,这三个函数完成设计窗口类、注册窗口类、创建窗口、显示窗口、更新窗口、消息循环、消息处理函数。pThread->InitInstance()是三个函数当中的一个,pThread与pApp等价的,它完成窗口初始化工作,完成窗口的注册,完成窗口的创建,显示和更新。
首先调用 pApp->InitApplication(),用来做内部初始化管理用的。
//_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()
// { return afxCurrentWinApp; }
调用pThread->InitInstance()
说明:pThread也指向theApp,由于基类中virtual BOOL InitApplication()定义为虚函数,所以调用pThread->InitInstance()时候,调用的是派生类CTestApp的InitInstance()函数。
nReturnCode = pThread->Run();
说明:pThread->Run()完成了消息循环。
5,注册窗口类:AfxEndDeferRegisterClass(); //该函数会先判断要注册的窗口类是否已经注册过了
AfxEndDeferRegisterClass()函数所在文件:MFC|SRC|APPCORE.CPP
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister){...}
说明:设计窗口类:在MFC中事先设计好了几种缺省的窗口类,根据不同的应用程序的选择,调用AfxEndDeferRegisterClass()函数注册所选择的窗口类。
调试:CWinApp::CWinApp();->CTEApp theApp;(->CTEApp ::CTEApp())->CWinApp::CWinApp()->CTEApp ::CTEApp()->_tWinMain(){}//进入程序
->AfxWinMain();->pApp->InitApplication();->pThread->InitInstance()//父类InitInstance虚函数;->CTEApp::InitInstance()//子类实现函数;->AfxEndDeferRegisterClass(LONG fToRegister)//注册所选择的窗口类(出于文档管理,注册提前,正常的应在PreCreateWindow中进行注册)//之后进入创建窗口阶段(以下再不做调试)
6,PreCreateWindow()://这里面会调用AfxEndDeferRegisterClass()注册窗口类
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) //& cs 是一个引用,
//对cs的修改,会在基类中体现,这样我们就有机会修改窗口的外观
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
return TRUE;
}
说明:
CFrameWnd::PreCreateWindow()函数所在文件:MFC|SRC|WINFRM.CPP
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
//判断AFX_WNDFRAMEORVIEW_REG型号窗口类是否注册,如果没有注册则注册
cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background
//把注册后的窗口类名赋给cs.lpszClass
}
if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
cs.style |= FWS_PREFIXTITLE;
if (afxData.bWin4)
cs.dwExStyle |= WS_EX_CLIENTEDGE;
return TRUE;
}
其中:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);//PreCreateWindow()是个虚函数,如果子类有则调用子类的。
#define VERIFY(f) ASSERT(f)
#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)
define AFX_WNDFRAMEORVIEW_REG 0x00008
const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;//WINCORE.CPP文件中,定义为全局数组。
//#define AFX_WNDFRAMEORVIEW AFX_WNDCLASS("FrameOrView")
7,创建窗口:
创建窗口时的函数调用关系:
Create() -> CreateEx() -> PreCreateWindow() -> AfxEndDeferRegisterClass()
Create()函数由谁调用?是由LoadFrame()调用。
Create()函数路径:MFC|SRC|WINFRM.CPP:
CFrameWnd::Create(...){
...
CreateEx(...);//从父类继承来的,调用CWnd::CreateEx().
//后缀_Ex表示是一个扩展函数
...
}
CWnd::CreateEx()函数路径:MFC|SRC|WINCORE.CPP
BOOL CWnd::CreateEx(...){
...
if (!PreCreateWindow(cs))//虚函数,如果子类有调用子类的。
{
PostNcDestroy();
return FALSE;
}
...
HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
...
}
说明:CreateWindowEx()函数与CREATESTRUCT结构体参数的对应关系,使我们在创建窗口之前通过可PreCreateWindow(cs)修改CREATESTRUCT cs结构体成员来修改所要的窗口外观。PreCreateWindow(cs))//是虚函数,如果子类有调用子类的。
HWND CreateWindowEx(
DWORD dwExStyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);
typedef struct tagCREATESTRUCT { // cs
LPVOID lpCreateParams;
HINSTANCE hInstance;
HMENU hMenu;
HWND hwndParent;
int cy;
int cx;
int y;
int x;
LONG style;
LPCTSTR lpszName;
LPCTSTR lpszClass;
DWORD dwExStyle;
} CREATESTRUCT;
8,显示和更新窗口:
CTEApp类,TEApp.cpp中
m_pMainWnd->ShowWindow(SW_SHOW);//显示窗口,m_pMainWnd指向框架窗口
m_pMainWnd->UpdateWindow();//更新窗口
说明:
class CTEApp : public CWinApp{...}
class CWinApp : public CWinThread{...}
class CWinThread : public CCmdTarget
{
...
public:
CWnd* m_pMainWnd;
...
...
}
9,消息循环:由pThread->Run();完成。
int AFXAPI AfxWinMain()
{ ...
// Perform specific initializations
if (!pThread->InitInstance()){...}
//完成窗口初始化工作,完成窗口的注册,完成窗口的创建,显示和更新。
nReturnCode = pThread->Run();
//继承基类Run()方法,调用CWinThread::Run()来完成消息循环
...
}
////////////////////////////////////////////////////////////////
CWinThread::Run()方法路径:MFC|SRC|THRDCORE.CPP
int CWinThread::Run()
{ ...
// phase2: pump messages while available
do//消息循环
{
// pump message, but quit on WM_QUIT
if (!PumpMessage())//取消息并处理
return ExitInstance();
...
} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
...
}
说明:
BOOL PeekMessage(,,,,)函数说明
The PeekMessage function checks a thread message queue for a message and places the message (if any) in the specified structure.
If a message is available, the return value is nonzero.
If no messages are available, the return value is zero.
/////////////////////////////////////////////////////////////
BOOL CWinThread::PumpMessage()
{
...
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))//取消息
{...}
...
// process this message
if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
{
::TranslateMessage(&m_msgCur);//进行消息(如键盘消息)转换
::DispatchMessage(&m_msgCur);//分派消息到窗口的回调函数处理(实际上分派的消息经过消息映射,交由消息响应函数进行处理。)
}
return TRUE;
}
9,文档与视结构:
可以认为View类窗口是CMainFram类窗口的子窗口。
DOCument类是文档类。
DOC-VIEW结构将数据本身与它的显示分离开。
文档类:数据的存储,加载
视类:数据的显示,修改
10,文档类,视类,框架类的有机结合:
在CTEApp类CTEApp::InitInstance()函数中通过文档模板将文档类,视类,框架类的有机组织一起。
...
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTEDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CTEView));
AddDocTemplate(pDocTemplate);//增加到模板
下面给出CWnd 的仿真:
class CWnd{
public:
BOOL CreateEx(
DWORD dwExstyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x ,
int y
int nWidth,
int nHeight,
HWND hWndParent,
HMWNU hMenu,
HINSTANCE hInstance,
LPVOID lpParam );
BOOL ShowWindow(int nCmdShow);
BOOL UpdateWindow();
public:
HWND m_hwnd; //m_hwnd在构造函数中将其初始化为NULL
};
BOOL CWnd::CreateEx(
DWORD dwExstyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x ,
int y
int nWidth,
int nHeight,
HWND hWndParent,
HMWNU hMenu,
HINSTANCE hInstance,
LPVOID lpParam );
{
m_hWnd = ::CreateWindowEx(dwExstyle, lpClassName, dwStyle,
x, y, nWidth,nHeight, hWndParent, hMenu, hInstance, lpParam);
if(m_hWnd != NULL )
return TRUE;
else
return FALSE;
}//END CreateEx()
BOOL CWnd::ShowWindow (int nCmdShow)
{
::ShowWindow (m_hWnd,nCmdShow); //在函数前面加上的含义表示使用的是全局函数,
//以前使用全局函数的时候可以直接写函数名就行了,现在加上“ :: ”是为了防止与 windows API 函数混淆
}
BOOL CWnd :: UpdateWindow()
{
::UpdateWindow ( m_hWnd);
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdshow)
{
WNDCLASS wndcls;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
.................
RegisterClass (& wndcls);
CWnd wnd; //wnd并不等价于窗口,当窗口销毁之后,C++对象还可以存在
wnd.CreateEx(dwExstyle, lpClassName, dwStyle,
x, y, nWidth,nHeight, hWndParent, hMenu, hInstance, lpParam);
wnd.ShowWindow(SW_SHOWNUORMAL); //注意这里不再需要传递hwnd句柄,因为wnd里面已经定义了句柄 m_hwnd
wnd.UpdateWindow();
}//endof WinMain()
在网上找到了别人做得笔记,非常好,于是拿过来用,在他的基础上增加一些内容。
不然全部自己写的话,估计写不到他那么好!
在MFC生成的应用程序口,窗口的生成跟第一讲不太一样,是怎样生成的?
1,寻找WinMain入口:(MFC向导生成的程序找不到WinMain函数,它是在编译的时候由链接器链接到程序当中的)
在安装目录下找到MFC文件夹下的SRC文件夹,SRC下是MFC源代码。
路径:MFC/SRC/APPMODUL.CPP:
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
//_tWinMain其实是一个宏 #define _tWinMain WinMain
LPTSTR lpCmdLine, int nCmdShow)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
注意:(#define _tWinMain WinMain)
2,C++中,全局对象的构造函数在main()开始执行之前被调用,全局对象被创建。全局构造函数按照它们在同一个文件中的声明顺序被调用。全局函数析构函数在main()函数结束后按照相反的顺序被调用。同样地,在VC++中,全局对象或全局变量来,在程序运行即WINMAIN函数加载的时候,已经为全局对象或全局变量分配了内存和赋初值。
所以:CTEApp theApp;->CTEApp ::CTEApp(){}->_tWinMain(){}
说明:每一个MFC程序,有且只有一个从WinApp类派生的类(应用程序类),也只有一个从应用程序类所事例化的对象,表示应用程序本身。在WIN32程序当中,表示应用程序是通过WINMAIN入口函数来表示的(通过一个应用程序的一个事例号这一个标识来表示的)。在基于MFC应用程序中,是通过产生一个应用程序对象,用它来唯一的表示了应用程序。
3,通过构造应用程序对象过程中调用基类CWinApp的构造函数,在CWinApp的构造函数中对程序包括运行时一些初始化工作完成了。[派生类构造之前先构造基类]
CWinApp构造函数:MFC|SRC|APPCORE.CPP
CWinApp::CWinApp(LPCTSTR lpszAppName){...}//带参数,而CTEApp构造函数
//没有显式向父类传参,难道CWinApp()有默认参数?见下:
(在CWinApp类定义中, CWinApp(LPCTSTR lpszAppName = NULL); )
注意:CWinApp()函数中:
pThreadState->m_pCurrentWinThread = this;
pModuleState->m_pCurrentWinApp = this
//this 指向那里?是CWinApp对象还是CTestApp对象?
(this指向的是派生类CTEApp对象,即theApp)
//???非常奇怪,我测试的this 指针指向基类呀!
调试:CWinApp::CWinApp();->CTEApp theApp;(->CTEApp ::CTEApp())->CWinApp::CWinApp()->CTEApp ::CTEApp()->_tWinMain(){}
4,_tWinMain 函数中通过调用AfxWinMain()函数来完成它要完成的功能。(Afx*前缀代表这是应用程序框架函数,是一些全局函数,应用程序框架是一套辅助生成应用程序的框架模型,把一些类做一些有机的集成,我们可根据这些类函数来设计自己的应用程序,Af是应用程序的框架的缩写)。
AfxWinMain()函数路径:MFC / SRC / WINMAIN.CPP:
而WinMain()函数并不在WINMAIN.CPP文件里。
在AfxWinMain()函数中:
CWinApp* pApp = AfxGetApp();
说明:AfxGetApp()获取一个指向CWinApp派生类对象(theApp)的指针。
pApp调用三个函数,这三个函数完成设计窗口类、注册窗口类、创建窗口、显示窗口、更新窗口、消息循环、消息处理函数。pThread->InitInstance()是三个函数当中的一个,pThread与pApp等价的,它完成窗口初始化工作,完成窗口的注册,完成窗口的创建,显示和更新。
首先调用 pApp->InitApplication(),用来做内部初始化管理用的。
//_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()
// { return afxCurrentWinApp; }
调用pThread->InitInstance()
说明:pThread也指向theApp,由于基类中virtual BOOL InitApplication()定义为虚函数,所以调用pThread->InitInstance()时候,调用的是派生类CTestApp的InitInstance()函数。
nReturnCode = pThread->Run();
说明:pThread->Run()完成了消息循环。
5,注册窗口类:AfxEndDeferRegisterClass(); //该函数会先判断要注册的窗口类是否已经注册过了
AfxEndDeferRegisterClass()函数所在文件:MFC|SRC|APPCORE.CPP
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister){...}
说明:设计窗口类:在MFC中事先设计好了几种缺省的窗口类,根据不同的应用程序的选择,调用AfxEndDeferRegisterClass()函数注册所选择的窗口类。
调试:CWinApp::CWinApp();->CTEApp theApp;(->CTEApp ::CTEApp())->CWinApp::CWinApp()->CTEApp ::CTEApp()->_tWinMain(){}//进入程序
->AfxWinMain();->pApp->InitApplication();->pThread->InitInstance()//父类InitInstance虚函数;->CTEApp::InitInstance()//子类实现函数;->AfxEndDeferRegisterClass(LONG fToRegister)//注册所选择的窗口类(出于文档管理,注册提前,正常的应在PreCreateWindow中进行注册)//之后进入创建窗口阶段(以下再不做调试)
6,PreCreateWindow()://这里面会调用AfxEndDeferRegisterClass()注册窗口类
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) //& cs 是一个引用,
//对cs的修改,会在基类中体现,这样我们就有机会修改窗口的外观
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
return TRUE;
}
说明:
CFrameWnd::PreCreateWindow()函数所在文件:MFC|SRC|WINFRM.CPP
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
//判断AFX_WNDFRAMEORVIEW_REG型号窗口类是否注册,如果没有注册则注册
cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background
//把注册后的窗口类名赋给cs.lpszClass
}
if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
cs.style |= FWS_PREFIXTITLE;
if (afxData.bWin4)
cs.dwExStyle |= WS_EX_CLIENTEDGE;
return TRUE;
}
其中:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);//PreCreateWindow()是个虚函数,如果子类有则调用子类的。
#define VERIFY(f) ASSERT(f)
#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)
define AFX_WNDFRAMEORVIEW_REG 0x00008
const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;//WINCORE.CPP文件中,定义为全局数组。
//#define AFX_WNDFRAMEORVIEW AFX_WNDCLASS("FrameOrView")
7,创建窗口:
创建窗口时的函数调用关系:
Create() -> CreateEx() -> PreCreateWindow() -> AfxEndDeferRegisterClass()
Create()函数由谁调用?是由LoadFrame()调用。
Create()函数路径:MFC|SRC|WINFRM.CPP:
CFrameWnd::Create(...){
...
CreateEx(...);//从父类继承来的,调用CWnd::CreateEx().
//后缀_Ex表示是一个扩展函数
...
}
CWnd::CreateEx()函数路径:MFC|SRC|WINCORE.CPP
BOOL CWnd::CreateEx(...){
...
if (!PreCreateWindow(cs))//虚函数,如果子类有调用子类的。
{
PostNcDestroy();
return FALSE;
}
...
HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
...
}
说明:CreateWindowEx()函数与CREATESTRUCT结构体参数的对应关系,使我们在创建窗口之前通过可PreCreateWindow(cs)修改CREATESTRUCT cs结构体成员来修改所要的窗口外观。PreCreateWindow(cs))//是虚函数,如果子类有调用子类的。
HWND CreateWindowEx(
DWORD dwExStyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);
typedef struct tagCREATESTRUCT { // cs
LPVOID lpCreateParams;
HINSTANCE hInstance;
HMENU hMenu;
HWND hwndParent;
int cy;
int cx;
int y;
int x;
LONG style;
LPCTSTR lpszName;
LPCTSTR lpszClass;
DWORD dwExStyle;
} CREATESTRUCT;
8,显示和更新窗口:
CTEApp类,TEApp.cpp中
m_pMainWnd->ShowWindow(SW_SHOW);//显示窗口,m_pMainWnd指向框架窗口
m_pMainWnd->UpdateWindow();//更新窗口
说明:
class CTEApp : public CWinApp{...}
class CWinApp : public CWinThread{...}
class CWinThread : public CCmdTarget
{
...
public:
CWnd* m_pMainWnd;
...
...
}
9,消息循环:由pThread->Run();完成。
int AFXAPI AfxWinMain()
{ ...
// Perform specific initializations
if (!pThread->InitInstance()){...}
//完成窗口初始化工作,完成窗口的注册,完成窗口的创建,显示和更新。
nReturnCode = pThread->Run();
//继承基类Run()方法,调用CWinThread::Run()来完成消息循环
...
}
////////////////////////////////////////////////////////////////
CWinThread::Run()方法路径:MFC|SRC|THRDCORE.CPP
int CWinThread::Run()
{ ...
// phase2: pump messages while available
do//消息循环
{
// pump message, but quit on WM_QUIT
if (!PumpMessage())//取消息并处理
return ExitInstance();
...
} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
...
}
说明:
BOOL PeekMessage(,,,,)函数说明
The PeekMessage function checks a thread message queue for a message and places the message (if any) in the specified structure.
If a message is available, the return value is nonzero.
If no messages are available, the return value is zero.
/////////////////////////////////////////////////////////////
BOOL CWinThread::PumpMessage()
{
...
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))//取消息
{...}
...
// process this message
if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
{
::TranslateMessage(&m_msgCur);//进行消息(如键盘消息)转换
::DispatchMessage(&m_msgCur);//分派消息到窗口的回调函数处理(实际上分派的消息经过消息映射,交由消息响应函数进行处理。)
}
return TRUE;
}
9,文档与视结构:
可以认为View类窗口是CMainFram类窗口的子窗口。
DOCument类是文档类。
DOC-VIEW结构将数据本身与它的显示分离开。
文档类:数据的存储,加载
视类:数据的显示,修改
10,文档类,视类,框架类的有机结合:
在CTEApp类CTEApp::InitInstance()函数中通过文档模板将文档类,视类,框架类的有机组织一起。
...
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTEDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CTEView));
AddDocTemplate(pDocTemplate);//增加到模板
下面给出CWnd 的仿真:
class CWnd{
public:
BOOL CreateEx(
DWORD dwExstyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x ,
int y
int nWidth,
int nHeight,
HWND hWndParent,
HMWNU hMenu,
HINSTANCE hInstance,
LPVOID lpParam );
BOOL ShowWindow(int nCmdShow);
BOOL UpdateWindow();
public:
HWND m_hwnd; //m_hwnd在构造函数中将其初始化为NULL
};
BOOL CWnd::CreateEx(
DWORD dwExstyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x ,
int y
int nWidth,
int nHeight,
HWND hWndParent,
HMWNU hMenu,
HINSTANCE hInstance,
LPVOID lpParam );
{
m_hWnd = ::CreateWindowEx(dwExstyle, lpClassName, dwStyle,
x, y, nWidth,nHeight, hWndParent, hMenu, hInstance, lpParam);
if(m_hWnd != NULL )
return TRUE;
else
return FALSE;
}//END CreateEx()
BOOL CWnd::ShowWindow (int nCmdShow)
{
::ShowWindow (m_hWnd,nCmdShow); //在函数前面加上的含义表示使用的是全局函数,
//以前使用全局函数的时候可以直接写函数名就行了,现在加上“ :: ”是为了防止与 windows API 函数混淆
}
BOOL CWnd :: UpdateWindow()
{
::UpdateWindow ( m_hWnd);
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdshow)
{
WNDCLASS wndcls;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
.................
RegisterClass (& wndcls);
CWnd wnd; //wnd并不等价于窗口,当窗口销毁之后,C++对象还可以存在
wnd.CreateEx(dwExstyle, lpClassName, dwStyle,
x, y, nWidth,nHeight, hWndParent, hMenu, hInstance, lpParam);
wnd.ShowWindow(SW_SHOWNUORMAL); //注意这里不再需要传递hwnd句柄,因为wnd里面已经定义了句柄 m_hwnd
wnd.UpdateWindow();
}//endof WinMain()
相关文章推荐
- 20140623:孙鑫vc视频第三讲学习笔记
- 孙鑫vc++学习(vs2008)笔记之第一课Windows程序运行原理
- 孙鑫VC学习笔记:第十三讲 保存可串行化的类对象 如何获取文档与视类指针
- 孙鑫VC学习笔记:第十五讲 进程和线程基本概念
- 孙鑫VC学习笔记:第十讲画图 在窗口中贴上位图
- 孙鑫VC学习笔记:第十七讲 (三) 用命名管道实现进程间的通信
- 孙鑫VC学习笔记:第十一讲 (二) 图形的保存与重绘方法一
- 看了孙鑫老师的vc视频,今天又在大侠的blog里,即http://blog.csdn.net/hbyufan/ 中发现有相关笔记,转贴学习
- 孙鑫VC++视频学习笔记之8: MFC中指针的获取
- 孙鑫VC学习笔记:第二讲 掌握C++
- 孙鑫VC学习笔记:第十五讲 增加互斥条件实现线程同步
- 孙鑫VC学习笔记:第十五讲 (一) 进程和线程基本概念
- 孙鑫VC学习笔记:第十三讲 (二) 设置文档标题
- 孙鑫VC学习笔记:第十一讲 (一) 坐标空间与各种转换的概念
- 孙鑫VC++视频学习笔记之5: VC菜单相关编程
- 孙鑫VC学习笔记:第十九讲 动态链接库
- 孙鑫VC学习笔记:第十一讲 图形的保存与重绘方法一
- 孙鑫老师VC++教学视频学习笔记
- 孙鑫VC学习笔记:第十五讲 编写一个基于MFC对话框的聊天程序
- 孙鑫VC学习笔记:多线程编程