SDK 窗口程序创建

news2024/11/17 11:42:08

目录

 Windows 窗口

窗口的基本概念

创建一个窗口的流程

句柄

创建窗口 

设计注册窗口类

创建窗口

显示和更新窗口

创建消息循环

消息循环

建立消息循环

窗口过程函数

窗口程序模板(多字节)

窗口程序模板(Unicode)


 Windows 窗口

Winodws这个操作系统就是由窗口命名的,可见窗口的重要性

窗口的基本概念

通过这篇微软官方文档可以了解到窗口的基本概念:什么是窗口 - Win32 apps | Microsoft Learn

接下来了解一些更深层次的东西

Windows的窗口是由窗口类定义的,窗口类定义了窗口的外观和行为,并将其注册到系统中。每个窗口都是窗口类的一个实例,它们具有相同的属性,但可以拥有不同的内容和状态。

Windows 窗口通常包括以下几个部分:

  1. 标题栏(Title Bar):位于窗口的顶部,用于显示窗口的标题和一些控制按钮(例如最小化、最大化、关闭等)。
  2. 菜单栏(Menu Bar):可选的,位于窗口的顶部或程序的主窗口下方,用于显示应用程序的菜单和子菜单。
  3. 工具栏(Tool Bar):可选的,通常位于窗口的顶部或菜单栏下方,用于提供快捷方式和工具按钮。
  4. 客户区(Client Area):窗口的主要部分,用于显示应用程序的内容、控件和用户界面。
  5. 状态栏(Status Bar):位于窗口的底部,用于显示应用程序的状态信息、提示信息等。

除此之外,窗口还可以包含各种控件,例如按钮、文本框、列表框、复选框等,以及自定义的绘图和布局逻辑。

创建一个窗口的流程

  1. 要有一个窗口类,并且得到一个实例
  2. 调用系统API注册窗口类,需要指定回调函数
  3. 再调用系统API创建窗口,会返回一个窗口的句柄

句柄

程序员是不能直接操作窗口的,需要调用系统的API;

当应用程序请求创建一个新的句柄时,操作系统内核会为该句柄分配一段内存空间来存储句柄所引用的对象或资源的相关信息,并返回该句柄给应用程序。对于不同类型的句柄,内核会使用不同的数据结构来管理它们。

句柄(Handle)是在计算机编程中用于表示对象或资源的标识符。在操作系统中,句柄可以被认为是对对象或资源的引用,程序可以通过句柄来访问和操作这些对象或资源。句柄是操作系统提供的一种标识和访问对象或资源的机制,它由操作系统内核来管理

想要访问这些系统资源,需要API+句柄来实现

下面是一些常见的句柄类型及其含义:

  1. 窗口句柄(HWND):窗口句柄是对窗口对象的引用,可以用于标识和操作特定的窗口。通过窗口句柄,程序可以改变窗口的属性、位置、大小,发送消息到窗口,以及获取窗口的属性和状态等。
  2. 文件句柄(File Handle):文件句柄是对文件对象的引用,用于表示打开的文件。通过文件句柄,程序可以读取、写入、关闭文件,以及获取文件的属性和状态等。
  3. 设备句柄(Device Handle):设备句柄是对设备对象的引用,用于表示打开的设备。通过设备句柄,程序可以与设备进行通信,执行设备操作,例如读写设备数据、控制设备行为等。
  4. 内存句柄(Memory Handle):内存句柄是对内存块的引用,用于表示分配的内存。通过内存句柄,程序可以读写分配的内存区域,释放内存,以及获取内存的相关信息。

创建窗口 

 创建一个窗口的基本流程:

  1. 设计注册窗口类
  2. 常见窗口实例
  3. 显示窗口
  4. 更新窗口
  5. 消息循环
  6. 窗口注册函数

这里演示的是Unicode的窗口类创建

设计注册窗口类

窗口类

设计窗口

