孙鑫VC++第一章 Windows内部运行原理

news2024/11/27 15:51:52

1. Windows应用程序,操作系统,计算机硬件之间的相互关系

请添加图片描述

  • 1箭头表示操作系统控制输出设备
  • 2箭头表示操作系统可以得到输入设备信息
  • 3箭头表示应用程序通知操作系统执行具体操作 操作系统提供给应用程序的接口 API
  • 4箭头表示输入设备变化告诉应用程序

Windows操作系统提供了1000多种API函数
CreateWindow为程序创建一个窗口的。
ShowWindow:用于显示窗口。
LoadIcon:用于加载图标。
SendMessage:用于发送消息。
句柄:图标句柄(HICON)光标句柄(HCURSOR)画刷句柄(HBRUSH)

2. 消息与消息队列

  • MSG结构体:
//消息是由MSG结构体来表示的。
LRESULT CALLBACK WinSunProc(
	HWND hwnd,  		// handle to window表示消息所属的窗口
	UINT uMsg,    		// message identifier指定了消息的标识符
	WPARAM wParam,	    // first message parameter指定消息的附加信息
	LPARAM lParam 		// second message parameter指定消息的附加信息
);

3. WinMain函数的定义:

//WinMain是Windows程序的入口点函数。
int WINAPI WinMain(
	HINSTANCE hInstance,  		// handle to current instance该程序当前运行的实例的句柄
	HINSTANCE hPrevInstance,		// handle to previous instance当前实例的前一个实例的句柄
	LPSTR lpCmdLine,       		// command line一个以空终止的字符串,指定传递给应用程序的命令行参数。
	int nCmdShow           			// show state指定程序的窗口应该如何显示
)

4. 窗口的创建

创建一个完整的窗口,需要经过下面几个操作步骤:
1.设计一个窗口类;
2.注册窗口类;
3.创建窗口;
4.显示及更新窗口。

4.1 设计一个窗口类:

typedef struct _WNDCLASS                //窗口类
{ 
//窗口的特征就是由WNDCLASS结构体来定义的。
	//设计一个窗口类
	WNDCLASS wndcls;
	wndcls.cbClsExtra = 0; //为系统中的每一个窗口类管理一个 WNDCLASS 结构。不应使用(应为零)
	wndcls.cbWndExtra = 0; //为每一个窗口管理一个内部数据结构,不应使用(应为零)
	wndcls.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); //hbrBackground指定窗口类的背景画刷句柄。背景色
	wndcls.hCursor = LoadCursor(NULL, IDC_ARROW); //hCursor 指定窗口类的光标句柄。当鼠标悬停在窗口上时的游标
	wndcls.hIcon = LoadIcon(NULL, IDI_QUESTION); //hIcon指定窗口类的图标句柄。框架窗口的图标
	wndcls.hInstance = hInstance; //hInstance指定包含窗口过程的程序的实例句柄。自动填充 AfxGetInstanceHandle,应用程序实例句柄由WinMain函数传进来
	wndcls.lpfnWndProc = WinSunProc; //函数指针,指向窗口过程函数。窗口进程,必须是 AfxWndProc
	wndcls.lpszClassName = "have a happy day"; // lpszClassName 是一个以空终止的字符串,指定窗口类的名字。类名
	wndcls.lpszMenuName = NULL; //lpszMenuName是一个以空终止的字符串,指定菜单资源的名字。不应使用(应为NULL)
	wndcls.style = CS_HREDRAW | CS_VREDRAW;//style指定这一类型窗口的样式,当窗口水平方向垂直方向上的高度发生变化时,将重新绘制整个窗口。
} WNDCLASS, *PWNDCLASS;

第一个成员变量style指定这一类型窗口的样式,常用的样式如下:
■ CS_HREDRAW
当窗口水平方向上的宽度发生变化时,将重新绘制整个窗口。当窗口发生重绘时,窗口中的文字和图形将被擦除。如果没有指定这一样式,那么在水平方向上调整窗口宽度时,将不会重绘窗口。
■ CS_VREDRAW
当窗口垂直方向上的高度发生变化时,将重新绘制整个窗口。如果没有指定这一样式,那么在垂直方向上调整窗口高度时,将不会重绘窗口。
■ CS_NOCLOSE
禁用系统菜单的Close命令,这将导致窗口没有关闭按钮。
■ CS_DBLCLKS
当用户在窗口中双击鼠标时,向窗口过程发送鼠标双击消息。

