首页 > 其他分享 >MFC学习随笔

MFC学习随笔

时间:2023-05-05 16:56:33浏览次数:43  
标签:MFC 窗口 随笔 TEXT WM 学习 hwnd wc NULL

1.原理

image-20221111113204739

1.1设计窗口

	wc.cbClsExtra = 0; //类的额外内存
	wc.cbWndExtra = 0; //窗口额外内存
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置背景 - 白色
	wc.hCursor = LoadCursor(NULL, IDC_HAND); // 设置光标,如果第一个参数为NULL , 代表使用系统提供的光标
	wc.hIcon = LoadIcon(NULL, IDI_ERROR); //图标 如果第一个参数为NULL 代表使用系统提供的图标
	wc.hInstance = hInstance; // 应用程序实例句柄, 传入WinMain 中的形参即可
	//wc.IpfnWndProc = WindowProc; //回调函数 窗口过程
	wc.lpszClassName = TEXT("WIN"); // 指定窗口类名称
	wc.lpszMenuName = NULL; //菜单名称
	wc.style = 0;//显示风格 0代表默认风格

1.2 注册窗口类

	RegisterClass(&wc);

1.3创建窗口

	HWND hwnd = CreateWindow(
		wc.lpszClassName, //类名
		TEXT("WINDOWS"), //标题名
		WS_OVERLAPPEDWINDOW, //风格
		CW_USEDEFAULT, // x坐标 默认
		CW_USEDEFAULT, // y坐标 默认
		CW_USEDEFAULT, // 宽 默认
		CW_USEDEFAULT, // 高 默认
		NULL, //父窗口
		NULL, // hMeanu 菜单
		hInstance, // 实例句柄 hInstance
		NULL //附加值
	);

1.4显示和更新

	ShowWindow(hwnd, SW_SHOWNORMAL); //显示
	UpdateWindow(hwnd); //更新

1.5通过循环获取消息

image-20221111120936349

	MSG msg;
	while (true) {
		// 消息
		//第二个参数为NULL, 表示处理所有窗口的消息
		// 最小和最大的过滤的消息 , 填入0
		// 填0代表捕获所有消息
		if (GetMessage(&msg, NULL, 0, 0) == FALSE) {
			break;
		}
		//翻译消息
		TranslateMessage(&msg);
		//不为false
		//分发消息
		DispatchMessage(&msg);
	}

1.6处理窗口过程

//6. 处理消息(窗口过程) 使用回调函数
LRESULT CALLBACK WindowProc(
	HWND hwnd, // 消息所属的窗口句柄
	UINT uMsg, //具体消息名称 WM_XXX消息名
	WPARAM wParam, // 键盘附加消息
	LPARAM lParam //鼠标附加消息
)
{
	switch (uMsg) {
	case WM_CLOSE:
		DestroyWindow(hwnd); // 发送另一个消息 WM_DESTROY
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_LBUTTONDOWN: // 鼠标左键按下
		int xPos = LOWORD(lParam);
		int yPos = HIWORD(lParam);

		wchar_t buf[1024];
		wsprintf(buf,TEXT("x = %d , y = %d"), xPos, yPos);

		MessageBox(hwnd,TEXT("aaa"),TEXT("鼠标左键按下"),MB_OK);
		break;

	case WM_KEYDOWN: //键盘
		MessageBox(hwnd, TEXT("键盘按下"), TEXT("键盘按下"), MB_OK);
		break;

	case WM_PAINT: //绘图
		PAINTSTRUCT ps;// 绘图结构体
		HDC hdc = BeginPaint(hwnd, &ps);
		TextOut(hdc, 100, 100, TEXT("HELLO", strlen("HELLO")));
		EndPaint(hwnd,&ps);
	}

	return DefWindowProc(hwnd, uMsg, wParam, lParam);
		//返回值用默认处理方式
}

1.7完整代码

#include<Windows.h>