WNDCLASS wc;							//创建一个类名为 wc 的窗口类
wc.style = CS_VREDRAW | CS_HREDRAW; 	//默认填CS_VREDRAM | CS_HREDRAM 的组合,可通过位运算增加风格或删除风格
wc.lfnWndProc = MyWindowProc;		    //窗口过程函数(窗口回调函数)
wc.cbClsExtra = 0;						//默认填0
wc.cbWndExtra = 0;						//默认填0
wc.hInstance = hInstance;				//标注这个窗口类属于哪个进程,便于从消息队列获取该进程的消息
wc.hIcon = NUll;						//图标
wc.hCursor = NULL;						//光标
wc.hbrBackground = (HBRUSH)COLOR_HIGHLIGHT;//由于是msdn上预定义的,如果出现类型不匹配直接强转即可。
wc.lpszMenuName = NULL;					//菜单
wc.lpszClassName = "MyWindow";			//窗口的类名

参数解释:

  • wc.style:成员style控制窗口的某些重要特性,在WINDOWS.H中定义了一些前缀为CS的常量,在程序中可组合使用这些常量.也可把sytle设为0.
    • wc.style = CS_HREDRAW | CS_VREDRAW它表示当窗口的纵横坐标发生变化时要重画整个窗口。
    • eg:无论你怎样拉动窗口的大小,那行字都会停留在窗口的正中部,而假如把这个参数设为0的话,当改动窗口的大小时,那行字则不一定处于中部了。
  • wc.lfnWndProc:窗口过程函数,它将接收Windows发送给窗口的消息,并执行相应的任务。并且必须在模快定义中回调它。WndProc是一个回调函数(详见消息循环)
  • wc.cbClsExtra:指定用本窗口类建立的所有窗口结构分配的额外字节数。当有两个以上的窗口属于同一窗口类时,如果想将不同的数据和每个窗口分别相对应。则使用该域很有用。这般来讲,你只要把它们设为0就行了,不必过多考虑。
  • wc.hInstance:标识应用程序的实例hInstance,当然,实例名是可以改变的。
    • wc.hInstance = MyhInstance ;这一成员可使Windows连接到正确的程序(自己的程序)。
  • wc.hIcon:成员hIcon被设置成应用程序所使用图标的句柄,图标是将应用程序最小化时出现在任务栏里的的图标,用以表示程序仍驻留在内存中。Windows提供了一些默认图标,我们也可定义自己的图标,VC里面专有一个制作图标的工具。
  • wc.hCursor:定义该窗口产生的光标形状。LoadCursor可返回固有光标句柄或者应用程序定义的光标句柄。IDC_ARROW表示箭头光标.
  • wc.hbrBackground:决定Windows用于着色窗口背景的刷子颜色,函数GetStockObject返回窗口的颜色,本程序中返回的是白色,你也可以把它改变为红色等其他颜色.试试看
  • wc.lpszMenuName:用来指定菜单名,本程序中没有定义菜单,所以为NULL。
  • wc.lpszClassName:指定了本窗口的类名。类名是操作系统识别类的唯一ID
    • wc.lpszClassName = "MyWindow";窗口类名必须自定义。

注册窗口类

ATOM Ret = RegisterClass(&ws); //告知操作系统
    if (Ret == 0)
    {
        MessageBox(NULL,"注册窗口类失败","提示",MB_OK);
    }

创建窗口

创建窗口函数

HWND CreateWindow(
  LPCTSTR lpClassName,  // 登记的窗口类名
  LPCTSTR lpWindowName, // 用来表明窗口的标题
  DWORD dwStyle,        // 用来表明窗口的风格,如有无最大化,最小化按纽啊什么的
  int x,                // 用来表明程序运行后窗口在屏幕中的坐标值。
  int y,                // 用来表明程序运行后窗口在屏幕中的坐标值。
  int nWidth,           // 用来表明窗口初始化时(即程序初运行时)窗口的大小,即长度与宽度。
  int nHeight,          // 用来表明窗口初始化时(即程序初运行时)窗口的大小,即长度与宽度。
  HWND hWndParent,      // 在创建窗口时可以指定其父窗口,这里没有父窗口则参数值为0。
  HMENU hMenu,          // 用以指明窗口的菜单,菜单以后会讲,这里暂时为0。
  HANDLE hInstance,     // 应用程序实例句柄,与程序绑定
  LPVOID lpParam        // 最后一个参数是附加数据,一般都是0。
);

显示和更新窗口

显示窗口