4.2 注册窗口类:

//在设计完窗口类(WNDCLASS)后,需要调用 RegisterClass 函数对其进行注册,在注册成功后,才可以创建该类型的窗口。
RegisterClass(&wndcls);

4.3 创建窗口:

//创建窗口,定义一个变量用来保存成功创建窗口后返回的句柄
HWND hwnd;
hwnd = CreateWindow("have a happy day", "hello",WS_OVERLAPPEDWINDOW, 10, 10, 500, 500, NULL, NULL, hInstance, NULL);
  • lpClassName指定窗口类的名称。
  • lpWindowName指定窗口的名字。
  • dwStyle 指定创建的窗口的样式。
  • dwStyle参数:
/*
 * Common Window Styles
 */
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED     | \
                             WS_CAPTION        | \
                             WS_SYSMENU        | \
                             WS_THICKFRAME     | \
                             WS_MINIMIZEBOX    | \
                             WS_MAXIMIZEBOX)
 
#define WS_POPUPWINDOW      (WS_POPUP          | \
                             WS_BORDER         | \
                             WS_SYSMENU)
 
#define WS_CHILDWINDOW      (WS_CHILD)

要注意区分 WNDCLASS 中的 style 成员与CreateWindow函数的dwStyle参数,前者是指定窗口类的样式,基于该窗口类创建的窗口都具有这些样式,后者是指定某个具体的窗口的样式。WS_OVERLAPPEDWINDOW是多种窗口类型的组合。

  • 窗口类型:
    ■ WS_OVERLAPPED:产生一个层叠的窗口,一个层叠的窗口有一个标题栏和一个边框。
    ■ WS_CAPTION:创建一个有标题栏的窗口。
    ■ WS_SYSMENU:创建一个在标题栏上带有系统菜单的窗口,要和 WS_CAPTION类型一起使用。
    ■ WS_THICKFRAME:创建一个具有可调边框的窗口。
    ■ WS_MINIMIZEBOX: 创 建 一 个 具 有 最 小 化 按 钮 的 窗 口, 必 须 同 时 设 定WS_SYSMENU类型。
    ■ WS_MAXIMIZEBOX: 创 建 一 个 具 有 最 大 化 按 钮 的 窗 口, 必 须 同 时 设 定WS_SYSMENU类型。

  • x、y、nWidth、nHeight :分别指定窗口左上角的 x 坐标、y坐标、窗口的宽度和高度。
    如果参数x 被设为 CW_USEDEFAULT,那么系统为窗口选择默认的左上角坐标并忽略y参数。如果参数nWidth被设为CW_USEDEFAULT,那么系统为窗口选择默认的宽度和高度,参数nHeight被忽略。

  • 参数hWndParent指定被创建窗口的父窗口句柄。
    对父窗口的操作对子窗口的影响

  • 参数hMenu指定窗口菜单的句柄。

  • 参数hInstance指定窗口所属的应用程序实例的句柄。

  • 参数lpParam:作为WM_CREATE消息的附加参数lParam传入的数据指针。

  • 如果窗口创建成功,CreateWindow函数将返回系统为该窗口分配的句柄,否则,返回NULL。注意,在创建窗口之前应先定义一个窗口句柄变量来接收创建窗口之后返回的句柄值。

4.4 显示及更新窗口

//显示及刷新窗口
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd);

1. 显示窗口

调用函数ShowWindow来显示窗口:

  • hWnd就是在上一步骤中成功创建窗口后返回的那个窗口句柄。
  • nCmdShow指定了窗口显示的状态:
    ■ SW_HIDE:隐藏窗口并激活其他窗口。
    ■ SW_SHOW:在窗口原来的位置以原来的尺寸激活和显示窗口。
    ■ SW_SHOWMAXIMIZED:激活窗口并将其最大化显示。
    ■ SW_SHOWMINIMIZED:激活窗口并将其最小化显示。
    ■ SW_SHOWNORMAL:激活并显示窗口。如果窗口是最小化或最大化的状态,则系统将其恢复到原来的尺寸和大小。应用程序在第一次显示窗口的时候应该指定此标志。

2. 更新窗口

在调用ShowWindow函数之后,紧接着调用UpdateWindow来刷新窗口。
UpdateWindow函数的原型声明如下:

BOOL UpdateWindow(
    HWND hWnd   // CreateWindow 返回值
);

5. 消息循环

