平时也没机会接触到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
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
//窗口过程函数
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;
}