MFC进阶教程深入浅出版.笔记第1天
平时也没机会接触到MFC的代码,这次也是项目使然,手上项目涉及到MFC,感觉有点意思,所以在b站找了视频学习,没有上手操作过,只是走马观花,大致了解了这个代码的流程,现在奉上b站的视频链接:MFC进阶教程深入浅出版
以下是课程笔记:
为什么要学习MFC?
MFC:徽软基础类库(英语:Microsoft Foundation Classes.简称MFC)
如果你是在windows平台上做GUI开发,MFC是一个很好的选择(Qt跨平台),毕竟windows累积用户群庞大,市场接受程度高。
但是,学习MFC不仅仅要学习用MFC,还要学习MFC的框架设计思想。
如果仅仅会用MFC的话,可能在找工作的时候,一旦工作内容离开了MFC,就什么也不会了。学习任何东西都是一样的,学的是方法,而不仅仅是某个技术本身,因为技术肯定不停地更新的,你今天学的现在能用上,但是谁也不能保证以后会怎么样,但是万变不离其中,懂得了方法,学什么都一样。
MFC作为一个诞生了20年的成熟的框架,其设计思想是很值得我们学习的。当然,如果和Qt、Andorid和ios那种更加“现代化”框架相比,MFC确实显得有点不合时宜。
但是,如果你祖略读一读MFC源代码就会发现MFC的厉害之处。无法想象MFC在那个连C++的STL(Standard Template Library,标准模板库)都还没出现的年代,就用泛型编程技术写出了CList、CArray、CMap等容器。MFC不仅仅是将面向过程的API封装为面向对象的形式,他还在背后做了很多事情,包括简化一些过程,提高一些稳定性(当然主要是针对于Windows平台)。
很多公司在一些做了很久的项目上,往往都是有自己的类库、自己的框架,我们只需要在其基础上不断的完善和扩展。如果你不了解类库,你是根本无从下手。这也是我们要学习类库、框架设计的原因。
-------------------------------------------------
课程安排
第一天(Win消息机制、SDK编程基础):
1、基本概念介绍(SDK、API、句柄、消息队列、WinMain函数)
2、第一个windows界面程序(WinAPI)
3、消息循环和窗口过程函数
4、第一个MFC程序(CWinApp、CFrameWnd)
5、消息映射
6、unicode宇符集介绍
7、根据向导创建MFC应用程序
8、MFC应用程序几个重要函数的介绍
9、事件的添加和删除
第二天(绘图、文本编程、菜单):
1、简单绘图
2、画刷和画笔的使用
3、插入符使用
4、字体操作
5、菜单相关操作
第三天(对话框、常用控件):
1、动态图标制作(定时器)
2、对话框(模态和非模态)
3、基于对话框的编程
3、基于对话框的编程
4、常用控件的使用
第四天(文档和视图、数据库编程):
1、文档视图结构介绍
2、CArchive类的使用
3、MFC odbc操作数据库
第五天~第六天:药品库存管理系统
-------------------------------------------------
一、基本概念
SDK:软件开发工具包,Simple-Develop-Key,简单的开发钥匙
JDK:Java开发工具包,Java Development Kit,是 Java 语言的软件开发工具包
IDE:VS qt
API:应用程序接口
WINAPI: windows平台下的系统调用,windows.h,调用系统提供的特殊接口,得到系统的资源
窗口:父窗口和子窗口,客户区和非客户区
句柄:结构体变量,控件的标志,窗口句柄HWND,图标句柄:HICO
消息队列
消息
窗口过程函数
main()
WinMain() //WINAPI入口地址
二、winAPI窗口程序
1、定义入口函数WinMain()
2、创建一个窗口
a)设计窗口类WNDCLASS(给成员变量赋值)
b)注册窗口类
c)创建窗口
d)显示和更新窗口
3、消息循环
4、窗口过程函数
MSDN Library:winAPI,MFC//关键词查找区分:TextOut(windows)/TextOut Method(MFC)
MFC参考文档(中文) //很多时候你创建一个类,你需要看它的构造函数,考虑需不需要给他传参
三、一个MFC程序(纯代码)(#include <afxwin.h>)
1)应用程序类 CWinApp
2)框架类 CFrameWnd
class MyApp: public CWinApp
{
public:
//MFC程序的入口地址
virtual BOOL InitInstance();
};
class MyFrame: public CFrameWnd
{
public:
MyFrame();
private:
};
1)有且只有一个全局的应用程序类对象
2)在程序入口函数实现功能InitInstance()//内部底层函数已封装,看不到main()和winmain()
A) 给框架类MyFrame对象动态分配空间(自动调用它的构造函数)
a) 框架类MyFrame对象构造函数函数里创建窗口 CWnd::Create
B) 框架类对象显示窗口 CWnd::ShowWindow
C) 框架类对象更新窗口 CWnd::UpdateWindow
D) 保存框架类对象指针 CWinThread::m_pMainWnd //不是我们要用,而是mfc后面要用到窗口这个指针
事件处理:
消息映射
1、所操作类.h中,声明消息映射宏
DECLARE_MESSAGE_MAP()
2、对应的.cpp定义宏
BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)//派生类名,基类名
ON_WM_LBUTTOND() //消息映射入口标志
END_MESSAGE_MAP()
3、对应类.h中,消息处理函数的声明
4、对应.cpp 消息处理函数的定义
步骤:类视图里面 → 选择所需类 → 右击 → 属性 → 消息 → WM_LBUTTONDOW → ADD
四、根据向导创建工程
1、文档视图结构
文档类:它是一个类,这个类专门来存储加载(读写)数据 //可自己定义,后台处理,没有控件
视图类:它是一个类,这个类专门来显示和修改数据
框架类:一个容器,这个容器装了视图
2.几个比较重要的函数
应用程序类CWinApp:
InitInstance():程序的入口地址
框架类CFrameWnd:
PreCreateWindow():创建窗口之前调用
OnCreate():创建窗口后,触发WM_CREATE,它是WM_CREATE消息的处理函数
视图类CView:
OnDraw():绘图
WM_PAINT消息处理函数OnPaint() → 内部调用OnDraw()
OnPaint()和OnDraw()同时存在,只有OnPaint()有效
OnCreate():创建窗口后自动调用
3.事件的添加和删除(消息处理函数)
a)框架和视图的区别
步骤:类视图里面 → 选择所需类 → 右击 → 属性 → 消息 → WM_LBUTTONDOW → ADD
框架就相当于容器,容器放视图
视图相当于壁纸
四、字符集
ANSI 多字节,单字节
char p[]="abcdet"; //一个字符一个字节
unicode 宽字节,一个字符2个字节
TCHAR *p = L"abc";//一个字符2个字节
wcslen (p);
MFC:
TCHAR:自动适应字节(条件编译ANSI、unicode),相当于char,但比char智能。
TEXT()
_T()
五、拓展
afx_xxxx:全局函数,不属于某个类特有的
xxxEx/xxxW,拓展函数,属性可能有改进。
TextOut,TextOutW
MFC:
类名和函数名字:单词首字母大写
class MyClass{};
void SetName(){}
//形参
isFlag
isPressTest
成员变量
m_xxxx
m_hWnd
onchar 敲键盘就响应
第一天作业
1、请画图描述一下windows平台下消息循环时怎样的一个过程?
2、通过WinAPI实现如下程序
a)左击窗口,获取点击的坐标,通过对话框显示出来
提示:a)如何获取,查看MSDN,通过消息查看,WM_XXX,window message(window信息)
b)windows下,格式化字符串
TCHAR buf[1024] = { 0 };
wsprintf(buf, TEXT("x = %d, y = %d"), 10, 10);
b)键盘按下(上,下,左,右),通过对话显示出来
键盘值的宏(MSDN):VK_XXX,virtual key(虚拟按键)首字母,或者通过ASCII值比较
3、WinApi和MFC有什么区别和联系?
非向导创建MFC程序(纯代码)
//visual stdio c++ àwin32项目
#include<windows.h> //窗口过程函数 LRESULT CALLBACK DealMessage(HWND hWnd,//窗口句柄.消息所属的窗口 UINT uMsg,//消息标志 WPARAM wParam,//附加信息 LPARAM lParam) { switch(uMsg) { case WM_LBUTTONDOWN://鼠标左键按下 MessageBos(hWnd, TEXT("ABC"), TEXT("鼠标左键按下"), MB_OK); break; case WM_DESTROY: PostQuitMessage(2);//WM_QUIT,给主函数return msg.wParam break; case WM_PAINT: { PAINTSTRUCT ps;//绘图结构体 HDC dc = BeginPaint(hWnd, &ps); TCHAR *p = L"aaaaaa"; TextOutW(dc, 30, 30, p, wcslen(p)); EndPaint(hWnd, &ps); break; } default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; } //CALLBACK int WINAPI WinMain(HINSTANCE hInstance,//应用程序实例 HINSTANCE hPrevInstance,//上一个应用程序实例,不用 LPSTR lpCmdLine,//命令行参数 int nShowCmd//窗口显示的样式,最大化,最小化 ) { /* 1.定义入口函数WinMain() 2.创建一个窗口 a)设计窗口类WNDCLASS(给成员变量斌值) b)注册窗口类 c)创建窗口类 d)显示和更新窗口 3.消息循环 4.窗口过程函数 */ //a)设计窗口类WNDCLASS(给成员变量赎值) WNDCLASS wc; wc.cbClsExtra = 0;//类的附加信息 wc.cbWndExtra = 0;//窗口附加信息 //获取系统默认的白色画刷 wc.hbrfackxround =(HBRUSH)GetStockObject(WHITE_BRUSH);//背景色,必须写 //wc.hCursor = NULL;//使用默认 wc. hCursor = LoadCursor(NULL, IDC_HELP);//加载系统默认光标 //wc.hlcon = NULL; wc.hIcon = LoadIcon(NULL,IDI_WARNING);//加载系统歇认图标 wc.hInstance = hInstance;//应用程序实例 wc.lpfnWndProc = DealMessage;//窗口过程函数名字,消息处理函数 wc.lpszClassName = TEXT("abc");//类的名字 wc.lpszMenuName = NULL;//菜单名字 wc.style = nCmdShow;//显示风格 //b)注册窗口类,告诉系统窗口过程函数的入口地址 RegisterClass(&wc); //c)创建窗口类 HWND hWnd = CreateWindow(TEXT("abc"), TEXT("hello,world"), WS_OVERLAPPEDWINDOW, CM_USEDEFAUT, CM_USEDEFAUT, CM_USEDEFAUT, CM_USEDEFAUT, NULL, NULL, hInstance, NULL); //d)显示和更新窗口 ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); //3.消息循环 MSG msg; //如果接受到WM_QUIT,返回0,退出 //如果出错,返回-1,不退出 while(GetMessage(&msg, NULL, 0, 0)) { //翻译工作 //虚拟按键转为标准字符WM_CHAR TranslateMessage(&msg); //给操作系统分发消息 DispatchMlessage(&msg); } return msg.wParam; }