【MFC】程序框架及基础知识

1. 首先,贴一个简单的Win32的Hello World程序,这是学MFC的基础。

如果没有学过Win32,请自行补充相关知识。

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nShowCmd)
{
    static TCHAR lpszAppName[] = TEXT("HelloWin");
    HWND      hwnd;
    MSG       msg;
    WNDCLASS  wc;

    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = lpszAppName;

    // 注册窗口类
    if (!RegisterClass(&wc))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
            lpszAppName, MB_ICONERROR);
        return 0;
    }

    // 创建应用程序主窗口
    hwnd = CreateWindow(lpszAppName,
        TEXT("The Hello Program"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);

    // 显示窗口
    ShowWindow(hwnd, nShowCmd);
    UpdateWindow(hwnd);

    // 消息循环
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

//
// 窗口过程函数
//
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;
    PAINTSTRUCT ps;
    RECT        rect;

    switch (message)
    {
    case WM_CREATE:
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);
        DrawText(hdc, TEXT("Hello World!"), -1, &rect,
            DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}

2. MFC其实是微软对Win32 API的一个封装。

创建一个简单的MFC程序如Test后,整个程序的初始化及运行流程大致下:

CTestApp中定义theApp全局对象

—>执行父类CWinApp构造函数

—>执行子类本身构造函数

—>调用AfxWinMain函数

—>Afx函数中调用initInstance函数,包括注册窗口类、创建窗口、显示窗口等

—>进行消息循环

3. 程序框架

建立一个单文档MFC示例程序,程序就会包含:

CTestApp——应用程序类

CMainFrame、CTestView——窗体类,后者可看做前者的子类

CTestDoc——文档类

4. 注意事项:

MFC其实是对Win32 API函数的一些封装,比如CWnd类,我们自己也可以模拟这个封装过程。

下面是我自己写的一个模拟封装程序:

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

class CMyWnd
{
public:
	BOOL MyCreateWindow(
	  LPCTSTR lpClassName,
	  LPCTSTR lpWindowName,
	  DWORD dwStyle,
	  int x,
	  int y,
	  int nWidth,
	  int nHeight,
	  HWND hWndParent,
	  HMENU hMenu,
	  HANDLE hInstance,
	  PVOID lpParam
	);

	BOOL MyShowWindow(int nCmdShow);

	BOOL MyUpdateWindow();

	HWND GetHwnd();

private:
	HWND m_hwnd;
};

BOOL CMyWnd::MyCreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle,
							int x,int y, int nWidth, int nHeight,
							HWND hWndParent, HMENU hMenu, HANDLE hInstance, LPVOID lpParam)
{
	m_hwnd = ::CreateWindow(lpClassName,lpWindowName,dwStyle,
							x,y,nWidth,nHeight,hWndParent,hMenu,(HINSTANCE)hInstance,lpParam);
	if(NULL == m_hwnd)
		return FALSE;
	else
		return TRUE;
}

BOOL CMyWnd::MyShowWindow(int nCmdShow)
{
	return ::ShowWindow(m_hwnd, nCmdShow);
}

BOOL CMyWnd::MyUpdateWindow()
{
	return ::UpdateWindow(m_hwnd);
}

HWND CMyWnd::GetHwnd()
{
	return this->m_hwnd;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
	MSG msg;
	WNDCLASS wndclass;
	CMyWnd wnd;
	TCHAR szName[] = TEXT("Class Test");
	//HWND hwnd;

	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hInstance = hInstance;
	wndclass.lpfnWndProc = WndProc;
	wndclass.lpszClassName = szName;
	wndclass.lpszMenuName = NULL;
	wndclass.style = CS_HREDRAW | CS_VREDRAW;

	if(!RegisterClass(&wndclass))
	{
		MessageBox(NULL, TEXT("Need Window NT"), TEXT("Title"), MB_OK);
		return 0;
	}

	//wnd = new CMyWnd;
	wnd.MyCreateWindow(szName, TEXT("Window Test"), WS_OVERLAPPEDWINDOW,
					   CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
					   NULL, NULL, hInstance, NULL);

	//hwnd = wnd->GetHwnd();

	wnd.MyShowWindow(nShowCmd);
	wnd.MyUpdateWindow();

	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}

	return DefWindowProc(hwnd, message, wParam, lParam);
}

可见,CMyWnd窗口类其实 与 窗口无直接关系,他们之间的联系其实只是m_hwnd的存在;

窗口被销毁,并不会影响窗口类,微软MFC封装的CWnd类也是一样;

当然,我们这里只是简单的模拟,并不完善,当窗口类销毁时,MFC中会把相应的窗口也销毁。

5. 向MFC程序添加控件

这个比较简单,可以再CMainFrame类中定义一个CButton的对象,然后在该类的构造函数中初始化这个成员对象。

当然,也可以在CTestView类写,可以给它写个相应WM_CRAETE的OnCreate函数即可;

首先在CTestView头文件中添加:

private:
	CButton m_btn;

然后在CTestView定义文件中添加:

// CTest1View message handlers

int CTest1View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	m_btn.Create(TEXT("World"), WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, CRect(0,0,50,20), this, 124);

	return 0;
}

这个过程其实可以使用VC自带的生成工具来写,不用我们完全手动编辑。

时间: 2024-08-06 11:46:39