在创建窗口、显示窗口、更新窗口后,需要编写一个消息循环,不断地从消息队列中取出消息,并进行响应。

从消息队列中取出消息,需要调用GetMessage()函数,函数的原型声明如下:

BOOL GetMessage(
		LPMSG lpMsg, // 指向一个消息结构体
		HWND hWnd, // 接收消息的windows NULL表示所有窗口
		UINT wMsgFilterMin, // 过滤消息
		UINT wMsgFilterMax
);
/*
- lpMsg 指向一个消息(MSG)结构体。
- hWnd指定接收属于哪一个窗口的消息。
- wMsgFilterMin指定要获取的消息的最小值,通常设置为0。
- wMsgFilterMax指定要获取的消息的最大值。
如果wMsgFilterMin  wMsgFilter Max都设置为0,则接收所有消息。
*/

GetMessage函数接收到除WM_QUIT外的消息均返回非零值。对于WM_QUIT消息,该函数返回0。如果出现了错误,该函数返回-1,例如,当参数hWnd是无效的窗口句柄或lpMsg是无效的指针时,该函数返回-1。

通常编写的消息循环代码如下:

//定义消息结构体,开始消息循环
	MSG msg;
	BOOL bRet;
	//while (GetMessage(&msg, NULL, 0, 0))
	while ((bRet = GetMessage(&msg, hwnd, 0, 0)) != 0)
	{
		if (bRet == -1)
		{
			// handle the error and possibly exit
			return -1;
		}
		else
		{
			TranslateMessage(&msg);//用于将虚拟键消息转换为字符消息。
			DispatchMessage(&msg);//分派一个消息到窗口过程,由窗口过程函数对消息进行处理。
		}	
	}
	return msg.wParam;

TranslateMessage 函数用于将虚拟键消息转换为字符消息。

字符消息被投递到调用线程的消息队列中,当下一次调用GetMessage 函数时被取出。当我们敲击键盘上的某个字符键时,系统将产生 WM_KEYDOWN 和 WM_KEYUP 消息。这两个消息的附加参数(wParam和lParam)包含的是虚拟键代码和扫描码等信息,而我们在程序中往往需要得到某个字符的ASCII 码,TranslateMessage 这个函数就可以将WM_KEYDOWN 和 WM_KEYUP消息的组合转换为一条WM_CHAR消息(该消息的wParam附加参数包含了字符的ASCII码),并将转换后的新消息投递到调用线程的消息队列中。(注意,TranslateMessage函数并不会修改原有的消息,它只产生新的消息并投递到消息队列中。)

DispatchMessage 函数分派一个消息到窗口过程,由窗口过程函数对消息进行处理。

DispachMessage实际上是将消息回传给操作系统,由操作系统调用窗口过程函数对消息进行处理(响应)。

Windows应用程序,操作系统,计算机硬件之间的相互关系:
请添加图片描述
Windows应用程序的消息处理机制:
(1)操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。
(2)应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条的消息。在取出消息后,应用程序可以对消息进行一些预处理,例如,放弃对某些消息的响应,或者调用TranslateMessage产生新的消息。
(3)应用程序调用DispatchMessage,将消息回传给操作系统。消息是由MSG结构体对象来表示的,其中就包含了接收消息的窗口的句柄。因此,DispatchMessage函数总能进行正确的传递。
(4)系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理(即“系统给应用程序发送了消息”)。

从消息队列中获取消息还可以调用PeekMessage函数,该函数的原型声明如下所示:

BOOL PeekMessage(
		LPMSG lpMsg, // 指向一个消息结构体
		HWND hWnd, // 接收消息的windows NULL表示所有窗口
		UINT wMsgFilterMin, // 过滤消息
		UINT wMsgFilterMax,
  	UINT wRemoveMsg
);
/*
lpMsg 指向一个消息(MSG)结构体。
hWnd指定接收属于哪一个窗口的消息。
wMsgFilterMin指定要获取的消息的最小值,通常设置为0。
wMsgFilterMax指定要获取的消息的最大值。如果wMsgFilterMin和wMsgFilter Max都设置为0,则接收所有消息。
最后1个参数指定消息获取的方式:
	PM_NOREMOVE:消息将不会从消息队列中被移除。
	PM_REMOVE:消息将从消息队列中被移除(与GetMessage 函数的行为一致)。
*/