//6. 处理消息(窗口过程) 使用回调函数
LRESULT CALLBACK WindowProc(
	HWND hwnd, // 消息所属的窗口句柄
	UINT uMsg, //具体消息名称 WM_XXX消息名
	WPARAM wParam, // 键盘附加消息
	LPARAM lParam //鼠标附加消息
)
{
	switch (uMsg)
	{
		case WM_CLOSE:
			DestroyWindow(hwnd); // 发送另一个消息 WM_DESTROY
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		case WM_LBUTTONDOWN: // 鼠标左键按下
		{
			int xPos = LOWORD(lParam);
			int yPos = HIWORD(lParam);

			wchar_t buf[1024];
			wsprintf(buf, TEXT("x = %d , y = %d"), xPos, yPos);

			MessageBox(hwnd, TEXT("aaa"), TEXT("鼠标左键按下"), MB_OK);
			break;
		}
		case WM_KEYDOWN: //键盘
			MessageBox(hwnd, TEXT("键盘按下"), TEXT("键盘按下"), MB_OK);
			break;

		case WM_PAINT: //绘图
		{
			PAINTSTRUCT ps;// 绘图结构体
			HDC hdc = BeginPaint(hwnd, &ps);
			TextOut(hdc, 100, 100, TEXT("HELLO"), strlen("HELLO"));
			EndPaint(hwnd, &ps);
		}
	}

	return DefWindowProc(hwnd, uMsg, wParam, lParam);
	//返回值用默认处理方式
}

int WINAPI WinMain(
	HINSTANCE hInstance, // 应用程序实例句柄
	HINSTANCE hPrevInstance, //上一个应用程序句柄 在Win32环境下 一般为NULL 不起作用了
	LPSTR lpCmdLine,
	int nShowCmd // 显示命令 最大化 最小化 正常 

)
{
	//1. 设计窗口
	WNDCLASS wc;

	wc.cbClsExtra = 0; //类的额外内存
	wc.cbWndExtra = 0; //窗口额外内存
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置背景 - 白色
	wc.hCursor = LoadCursor(NULL, IDC_HAND); // 设置光标,如果第一个参数为NULL , 代表使用系统提供的光标
	wc.hIcon = LoadIcon(NULL, IDI_ERROR); //图标 如果第一个参数为NULL 代表使用系统提供的图标
	wc.hInstance = hInstance; // 应用程序实例句柄, 传入WinMain 中的形参即可
	wc.lpfnWndProc = WindowProc; //回调函数 窗口过程
	wc.lpszClassName = TEXT("WIN"); // 指定窗口类名称
	wc.lpszMenuName = NULL; //菜单名称
	wc.style = 0;//显示风格 0代表默认风格

	//2. 注册窗口
	RegisterClass(&wc);

	//3. 创建窗口
	HWND hwnd = CreateWindow(
		wc.lpszClassName, //类名
		TEXT("WINDOWS"), //标题名
		WS_OVERLAPPEDWINDOW, //风格
		CW_USEDEFAULT, // x坐标 默认
		CW_USEDEFAULT, // y坐标 默认
		CW_USEDEFAULT, // 宽 默认
		CW_USEDEFAULT, // 高 默认
		NULL, //父窗口
		NULL, // hMeanu 菜单
		hInstance, // 实例句柄 hInstance
		NULL //附加值
	);

	//4. 显示和更新
	ShowWindow(hwnd, SW_SHOWNORMAL); //显示
	UpdateWindow(hwnd); //更新

	//5. 通过循环取消息
	MSG msg;
	while (1) {
		// 消息
		//第二个参数为NULL, 表示处理所有窗口的消息
		// 最小和最大的过滤的消息 , 填入0
		// 填0代表捕获所有消息
		if (GetMessage(&msg, NULL, 0, 0) == FALSE) {
			break;
		}
		//翻译消息
		TranslateMessage(&msg);
		//不为false
		//分发消息
		DispatchMessage(&msg);
	}


	return 0;
}

2.MFC

2.1 包含头文件

image-20221111145416054

2.2 简单的一个MFC应用

2.2.1 代码简略

image-20221111145503518

2.2.2 在vs中设置使用共享DLL的MFC

image-20221111150534795

2.2.3 头文件代码

#include<afxwin.h>

class MyApp:public CWinApp //CWinApp应用程序类
{
public:
	//基类的虚函数 派生类只是重写
	//程序入口
	virtual BOOL InitInstance();
};

//框架类 CFrameWnd 子类
class MyFrame:public CFrameWnd //窗口框架类
{
public:
	MyFrame();

};

2.2.4 cpp文件代码

#include"mfc.h"

MyApp app;//有且只有一个全局的应用程序窗口类对象

BOOL MyApp::InitInstance()
{
	//1.创建框架类对象 创建窗口
	MyFrame* frame = new MyFrame;

	//显示和更新
	frame->ShowWindow(SW_SHOWNORMAL); // 显示窗口
	frame->UpdateWindow(); //更新窗口
	
	m_pMainWnd = frame; //保存指向应用程序的主窗口的指针
	return TRUE;

}