【MFC】程序框架及基础知识的相关文章

黑马程序员——集合基础知识(泛型)

集合:泛型基础知识 泛型.(泛型就是类型参数化,默认的时object,虽然不用强制类型转换,这个就要你自己去写特性方法,比如compareto是string的特有方法吧,你可以写但是父类肯定调用不了) itnex t对象都是obj要使用对象的特性功能必须强.编译的时候没问题,因为都不知道你会传什么对象,你橙子也可以当作apple来传,设计的时候并不知道! 泛型作用.1.用于解决安全问题.运行时期出现的问题classcastexception转移到编译时期.2.迭代器里面的itnext()不用强转

黑马程序员——集合基础知识(Collection)

集合基础知识 数组:长度固定,可存基本数据和对象. 集合:只能放对象,不固定.容器也有共性,不断抽取成一个体系,集合框架.参阅顶层创建底层.顶层是collection.collection里有两个常见的接口,List和Set.常见集合有Arraylist,linkedlist,vector,hashSet TreeSet.为什么会出现这么多的容器呢,因为每一个容器对数据的存储方式都有不一样,.这个存储方式称之为数据结构!!因为他们的特点不一样 list因为有脚标存储和删除的效率很低,Set的效率

黑马程序员——集合基础知识(Map)

Map概念 要同时存储两个元素,他们之间有映射关系,每个键不能重复,每个键只能映射到一个值. 存储键值对,并且键是唯一的. 1.添加. put()如果添加的键原来有值,后添加的值会覆盖前面的值,并返回之前的值. 2.删除 remove()按键删除. 3.判断 4.获取 get(object key) size() value()拿值value返回的是值的集合... HashTable 底层是哈西数据结构,不可以存入null键null值,线程同步. HashMap 底层是哈西表数据结构,允许使用n

黑马程序员——Java基础知识之多线程协同

多线程协同 线程间的通讯:对资源的操作动作不同,比如说两个卡车一个拉煤一个装煤,但是他们共享了一个资源. 怎么样把这个资源拿出来?怎样把车装满?这个资源当然是一个类,他里面的组成元素就是对象!!现在我们就要有操作对象的思想了,用对象把这车装满,现在一车装一个对象. 等待唤醒机制: 用的不是sleep是wait.flag标记,这是两人沟通的方式.其实每个标记就要做一次等待或者notify,判断wait,改值notify.线程池.notify唤醒里面的线程,按顺序唤醒.wait和notify必须用在

黑马程序员_java基础知识精华总结

本文总结了JAVA中的基础知识部分,具体包括:1.对象的初始化:2.2.继承时,对象的初始化过程:3.关于构造方法:4.有关public.private和protected:5.抽象类:6.final关键字:7.接口interface:8.多重继承:9.接口的嵌入:10.类的嵌入:11.异常类. 1.对象的初始化 (1)非静态对象的初始化在创建对象时,对象所在类的所有数据成员会首先进行初始化.基本类型:int型,初始化为0.如果为对象:这些对象会按顺序初始化.※在所有类成员初始化完成之后,才调用

黑马程序员_Java基础知识

java基础知识 1.Dos命令: dir:列出当前目录下所有的的文件及文件夹 md:创建目录 rd:删除目录 cd:进入指定mul cd\:返回到根目录 cd..:退到上级目录 del:删除文件 exit:退出dos命令行 *:通配符 help:帮助命令 2.path系统变量:系统中应用程序所在的路径 临时配置的环境变量的方式:用set命令完成 set:用于查看本机中所有环境变量的信息 set 变量名:查看具体的一个环境变量的值 set 变量名=:清空变量的值 set 变量名=具体值:赋值 在

黑马程序员_JavaSE基础知识总结一:Java编程前奏

------ android培训.java培训.期待与您交流! ---------- 一.计算机概述 1.软硬件与语言 根据冯·诺依曼体系结构,计算机可以划分为五个部分:存储器.运算器.控制器.输入设备.输出设备.我们可以更加简单地把计算机划分为软硬件两个部分,硬件是指计算机系统中由电子,机械和光电元件等组成的各种物理装置,这些物理装置按系统结构的要求构成一个有机整体为计算机软件运行提供物质基础,常见如显示器.扫描仪.键盘等:软件是一系列按照特定顺序组织的计算机数据和指令的集合,又可分为系统软件

黑马程序员-java基础知识+环境搭建和变量配置

一.dos命令 软件:是一系列按照特定顺序组织的计算机数据和指令的集合. 交互方式:图形化界面.命令行方式 dir  directory 显示文件和子目录 cd   change directory 改变当前的路径(进入指定目录) md   make directory 新建一个子目录(文件夹) rd   remove directory 删除一个子目录(文件夹) cd.. 返回上一文件夹 cd/  返回根目录(磁盘) del  delete 删除文件 (不走回收站)   del *.txt(删

TP框架---thinkphp基础知识

php框架    发瑞 一.真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维护项目,十分困难,代码风格不一样) 项目稳定的运行阶段 项目停止运行(旧项目的人员已经全部离职,新人开发新项目)   二.问题: 1. 多人开发项目,分工不合理,(html   php   mysql) 2. 代码风格不一样,后期维护十分困难 3. 项目生命周期十分短,项目生命没有延续性,造成资源浪费.人员浪费