VS 学习笔记-MFC Appwizard原理

1.MFC:microsoft funcation class

2.新建一个MFC工程选择单文档-MFC标准类型的项目,产生出来直接编译就能产生一个窗口。所有的都是类,程序的入口Winmain在哪里呢?在VS安装目录下找到appmodul.cpp设置断点在_twWinMain处发现程序停止。所以新建的MFC程序会自动去调用这里的WinMain函数。

3.选择类视图可以看到:CTestView(窗口类),CTestDoc(文档类),CTesApp(应用程序类),CMainFrame(窗口类),CAboutDlg(窗口类).

打开CTestApp的构造函数:选择CTestApp。在左边框下方点击构造函数CTestApp()设置断点发现:程序先进入构造函数再进入WinMain函数。原因是因为在程序Test.cpp中定义了一个CTestApp类型的全局变量。因为全局变量在进入main之前就分配好了内存空间。



4.如何唯一的表示这个应用程序。在LESSON1中是通过WinMain中分配的实例号来唯一的表示应用程序。而这里是通过创建一个唯一的CTestApp全局对象来表示应用程序本身。用户编写的程序要实例化一个应用程序(全局变量)就必须要构造函数CTestApp(),构造这个子类时就要先构造基类CWinApp()。作为桥梁就使应用程序和微软提供的CWinApp和winmain联系了起来。


5.CWinApp:在appcore.cpp当中。创建一个CTestApp时,会调用基类的构造函数CWinApp(),这个构造函数中的this指针此时是指向派生类对象theApp的指针。因为这时调用的CWinApp()被看做是CTestApp的一部分。


6.AfxWinMain()在WINMAIN.cpp当中。Af:app framework,表示应用程序框架模型,使各个类有机的结合在一起。在主函数中调用initinstance结果会去调用子类的initinstance(),并且在这一部分实现窗口的注册创建,显示和更新。

AfxWinMain()
{...
CWinThread* pThread=AfxGetThread();
CWinApp* pApp=AfxGetApp();//获得一个指向CWinApp的指针,实际上就是指向theApp。
if (!pThread->InitInstance())//这里调用子类的InitInstance()
{
if (pThread->m_pMainWnd != NULL)
{
TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode = pThread->ExitInstance();
goto InitFailure;
}
nReturnCode = pThread->Run();//调用消息循环
...

}

CTestApp::InitInstance()
{
if(!ProcessShellCommand(cmdInfo))//这一部分创建注册窗口
  return FALSE;
m_pMainWnd->ShowWindow(SW_SHOW);//展示窗口
m_pMainWnd->UpdateWindow();//更新窗口
return TRUE;

}



7.在MAIN函数中会调用注册窗口类函数。

注册窗口类wincore.cpp当中有函数AfxEndDeferGegisterClass.

MFC已经内部自己定义好了不同的窗口类,并不需要用户自己去定义。只需要用户去注册对应的窗口类。

if (fToRegister & AFX_WNDFRAMEORVIEW_REG)
{
// SDI Frame or MDI Child windows or views - normal colors
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
}

8.产生窗口

CMainFrame:框架窗口,整个应用程序的窗口。另外还有CView窗口。他们都是从CWnd派生出来的,所以都是窗口类。

正常情况下会在preCreateWindow这里才注册,但因为是是单文档MFC所以注册窗口类提前了。

调用CFramewnd中的Create函数,会进一步调用CWND的CreateEX函数。


用户可以修改CREATESTRUCT结构体调用PreCreateWindow,在创建窗口之前可以有机会去修改默认的窗口外观。


9.消息循环:主函数当中的RUN();

thrdcore.cpp当中有CWinThread::Run()

int CWinThread::Run()
{
	ASSERT_VALID(this);
	_AFX_THREAD_STATE* pState = AfxGetThreadState();

	// for tracking the idle time state
	BOOL bIdle = TRUE;
	LONG lIdleCount = 0;

	// acquire and dispatch messages until a WM_QUIT message is received.
	for (;;)
	{...
		// phase2: pump messages while available
		do
		{
			// pump message, but quit on WM_QUIT
			if (!PumpMessage())//Get Message, Translate Message, 
				return ExitInstance();
			...
		} while (::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE));
	}
}

10.消息循环:主函数当中的RUN();

11.窗口与窗口类

窗口类都是从CWnd派生来的。窗口类其实只是一个句柄。窗口销毁并不代表窗口类销毁。

#include <windows.h>

class CWnd
{
public:
	BOOL CreateEx(
			DWORD dwExStyle,//窗口的扩展风格
			LPCTSTR lpClassName,//指向注册类名的指针
			LPCTSTR lpWindowName,//指向窗口名称的指针
			DWORD dwStyle,//窗口风格
			int x,//窗口的水平位置
			int y,//窗口的垂直位置
			int nWidth,//窗口的宽度
			int nHeight,//窗口的高度
			HWND hWndParent,//父窗口的句柄
			HMENU hMenu,//菜单的句柄或是子窗口的标识符
			HINSTANCE hInstance,//应用程序实例的句柄
			LPVOID lpParam//指向窗口的创建数据
            );
	BOOL ShowWindow(int nCmdShow);
	BOOL UpdateWindow();
public:
	HWND m_hWnd;
};

BOOL CWnd::CreateEx(DWORD dwExStyle,//窗口的扩展风格
					LPCTSTR lpClassName,//指向注册类名的指针
					LPCTSTR lpWindowName,//指向窗口名称的指针
					DWORD dwStyle,//窗口风格
					int x,//窗口的水平位置
					int y,//窗口的垂直位置
					int nWidth,//窗口的宽度
					int nHeight,//窗口的高度
					HWND hWndParent,//父窗口的句柄
					HMENU hMenu,//菜单的句柄或是子窗口的标识符
					HINSTANCE hInstance,//应用程序实例的句柄
					LPVOID lpParam)//指向窗口的创建数据
{
  m_hWnd = ::CreateWindowEx(dwExStyle,lpClassName,lpWindowName,dwStyle,x,y,nWidth,
	                      nHeight,hWndParent,hMenu,hInstance,lpParam);
  if(m_hWnd!=NULL) 
	  return TRUE;
  else
	  return FALSE;
}


BOOL CWnd::ShowWindow(int nCmdShow)
{
 return	::ShowWindow(m_hWnd,nCmdShow);
}

BOOL CWnd::UpdateWindow()
{
 return	::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.CreateEx(...);
	wnd.ShowWindow(SW_SHOWNORMAL);
	wnd.UpdateWindow();
	...
}


12.添加button:

在CMainFrame中添加一个新的成员:CButton m_btn;然后在On_Create()里产生副窗口。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	if (!m_wndStatusBar.Create(this))
	{
		TRACE0("未能创建状态栏\n");
		return -1;      // 未能创建
	}
	m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

	
	m_btn.Create(TEXT("nino"),WS_CHILD|BS_DEFPUSHBUTTON,CRect(0,0,100,100),this,9);
	m_btn.ShowWindow(SW_SHOWNORMAL);

	return 0;
}

如果要在CView里添加button,而CView里没有ON_Create成员函数(用来响应窗口创建消息的函数)。

在CView里右键选择类向导。在消息里选择WM_CREATE并且添加处理程序就在CView里添加了ON_Create函数。














  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值