BOOL ShowWindow(  HWND hWnd,     // handle to window
  int nCmdShow   // show state);

更新窗口

BOOL UpdateWindow(  HWND hWnd   // handle to window);

参数1:窗口句柄,告诉ShowWindow()显示哪一个窗口

参数2:第二个参数则告诉它如何显示这个窗口:最小化(SW_MINIMIZE),普通(SW_SHOWNORMAL),还是最大化 (SW_SHOWMAXIMIZED)

WinMain在创建完窗口后就调用ShowWindow函数,并把iCmdShow参数传送给这个窗口。

WinMain()调用完ShowWindow后,还需要调用函数UpdateWindow,最终把窗口显示了出来。调用函数UpdateWindow将产生一个WM_PAINT消息,这个消息将使窗口重画,即使窗口得到更新.且不通过消息循环

创建消息循环

消息循环

Windows为每个正在运行的应用程序都保持一个消息队列。当你按下鼠标或者键盘时,Windows并不是把这个输入事件直接送给应用程序,而是将输入的事件先翻译成一个消息,然后把这个消息放入到这个应用程序的消息队列中去。

消息结构体定义:

typedef struct tagMSG {
    HWND hwnd;
    UINT message;       //消息的类别,也叫消息的ID,编号
    WPARAM wParam;
    LPARAM lParam;
    DWORD time;
    POINT pt;
} MSG;

操作系统将消息封装成MSG结构体投递到消息队列。

消息循环:应用程序的WinMain函数通过执行一段代码从她的队列中来检索Windows送往她的消息。然后WinMain就把这些消息分配给相应的窗口函数以便处理它们,这段代码是一段循环代码,故称为”消息循环”。

拿到消息以后,在通过获取的消息对应处理调用窗口回调函数

建立消息循环

消息循环以GetMessage调用开始,它从消息队列中取出一个消息:

MSG msg; //定义消息名
while (GetMessage (&msg, NULL, 0, 0))
{
     TranslateMessage (&msg) ; //翻译消息
     DispatchMessage (&msg) ; //
}
return msg.wParam ;

GetMessage函数

BOOL GetMessage( 
    LPMSG lpMsg, 		//接收消息的MSG结构的地址
    HWND hWnd, 			//窗口句柄,NULL则表示要获取该应用程序创建的所有窗口的消息;
    UINT wMsgFilterMin, //指定消息范围。后面三个参数被设置为默认值
    UINT wMsgFilterMax  //指定消息范围。后面三个参数被设置为默认值
    ); 

后面三个参数被设置为默认值这就是说你打算接收发送到属于这个应用程序的任何一个窗口的所有消息。

返回值:

  • 在接收到除WM_QUIT之外的任何一个消息后,GetMessage()都返回TRUE。
  • 如果GetMessage收到一个WM_QUIT消息,则返回FALSE
  • 如收到其他消息,则返回TRUE。

TranslateMessage:

消息用GetMessage读入后(注意这个消息可不是WM_QUIT消息),它首先要经过函数TranslateMessage()进行翻译,这个函数会转换成一些键盘消息,它检索匹配的WM_KEYDOWN和WM_KEYUP消息,并为窗口产生相应的ASCII字符消息(WM_CHAR),它包含指定键的ANSI字符.但对大多数消息来说它并不起什么作用,所以现在没有必要考虑它。

DispatchMessage:

要求Windows将消息传送给在MSG结构中为窗口所指定的窗口过程。我们在讲到登记窗口类时曾提到过,登记窗口类时,我们曾指定Windows把函数WindosProc作为咱们这个窗口的窗口过程(就是指处理这个消息的东东)。就是说,Windows会调用函数WindowsProc()来处理这个消息。

窗口过程函数

LRESULT CALLBACK WindowProc(  
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter);

WM_DESTROY消息是在窗口被销毁时发送的。 在窗口从屏幕上删除后,它被发送到正在被销毁的窗口的窗口过程。此消息首先发送到被销毁的窗口,然后发送到被销毁的子窗口(如果有的话)。 在处理消息期间,可以假定所有子窗口仍然存在。

LRESULT CALLBACK WndProc
(
	HWND hwnd,      // handle to window
	UINT uMsg,      // message identifier
	WPARAM wParam,  // first message parameter
	LPARAM lParam   // second message parameter
)
{
	switch (uMsg)
	{
	case WM_DESTROY: //销毁窗口的消息
		PostQuitMessage(0);//退出消息循环
		break;
	default:
		break;
	}
	return DefWindowProc(hwnd,uMsg,wParam,lParam);
}

窗口程序模板(多字节)

#include <windows.h>
#pragma comment(lib, "winmm")   //PlaySound在Winmm.lib这个库中,当然需要链接它。

LRESULT CALLBACK MyWndProc(HWND, UINT, WPARAM, LPARAM);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	static wchar_t szAppName[] = L"Hello Win";


	//设计窗口类
	WNDCLASS ws;
	ws.style = CS_HREDRAW | CS_VREDRAW;
	ws.lpfnWndProc = &MyWndProc;
	ws.cbClsExtra = NULL;
	ws.cbWndExtra = NULL;
	ws.hInstance = hInstance;
	ws.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	ws.hCursor = LoadCursor(NULL, IDC_ARROW);
	ws.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	ws.lpszMenuName = nullptr;
	ws.lpszClassName = szAppName;

	//注册窗口类
	if (!RegisterClass(&ws))
	{
		MessageBox(NULL, TEXT("注册窗口失败"), TEXT("错误提示:"), MB_OK);

		return 0;
	}

	//创建窗口
	HWND HelloHwnd = CreateWindow(
		szAppName,
		TEXT("The Hello Program"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL,);

	//显示窗口
	ShowWindow(HelloHwnd, iCmdShow);

	//更新窗口,调用Begin使得画面有效
	UpdateWindow(HelloHwnd);

	//建立消息循环
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg); //将msg结构传给Windows,进行一些键盘转换
		DispatchMessage(&msg);  //使得自动调用消息窗口句柄所属的窗口过程函数
	}

	return msg.wParam;  //结构的wParam字段是传递给PostQuitMessage函数的值(通常是0)。然后return叙述将退出WinMain并终止程序。
}