发送消息可以使用 SendMessage 和 PostMessage 函数。SendMessage将消息直接发送给窗口,并调用该窗口的窗口过程进行处理。在窗口过程对消息处理完毕后,该函数才返(SendMessage 发送的消息为不进队消息)。PostMessage函数将消息放入与创建窗口的线程相关联的消息队列后立即返回。除了这两个函数外,还有一个PostThreadMessage函数,用于向线程发送消息,对于线程消息,MSG结构体中的hwnd成员为NULL。

6. 编写窗口过程函数

一个Windows应用程序的主要代码部分就集中在窗口过程函数中。
编写一个窗口过程函数,用于处理发送给窗口的消息。
窗口过程函数的声明形式如下:

int MessageBoxA(
  HWND   hWnd,
  LPCSTR lpText,
  LPCSTR lpCaption,
  UINT   uType
);

提示: 系统通过窗口过程函数的地址(指针)来调用窗口过程函数,而不是名字。

//编写窗口过程函数
LRESULT CALLBACK WinProc(
	HWND hwnd,  		// handle to window,消息的窗口句柄
	UINT uMsg,   		// message identifier,消息代码
	WPARAM wParam,	// first message parameter,消息代码的附加参数
	LPARAM lParam 		// second message parameter,消息代码的附加参数
)

窗口过程函数的名字可以随便取,如WinProc,但函数定义的形式必须和上述声明的形式相同。

在窗口过程函数内部使用switch/case语句来确定窗口过程接收的是什么消息,以及如何对这个消息进行处理:

{
	switch (uMsg)
	{
	case WM_CHAR://当用户在窗口中按下一个字符键,程序将得到一条WM_CHAR消息
		char szChar[20];
		sprintf_s(szChar, sizeof(szChar), "char code is %d", wParam);
		MessageBox(hwnd, szChar, "char", 0);//弹出一个包含了显示信息的消息框
		break;
	case WM_LBUTTONDOWN://当用户在窗口中按下鼠标左键时,将产生WM_LBUTTONDOWN消息调用MessageBox,函数弹出一个提示信息,告诉用户“点击了鼠标”
		MessageBox(hwnd, "mouse clicked", "message", 0);
		HDC hdc;//定义了一个类型为HDC的变量hdc
		hdc = GetDC(hwnd);//用hdc保存GetDC函数返回的与特定窗口相关联的DC的句柄。不能在响应WM_PAINT消息时调用
		TextOut(hdc, 0, 50, "HAVE A NICE DAY!", strlen("HAVE A NICE DAY!"));//TextOut函数利用得到的DC句柄在指定的位置(x坐标为0,y坐标为50)输出一行文字
		ReleaseDC(hwnd, hdc);//如果使用GetDC函数来得到DC的句柄,那么在完成图形操作后,必须调用ReleaseDC函数来释放DC所占用的资源,否则会引起内存泄漏。
		break;
	case WM_PAINT://对WM_PAINT消息进行处理。当窗口客户区的一部分或者全部变为“无效”时,系统会发送WM_PAINT消息,通知应用程序重新绘制窗口。
		HDC hDC;
		PAINTSTRUCT ps;
		hDC = BeginPaint(hwnd, &ps);//调用BeginPaint函数得到DC的句柄。BeginPaint函数的第1个参数是窗口的句柄,第二个参数是PAINTSTRUCT结构体的指针,该结构体对象用于接收绘制的信息。BeginPaint只能在响应WM_PAINT消息时调用
		TextOut(hDC, 0, 0, "https://blog.csdn.net/qq_44974888/article/details/124137129?spm=1001.2014.3001.5501", strlen("https://blog.csdn.net/qq_44974888/article/details/124137129?spm=1001.2014.3001.5501"));//TextOut函数在(0,0)的位置输出一个网址
		EndPaint(hwnd, &ps);//BeginPaint函数得到的DC,必须用EndPaint函数去释放
		break;
	case WM_CLOSE://当用户单击窗口上的关闭按钮时,系统将给应用程序发送一条WM_CLOSE 消息。
		if (IDYES == MessageBox(hwnd, "是否退出程序?", "warning", MB_YESNO))
		{
			DestroyWindow(hwnd);//调用DestroyWindow函数销毁窗口
		}//DestroyWindow 函数在销毁窗口后会向窗口过程发送 WM_DESTROY 消息。注意,此时窗口虽然销毁了,但应用程序并没有退出。
		break;
	case WM_DESTROY://DestroyWindow函数在销毁窗口后,会给窗口过程发送WM_DESTROY消息,在该消息的响应代码中调用PostQuitMessage函数
		PostQuitMessage(0);//PostQuitMessage函数向应用程序的消息队列中投递一条WM_QUIT消息并返回
		break;//GetMessage函数只有在收到WM_QUIT消息时才返回0,此时消息循环才结束,程序退出
	default:
		return DefWindowProc(hwnd, uMsg, wParam, lParam);//对WM_CLOSE消息的响应并不是必须的,如果应用程序没有对该消息进行响应,系统将把这条消息传给DefWindowProc函数,那么DefWindowProc函数则调用DestroyWindow函数来响应这条WM_CLOSE消息。
	}
	return 0;
}

