MFC进阶教程深入浅出版.笔记第1天 - yeyeye123

时间:2024-03-06 10:18:05

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;


}