//实现消息过程函数
LRESULT CALLBACK MyWndProc(
	HWND hwnd,      //
	UINT message,   //
	WPARAM wParam,  //参数wParam表明窗口是非最小化还是非最大化,是最小化、最大化,还是隐藏
	LPARAM lParam   //lParam参数包含了新窗口的大小,新宽度和新高度均为16位值,合在一起成为32位的lParam。
)
{
	PAINTSTRUCT ps;     //PAINTSTRUCT结构中包含一些窗口消息处理程序,可以用来更新显示区域的内容。
	RECT rect;          //矩形结构
	HDC hdc;            //绘图结构

	switch (message)
	{
	case WM_CREATE:
		PlaySound(TEXT("G:\\CR40C++程序设计\\二阶段\\SDK\\Windows程序设计实例\\HELLOWIN\\胜利.wav"), NULL, SND_FILENAME | SND_ASYNC);
		return 0;

		//当窗口改变时
		//对WM_PAINT的处理几乎总是从一个BeginPaint呼叫开始:
		//一旦显示区域变得无效(正如在改变大小时所发生的情况一样),WndProc就接收到一个新的WM_PAINT消息。
		//WndProc通过呼叫GetClientRect取得变化后的窗口大小,并在新窗口的中央显示文字。
	case WM_PAINT:
	{

		//在设备客户区中央绘制文本
		hdc = BeginPaint(hwnd, &ps);        //返回用于在客户端区域中绘制的显示设备上下文的句柄,在BeginPaint呼叫中,如果显示区域的背景还未被删除,则由Windows来删除
		GetClientRect(hwnd, &rect);         //接受窗口改变后的尺寸信息。【x,y,高,宽】
		DrawText(
			hdc,                                    //BeginPaint传回的设备内容句柄
			TEXT("Hello ,Windows 10!"),                   //要输出的文字
			-1,                                     //第三个参数是 -1,指示字符串是以字节0终结的
			&rect,                                  //要输出的坐标
			DT_SINGLELINE | DT_CENTER | DT_VCENTER  //系列位旗标,旗标指示了文字必须显示在一行上,水平方向和垂直方向都位于第四个参数指定的矩形中央
		);
		EndPaint(hwnd, &ps); //释放ps函数资源,结束绘制请求并释放设备上下文。
	}
	//不处理:如果窗口消息处理程序不处理WM_PAINT消息(这是很罕见的),
	//它们必须被传送给DefWindowProc。DefWindowProc只是依次呼叫BeginPaint和EndPaint,以使显示区域有效。
	return 0;
	case WM_DESTROY:
		PostQuitMessage(0); //发送WM_QUIT以结束消息循环
		return 0;
	}

	return DefWindowProc(hwnd, message, wParam, lParam);    //操作系统待处理我们不处理的消息
}