DestroyWindow函数在销毁窗口后,会给窗口过程发送WM_DESTROY消息,我们在该消息的响应代码中调用PostQuitMessage函数。PostQuitMessage函数向应用程序的消息队列中投递一条WM_QUIT消息并返回。 GetMessage函数只有在收到WM_QUIT消息时才返回0,此时消息循环才结束,程序退出。要想让程序正常退出,我们必须响应 WM_DESTROY 消息,并在消息响应代码中调用PostQuitMessage,向应用程序的消息队列中投递WM_QUIT消息。传递给PostQuitMessage函数的参数值将作为WM_QUIT消息的wParam参数,这个值通常用作WinMain函数的返回值。

7. 总结(创建一个Win32应用程序的步骤)

(1)编写WinMain函数,可以在MSDN上查找并复制。
(2)设计窗口类(WNDCLASS)。
(3)注册窗口类。
(4)创建窗口。
(5)显示并更新窗口。
(6)编写消息循环。
(7)编写窗口过程函数。窗口过程函数的语法可通过 MSDN 查看 WNDCLASS 的lpfnWndProc成员变量,在这个成员的解释中可以查到。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/524787.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线性表之双向链表(详解)

🍕博客主页:️自信不孤单 🍬文章专栏:数据结构与算法 🍚代码仓库:破浪晓梦 🍭欢迎关注:欢迎大家点赞收藏关注 文章目录 🍥前言🍒双向链表1. 带头双向循环链表…

【C++】通序录管理系统

1、缘起 最近(2023-04-24)学习完了 C 编程语言的 基础语法,然后将这些基础语法的知识点整合到一起,实现一个 通讯录管理系统。以此来巩固以前所学习过的知识点,以求在后续的学习中能够灵活应用。 2、系统需求 通讯录是…

ChatGPT结合本地数据_llamaindex

1 功能 大模型学习的主要是通用数据,而用户可能需要让ChatGPT在本地的知识库中寻找答案。 普通用户不太可能训练大模型;由于本地数据格式丰富,内容烦多,且考虑到使用成本和token大小限制,也不可能在每次提问时都将所有…

balenaEtcher v1.18.1 开源跨平台镜像文件快速刻录工具

balenaEtcher 是一款开源免费的跨平台镜像文件快速刻录工具,使用体验感觉比软碟通UltraISO好用多了,推荐使用。它可以帮助用户快速将 ISO 文件、IMG 文件或者其他格式的镜像文件刻录到 USB 驱动器、SD 卡或者其他可烧录介质上。它支持 Windows、macOS 和…

50 Projects 50 Days - Blurry Loading 学习记录

项目地址 Blurry Loading 展示效果 Blurry Loading 实现思路 元素组成只需要有一张图片和中间的文本即可。针对动态过程分析初始和终止状态即可,初始时图片全模糊,文本显示0%;终止时,图片完全不模糊,文本会显示100…

Junit 单元测试框架(简单使用)

目录 一、注解 1. Test 2. BeforeEach 和 BeforeAll 3. AfterEach 和 AfterAll 二、断言 1. Assertions类 1.1 assertEquals 和 assertNotEquals 1.2 assertTrue 和 assertFalse 1.3 assertNull 和 assertNotNull 三、用例执行顺序 1. 方法的排序 —— Order 四、…

人工智能轨道交通行业周刊-第44期(2023.5.8-5.14)

本期关键词:智能列控、苏州城轨智慧大脑、智慧乘务系统、深铁智慧运维、铁路遥感、3D视觉 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通R…

【C++入门攻略】和【编程常见问题】

常见问题 vsstudio快捷键 快速注释组合键 ctrlk ctrlc 取消注释快捷键 ctrlk ctrl u 支持垃圾回收机制 大多数面向对象编程语言具有垃圾回收机制。早期的C语言不具备垃圾回收机制,这意味着申请的内存资源在使用完成后,需要程序员自己释放。直到C11标…