MyFrame::MyFrame()
{
	Create(NULL, TEXT("mfc"));
}

2.3 消息映射

2.3.1 简介

image-20221111163933863

2.3.2 简略代码

image-20221111163950556

2.3.3消息映射宏

image-20221111164214133

image-20221111164336139

2.3.4示例代码头文件

#include<afxwin.h>

class MyApp:public CWinApp //CWinApp应用程序类
{
public:
	//基类的虚函数 派生类只是重写
	//程序入口
	virtual BOOL InitInstance();
};

//框架类 CFrameWnd 子类
class MyFrame:public CFrameWnd //窗口框架类
{
public:
	MyFrame();

	//声明宏 提供消息映射机制
	DECLARE_MESSAGE_MAP()

	afx_msg void OnLButtonDown(UINT, CPoint);

	afx_msg void OnChar(UINT, UINT, UINT);

	afx_msg void OnPaint();
};

2.3.5示例代码cpp文件

#include"mfc.h"

MyApp app;//有且只有一个全局的应用程序窗口类对象

BOOL MyApp::InitInstance()
{
	//1.创建框架类对象 创建窗口
	MyFrame* frame = new MyFrame;

	//显示和更新
	frame->ShowWindow(SW_SHOWNORMAL); // 显示窗口
	frame->UpdateWindow(); //更新窗口
	
	m_pMainWnd = frame; //保存指向应用程序的主窗口的指针
	return TRUE;

}

//分界宏
BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)

	ON_WM_LBUTTONDOWN() //鼠标左键按下

	ON_WM_CHAR() //键盘

	ON_WM_PAINT()//绘图宏
END_MESSAGE_MAP()

MyFrame::MyFrame()
{
	Create(NULL, TEXT("mfc"));
}

void MyFrame::OnLButtonDown(UINT, CPoint point)
{
	//mfc里的字符数组
	TCHAR buf[1024];

	//wsprintf(buf, TEXT("x = %d, y = %d"), point.x, point.y);

	////对话框
	//MessageBox(buf);

	//mfc 中的字符串 CString
	CString str;
	str.Format(TEXT("x = %d,,, y = %d"), point.x, point.y);
	MessageBox(str);
}

void MyFrame::OnChar(UINT key, UINT, UINT)
{
	CString str;
	str.Format(TEXT("按下了 %c 键"), (char)key);

	MessageBox(str);
}

void MyFrame::OnPaint()
{
	CPaintDC dc(this); //指定绘图的设备

	dc.TextOutW(100, 100, TEXT("为了部落"));

	//画椭圆
	dc.Ellipse(10, 10, 100, 100);
}

2.4 字符编码

2.4.1 统计宽字节的字符串长度

image-20221111210736538

2.4.2 char*与CString之间的转换

image-20221111210817688

2.5 利用向导创建MFC

通过vs创建

image-20221111211808891

2.6 使用

image-20221111212533105

image-20221111212545641

选择所需要的窗口事件 , 右键添加

image-20221111212518698

如果有了OnDraw 再有OnPaint 会覆盖掉

  • MFC中后缀名为Ex的函数都是扩展函数
  • MFC中以Afx为前缀的函数都是全局函数 , 可以在程序的任何地方调用他们

view 视类 相片 MainFram类 相框

OnCreate相应创建窗口-设置风格属性等 Create创建窗口 WM_CREATE 消息是由Create函数调用的 一个窗口(Create)后会向系统发送WM_CREATE消息,OnCreate响应此消息

2.7 基于对话框进行操作

2.7.1 查找主窗口路径

image-20221111215234899

image-20221111215302201

2.7.2 模态对话框

image-20221113175958108

创建类 , 去创建一个和该按钮对应的类

image-20221113180607433

三种添加事件的方法

右键属性 - 控件事件

右键 - 添加事件处理程序

双击该按钮

image-20221113180839371

在头文件引入刚才创建的那个对话框的类的头文件

//弹出模态对话框
	CDlgExec dlg;
	dlg.DoModal();

2.7.3 非模态对话框

  • 创建视图对应类

  • 添加触发事件

  • 导入头文件

  • 写弹出的方法

    void CMFCApplication2Dlg::OnBnClickedButton2()
    {
    	// TODO: 在此添加控件通知处理程序代码
    
    	//弹出非模态对话框
    	CDlgShow dlg;
    	//创建
    	dlg.Create(IDD_DIALOG2);//创建一个窗口只能创建一次 , 多次会崩
    	//显示
    	dlg.ShowWindow(SW_SHOWNORMAL);
    
    }
    