窗口程序模板(Unicode)

#include <windows.h>
#pragma comment(lib, "winmm")   //PlaySound在Winmm.lib这个库中,当然需要链接它。

LRESULT CALLBACK MyWndProc(HWND, UINT, WPARAM, LPARAM);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

	PSTR szCmdLine, int iCmdShow)
{
	static char szAppName[] = "Hello Win";


	//设计窗口类
	WNDCLASS ws;
	ws.style = CS_HREDRAW | CS_VREDRAW;
	ws.lpfnWndProc = &MyWndProc;
	ws.cbClsExtra = NULL;
	ws.cbWndExtra = NULL;
	ws.hInstance = hInstance;
	ws.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	ws.hCursor = LoadCursor(NULL, IDC_ARROW);
	ws.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	ws.lpszMenuName = nullptr;
	ws.lpszClassName = szAppName;

	//注册窗口类
	if (!RegisterClass(&ws))
	{
		MessageBox(NULL, "注册窗口失败", "错误提示:", MB_OK);

		return 0;
	}

	//创建窗口
	HWND HelloHwnd = CreateWindow(
		szAppName,
		"The Hello Program",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL,
		);

	//显示窗口
	ShowWindow(HelloHwnd, iCmdShow);

	//更新窗口,调用Begin使得画面有效
	UpdateWindow(HelloHwnd);

	//建立消息循环
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg); //将msg结构传给Windows,进行一些键盘转换
		DispatchMessage(&msg);  //使得自动调用消息窗口句柄所属的窗口过程函数
	}

	return msg.wParam;  //结构的wParam字段是传递给PostQuitMessage函数的值(通常是0)。然后return叙述将退出WinMain并终止程序。
}

//实现消息过程函数
LRESULT CALLBACK MyWndProc(
	HWND hwnd,      //
	UINT message,   //
	WPARAM wParam,  //参数wParam表明窗口是非最小化还是非最大化,是最小化、最大化,还是隐藏
	LPARAM lParam   //lParam参数包含了新窗口的大小,新宽度和新高度均为16位值,合在一起成为32位的lParam。
)
{
	PAINTSTRUCT ps;     //PAINTSTRUCT结构中包含一些窗口消息处理程序,可以用来更新显示区域的内容。
	RECT rect;          //矩形结构
	HDC hdc;            //绘图结构

	switch (message)
	{
	case WM_CREATE:
		PlaySound("G:\\CR40C++程序设计\\二阶段\\SDK\\Windows程序设计实例\\HELLOWIN\\胜利.wav", NULL, SND_FILENAME | SND_ASYNC);
		return 0;

		//当窗口改变时
		//对WM_PAINT的处理几乎总是从一个BeginPaint呼叫开始:
		//一旦显示区域变得无效(正如在改变大小时所发生的情况一样),WndProc就接收到一个新的WM_PAINT消息。
		//WndProc通过呼叫GetClientRect取得变化后的窗口大小,并在新窗口的中央显示文字。
	case WM_PAINT:
	{

		//在设备客户区中央绘制文本
		hdc = BeginPaint(hwnd, &ps);        //返回用于在客户端区域中绘制的显示设备上下文的句柄,在BeginPaint呼叫中,如果显示区域的背景还未被删除,则由Windows来删除
		GetClientRect(hwnd, &rect);         //接受窗口改变后的尺寸信息。【x,y,高,宽】
		DrawText(
			hdc,                                    //BeginPaint传回的设备内容句柄
			"Hello ,Windows 10!",                   //要输出的文字
			-1,                                     //第三个参数是 -1,指示字符串是以字节0终结的
			&rect,                                  //要输出的坐标
			DT_SINGLELINE | DT_CENTER | DT_VCENTER  //系列位旗标,旗标指示了文字必须显示在一行上,水平方向和垂直方向都位于第四个参数指定的矩形中央
		);
		EndPaint(hwnd, &ps); //释放ps函数资源,结束绘制请求并释放设备上下文。
	}
	//不处理:如果窗口消息处理程序不处理WM_PAINT消息(这是很罕见的),
	//它们必须被传送给DefWindowProc。DefWindowProc只是依次呼叫BeginPaint和EndPaint,以使显示区域有效。
	return 0;
	case WM_DESTROY:
		PostQuitMessage(0); //发送WM_QUIT以结束消息循环
		return 0;
	}

	return DefWindowProc(hwnd, message, wParam, lParam);    //操作系统待处理我们不处理的消息
}

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

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

