编写简单的 win32 程序
HWND:窗口句柄类型(可以理解为窗口的ID),不能写 HINSTANCE (应用程序实例句柄类型,理解为代表这个exe,程序只能有一个 exe,但一个 exe 可以有多个窗口)
传入 NULL 表示没有父窗口句柄,窗口是独立的
Windows --- 第一个Windows窗口程序_小雪菜本菜的博客-CSDN博客_窗口程序
#include <Windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow)
{
//父窗口句柄
MessageBox(NULL, L"这是一个Win32程序", L"温馨提示", MB_OK);
return 0;
}
学习的目的:
了解 Windows 程序运行的原理,图形是怎么绘制的,窗口是怎么产生的
MFC:微软封装的Windows的面向对象的C++类库,封装了Windows API
MFC 全称微软基础类库,英文全称 Microsoft Foundation Classes
把操作一系列窗口的函数封装到窗口类,把操作一系列菜单的函数封装到菜单类,把操作一系列绘图的函数封装到绘图类
优点:可重用性,不需要重复造轮子、简单
缺点:①做界面比较丑 ②如果要做漂亮的程序比较复杂 ③工业应用比较多
我们也可以自己封装一个简单的界面库
duilib 比较优秀的界面库(迅雷、百度音乐),底层就是 win32
easyX 不太完善,不太符合编程规范,内部采用 c++,官网案例都是以 c 语言写的,实现按钮比较麻烦,需要自己绘制,自己判断点击范围,没有控件的概念
学习 MFC 后可以自己编写界面库
MFC 三部曲
一、建立 CWinApp 派生类
#include <Windows.h>
//CwinAPP 由 MFC 框架实现 需要包含头文件
#include <afxwin.h>
//派生类公有继承 CwinAPP
class CMyAPP :public CWinApp
{
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, L"这是一个Win32程序", L"温馨提示", MB_OK);
return 0;
}
二、重写 CWinApp 里面的 InitInstance 虚函数
虚函数的作用就是为了让你实现多态:从基类执行到派生类,调用派生类中重写的功能
class CMyAPP :public CWinApp
{
public:
//在基类里面声明了是一个虚函数 在派生类里面可以不加virtual修饰
virtual BOOL InitInstance()
{
//弹框
MessageBox(NULL,L"这是一个MFC程序",L"温馨提示",MB_OK);
return TRUE;
}
};
afx:application framework 团队开发的 MFC 工程
三、定义 CWinPP 派生类的全局对象,这个全局变量的名字一般写为 theAPP
CMyAPP theApp;
fatal error C1189: #error: Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]
fatal error C1189: #error: WINDOWS.H already included. MFC apps must not #include <Windows.h>
在 mfc 工程中不再需要写 WinMain 函数
#include <afxwin.h>
class CMyAPP : public CWinApp
{
public:
//MFC的初始化过程/启动管理,相当于main函数/入口
BOOL InitInstance()
{
MessageBox(NULL, L"这是一个MFC程序", L"温馨提示", MB_OK);
//返回TRUE表示初始化成功
return TRUE;
}
};
//MFC应用程序核心 一个MFC应用程序有且只有一个应用程序核心对象
CMyAPP theApp;
#include <afxwin.h>
class CMyAPP :public CWinApp
{
public:
BOOL InitInstance()
{
MessageBox(NULL, L"这是一个MFC程序", L"温馨提示", MB_OK);
//返回TRUE表示初始化成功
return TRUE;
}
//退出实例:执行完之后做的一些清理工作
//派生类调用基类的ExitInstance
int ExitInstance()
{
//返回值是WinMain函数提供的退出代号 一般return 0;
return CWinApp::ExitInstance();
}
};
//MFC应用程序核心 一个MFC应用程序有且只有一个应用程序核心对象
CMyAPP theApp;
重写:在派生类中重写基类的函数
重载:函数名相同,参数类型、参数个数不一样
通过调试发现:首先执行 CMyAPP theApp;再执行 MessageBox(NULL, L"这是一个MFC程序", L"温馨提示", MB_OK);
#include <iostream>
using namespace std;
class CTest
{
public:
CTest()
{
cout << "这是构造函数" << endl;
}
};
//定义一个全局对象
CTest t;
int main()
{
cout << "这是main函数" << endl;
return 0;
}
先执行构造函数,再执行 main 函数
全局变量的生命周期是从程序开始到程序结束
当 Windows 程序加载器去读代码的时候,首先会给所有的全局变量分配内存,最终才会调用 main 函数入口进入程序
这是一个对象,对象的定义首先需要构造,先执行构造函数,才会到 main 函数
MFC 的内部是有 WinMain 函数的
接下来给程序做一个对话框
//构造函数重载
explicit CDialog(
LPCTSTR lpszTemplateName, //字符串资源模板/资源ID的字符串
CWnd* pParentWnd = NULL); //父窗口句柄
explicit CDialog(
UINT nIDTemplate, //资源ID的整数类型
CWnd* pParentWnd = NULL); //父窗口句柄
CDialog();
#include <afxwin.h>
#include "resource.h"
class CMyAPP :public CWinApp
{
public:
BOOL InitInstance()
{
//专门定义对话框的类 构造函数做了重载不需要MAKEINTRESOURCE 父窗口句柄可以缺省
CDialog dlg(IDD_MAIN_DLG);
//弹出一个模态对话框
dlg.DoModal();
return TRUE;
}
//退出实例:执行完之后做的一些清理工作
//派生类调用基类的ExitInstance
int ExitInstance()
{
//返回值是WinMain函数提供的退出代号 一般return 0;
return CWinApp::ExitInstance();
}
};
CMyAPP theApp;
如果需要更改标题、设置图标不好操作,需要建立 CDialog 的派生类,用类封装然后调用,比较简单、简洁
用派生类也可以弹出一个对话框
#include <afxwin.h>
#include"resource.h"
//派生类继承 CDialog 类
class CMyDlg : public CDialog
{
public:
//CMyDlg绑定了这个资源模板
CMyDlg() : CDialog(IDD_MAIN_DLG)
{
}
};
class CMyAPP :public CWinApp
{
public:
BOOL InitInstance()
{
//专门定义对话框的类 构造函数做了重载不需要MAKEINTRESOURCE 父窗口句柄可以缺省
CMyDlg dlg;
//弹出一个模态对话框
dlg.DoModal();
return TRUE;
}
//退出实例:执行完之后做的清理工作
//派生类调用基类的ExitInstance
int ExitInstance()
{
//返回值是WinMain函数提供的退出代号 一般return 0;
return CWinApp::ExitInstance();
}
};
CMyAPP theApp;