1066 Root of AVL Tree(51行代码+超详细注释)

分数 25 全屏浏览题目 切换布局 作者 CHEN, Yue 单位 浙江大学 An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebala…

孙鑫VC++第一章 Windows程序内部运行机制

目录 1.1 API和SDK 1.2 窗口和句柄 1.3 消息和队列 1.4 WinMain 1.4.1 WinMain函数的定义 1.4.2 窗口的创建 1.4.3 消息循环 1.4.4 窗口过程函数 1.1 API和SDK API:Windows操作系统提供给应用程序编程的接口。 SDK(软件开发包):用于开发的所有资…

swing列表框_强制存储的DefaultListModel和DefaultComboBoxModel

package com.aynu.layout;import javax.swing.*; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class DefaultListModelTest {JFrame jf new JFrame("测试DefaultListModel");JTextField bookNa…

JVM学习(二)

1. JVM 运行时内存 Java 堆从 GC 的角度还可以细分为: 新生代 ( Eden 区 、 From Survivor 区 和 To Survivor 区 )和 老年 代。 1.1. 新生代 是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象,所以新生代会频繁触发 MinorGC 进行垃圾回收。新…

《如何评价北化面向对象江某英之我是传奇》

点进来的都是家人了,来,今天带你们一起速通江某英的面向对象。 首先,我们先看一下江某英的教学安排,所谓知己知彼,百战不殆。 一共是九个章节,但是最后一个总复习没讲,这不是为难我们吗&#x…

【移动端网页布局】Flex 弹性布局案例 ② ( 顶部固定定位搜索栏 | 固定定位盒子居中对齐 | 二倍精灵图设置 | CSS3 中的垂直居中对齐 )

文章目录 一、顶部固定定位搜索栏1、固定定位盒子居中对齐2、设置最大宽度和最小宽度3、使用 Flex 弹性布局管理宽度4、二倍精灵图设置5、CSS3 中的垂直居中对齐 - 行高 内容高度 ( 总高度 - 边框高度 - 内边距高度 ) 二、代码示例1、HTML 标签结构2、CSS 样式3、展示效果 一、…

Pytroch nn.Unfold() 与 nn.Fold()图码详解

文章目录 Unfold()与Fold()的用途nn.Unfold()Unfold()与Fold() 变化模式图解 nn.Fold()单通道 滑动窗口无重叠模拟图片数据(b,3,9,9),通道数 C 为3,滑动窗口无重叠。单通道 滑动窗口有重叠。 卷积等价于:Unfold Matri…

国民技术N32G430开发笔记(20)- FreeRTOS的移植

FreeRTOS的移植 1、官网下载FreeRTOSv202212.01,搜索官网下载即可。 2、新建一个FreeRTOSDemo的工程,可以把之前的工程中的Bootloader工程复制一份。 3、打开下载的freertos代码将相应代码移植到我们的工程中。 protable文件夹,因为是gcc环…

ChatGPT国内镜像网站集合

ChatGPT是一个基于人工智能的聊天机器人,它可以与用户进行自然语言交互。ChatGPT使用了最新的自然语言处理技术,包括深度学习和神经网络,以便更好地理解用户的意图和回答用户的问题。 ChatGPT可以回答各种问题,包括但不限于常见问…

RabbitMQ如何避免丢失消息

目录标题 消息丢失1. 生产者生产消息到RabbitMQ Server 消息丢失场景1. 网络问题2. 代码层面,配置层面,考虑不全导致消息丢失解决方案:开启confirm模式 2. 队列本身可能丢失消息1. 消息未完全持久化,当机器重启后,消息…

shell脚本之“sed“命令

文章目录 1.sed编辑器概述2.sed命令常用选项3.sed命令常用操作4.sed命令演示操作部分5.总结 1.sed编辑器概述 sed是一种流编辑器,流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。 sed编辑器可以根据命令来处理数据流中的数据,这些…

C嘎嘎~~[类 下篇 之 日期类的实现]

类 下篇 之 日期类的实现 6.const成员6.1 const成员的引入6.2const成员的概念 7.日期类的实现 6.const成员 6.1 const成员的引入 class Date { public:// 构造函数Date(int year 2023, int month 5, int day 5){_year year;_month month;_day day;}void Print(){cout &…