相关文章

springBoot--web--http缓存机制测试

springBoot--web--http缓存机制测试 前言1、多端内容适配基于请求头内容协商&#xff08;默认开启&#xff09;基于请求参数内容协商&#xff08;需要开启&#xff09; 2、默认返回json数据3、设置返回xml数据导入jackson-dataformat-xml包在类文件中添加注解 JacksonXmlRootEl…

Leetcode 1 两数之和 (暴力循环 HashMap* ) 含set、数组、map作哈希表的特性分析*

Leetcode 1 两数之和 &#xff08;暴力循环 哈希表&#xff09; 解法1 &#xff1a; 暴力循环解法2 : 哈希表HashMap法:red_circle:为什么想到用哈希表呢&#xff1f;:red_circle:为什么想到用map呢&#xff1f;:red_circle:归纳使用数组、set、map做哈希法&#xff1a; 题目链…

LeetCode 2316. 统计无向图中无法互相到达点对数::广度优先搜索(BFS)

【LetMeFly】2316.统计无向图中无法互相到达点对数&#xff1a;广度优先搜索&#xff08;BFS&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/count-unreachable-pairs-of-nodes-in-an-undirected-graph/ 给你一个整数 n &#xff0c;表示一张 无向图 中…

WP Ultimate CSV Importer远程代码执行分析-CVE-2023-4142