因为生存周期的问题 , 方法执行完这个窗口类会释放, 所以需要在大对话框的头文件中去申明他

image-20221113191435872

同时 大的对话框的头文件中, 需要引入这个非模态对话框的头文件

image-20221113191629290

而且这只能创建一次 , 再创建一次会崩溃

所以需要放到初始化函数里,防止二次执行创建操作

找到初始化方法

image-20221113191916677

image-20221113192032996

后面其他UI组件的用法其实大差不差直接看着文档写或者就看着demo代码来写就行了,懒得记录了,有一说一 , 这玩意是真的辣鸡

标签:MFC,窗口,随笔,TEXT,WM,学习,hwnd,wc,NULL
From: https://www.cnblogs.com/jy00/p/17374605.html

相关文章

  • ExtJs学习之Button(08)
    最少代码:HelloWorld.html源文件下载点击事件<linkrel="stylesheet"href="theme-gray-all.css"><!--样式--><scriptsrc="ext-all.js"></script><!--行为--><script>Ext.onReady(function(){/*-自己写的代码--开始--......
  • JavaSpring学习的报错查看
    警告:Exceptionencounteredduringcontextinitialization-cancellingrefreshattempt:org.springframework.beans.factory.BeanCreationException:Errorcreatingbeanwithname'bookService'definedinclasspathresource[applicationContext.xml]:C......
  • JavaScript学习汇总
    ExtJs学习之Button(08)uniGUI学习之脱离Delphi直接写ExtJS从入门到精通04官方文档查找办法_例如_Ext.Window(48)uniGUI学习之脱离Delphi直接写ExtJS从入门到精通03自定义函数_调用顺序(47)uniGUI学习之脱离Delphi直接写ExtJS从入门到精通02Ext.Panel创建后_调用的几种方法(46)......
  • 人工智能学习入门学习笔记 1
    目前人工智能算法分哪几类,哪些是需要训练的?人工智能算法通常可以分为以下几类:1. 监督学习(SupervisedLearning):需要有标注数据,即输入数据与输出结果是已知的,算法通过学习这些数据来建立一个输入到输出的映射模型。例如,图像分类、自然语言处理和预测等任务。2. 无监督学习(Unsupervi......
  • FFT学习笔记
    快速傅里叶变换多项式定义不严谨定义:形如\(f(x)=\sum\limits_{i=0}^{n}a_ix^i\)的式子为多项式。定义(fromOIWiki):对于求和式\(\suma_nx^n\),如果是有限项相加,称为多项式,记作\(f(x)=\sum\limits_{n=0}^ma_nx^n\)。次数:对于多项式\(F(x)=\sum\limits_{i=0}^{n......
  • wireshark(抓包)学习
    1、Wireshark简介Wireshark(前称Ethereal)是一个免费开源的网络数据包分析软件。网络数据包分析软件的功能是截取网络数据包,并尽可能显示出最为详细的网络数据包数据。Wireshark官方网站:https://www.wireshark.org,可以去官网查看这款软件的详细信息2、Wireshark基本使用方法......
  • HttpRunner 4.x 学习2 - 快速创建项目
    执行 hrpstartprojectdemo  命令,即可初始化指定名称的项目工程。hrpstartprojectauto快速创建项目demo├──.env是环境配置文件├──.gitignore传git仓库时忽略文件├──debugtalk.py辅助函数功能文件├──har辅助函数功能文件......
  • 云原生学习笔记-DAY3
    etcd进阶和K8s资源管理1etcd进阶1.1etcd配置etcd没有配置文件,配置是从serivce文件里面加载参数实现的1.2etcd选举机制1.2.1选举简介etcd基于Raft算法进行集群角色选举,使用Raft的还有Consul、InfluxDB、kafka(KRaft)等。Raft算法是由斯坦福大学的DiegoOngaro(迭戈......
  • httprunner 4.x学习 - 3.variables 变量声明与引用
    前言在HttpRunner中,支持变量声明(variables)和引用($var或${var})的机制。在config和step中均可以通过variables关键字定义变量,然后在测试步骤中可以通过$变量名称的方式引用变量。区别在于在config中定义的变量为全局的,整个测试用例(testcase)的所有地方均可以引......
  • vue3学习第一课
    1,先安装npmbrewinstallnpmnpminitvite-appvue3demmocdvue3demmonpminstallnpmrundev ......