1.前言 WordPress的WP Ultimate CSV Importer插件易受远程代码执行的攻击 2.影响版本 <=7.9.8(所有用户) 其他版本(管理员 3.漏洞信息 此漏洞发生在ImportHelpers.php中的get_header_values函数。 trim_content数组为漏洞触发位置 $header_trim 的作用是用来存储 $m…

数字医疗解决方案:互联网医院平台的创新应用

互联网医院平台代表了医疗行业的一项巨大创新&#xff0c;它利用数字技术为患者提供了更加便捷和高效的医疗服务。本文将探讨如何创新应用互联网医院平台&#xff0c;使用Python编程语言构建一个简单的远程医疗应用示例。 构建远程医疗应用 在本文中&#xff0c;我们将使用P…

@Cleanup() 使用注意事项

前端时间用lombok 的Cleanup() 想实现线程池的自动关闭&#xff0c;因为使用不当&#xff0c;查bug查了好久&#xff0c;因此写篇博客纪念下&#xff0c;同时也希望读者可以跳过这个坑。 Cleanup修饰的对象&#xff0c;可以在对象资源使用结束后&#xff0c;自动关闭。 1、错…

Map接口遍历方法

public static void main(String[] args) {Map map new HashMap();map.put("邓超", "孙俪");//替换map.put("王宝强", "马蓉");//okmap.put(null, "刘亦菲");//plmap.put("鹿晗", null);//okmap.put("lu汉&…

【微信小程序开发】运用WXS进行后台数据交互

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于小程序的相关操作吧 一.wxs是什么 WXS是指"微信小程序云开发"&#xff08;WeChat Mini Program Cloud Development&#xff09;&#xff0c;是由微信…

css3实现图片瀑布流,根据屏幕大小列可变和不可变的的瀑布流

前提是每张图片宽度要设置成一样,准备15张图测试 <div class"img-main"><div><img src"/assets/images/sq/1.jpg" alt"" title"1"></div><div><img src"/assets/images/sq/2.jpg" alt&quo…

Linux启动流程描述

目录 Linux的引导过程 启动系统内核 启动init进程 什么是Linux Linux的内核最初是由芬兰人林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;在赫尔辛基大学上学时出于个人爱好而编写的 Linux全称GUN/Linux&#xff0c;是一套开源的类Unix操作系统&#xff0c;是一个基…

【Linux】基本操作指令汇总(不完全)

文章目录 操作系统概念补充lspwdsuechocdtouchmkdirrmdir指令 && rm 指令(重要)man指令cpmvcatmorelessheadtailstat时间相关的指令calfindgrepwcsortuniqwhichziptar:打包/解包&#xff0c;不打开它&#xff0c;直接看内容bcunamectrl cctrl rctrl d\ls cpulsmemdf-hw…

base64是什么?怎么用的?

Base64是一种将二进制数据转换为ASCII字符的编码方式。 它可以用于在文本协议中传输二进制数据,例如在电子邮件中传输图片或在网页中嵌入图像等。Base64编码使用64个字符集(A-Z、a-z、0-9和"+“、”/")来表示二进制数据。 Base64编码的原理是将3个字节的二进制数…

澳洲谷揽GRANAR谷物分析仪维修GR-1800蛋白检测仪

澳洲GRANAR谷揽GR-1800谷物分析仪应用领域&#xff1a;大豆、油菜籽、亚麻籽 常用分析指标&#xff1a;蛋白质、芥酸、水分、灰分 、油脂等 分析时间&#xff1a;&#xff1c;3min 使用场景&#xff1a;谷物收购、生产加工、实验室 GR-1800i型号特点 1.检测时间由3分钟缩短…

keil中报警告comparison of constant 100 with boolean expression is always true

keil中变量Wave_Fre为变值 需要更改为 if( (0<Wave_Fre)&&(Wave_Fre<100)) 因为在C中运算符计算从左到右&#xff0c;((0<Wave_Fre) < 100 )

修改工单状态BAPI

业务需求&#xff1a;创建内部订单后&#xff0c;自动审批内部订单订单&#xff08;状态改为REL&#xff09; 函数&#xff1a;I_CHANGE_STATUS 单据状态表&#xff1a;JEST 单据状态描述表&#xff1a;TJ02T DATA lv_object TYPE char22 .lv_object OR && p_lv_au…

【LeetCode】63. 不同路径 II

1 问题 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。那么从左上角…

Jmeter(八):jmeter接口自动化测试操作流程、计数器、定时器详解

Jmeter&#xff1a;jmeter接口自动化测试操作流程 在企业使用jmeter开展实际的接口自动化测试工具&#xff0c;建议按如下操作流程&#xff0c; 可以使整个接口测试过程更规范&#xff0c;更有效。 接口自动化的流程&#xff1a; 1、获取到接口文档&#xff1a;swagger、wor…

广州华锐视点:VR3D技术在中学物理实验中的应用

随着科技的飞速发展&#xff0c;VR(虚拟现实)技术已经成为当今教育领域的一股重要力量。它为传统教学带来了前所未有的变革&#xff0c;特别是在初中物理实验教学中&#xff0c;VR技术的应用为学生们开启了全新的学习之旅。下面&#xff0c;让我们一起来探讨VR/3D虚拟仿真中学物…

uboot 启动流程详细分析参考

1 基本概念 1.1 uboot 是什么&#xff1f; 当我们厌倦了裸机程序&#xff0c;而想要采用操作系统的时候&#xff0c;uboot就是不得不引入的一段程序。所以&#xff0c;uboot就是一段引导程序&#xff0c;在加载系统内核之前&#xff0c;完成硬件初始化&#xff0c;内存映射&a…

2016-2023全国MEM国家A类线趋势图:浙大MEM要高多少?

2024年全国MEM联考已经到了关键的冲刺阶段&#xff0c;以目前全国非全日制mem项目的招生录取情况来看&#xff0c;大多数都是以国家A类线作为其录取的基本参考依据。而mem项目的国家线子啊过去的几年中也是有过比较大的波动&#xff0c;最明显的是2022年的国家线达到了历史最高…