win32-显示窗口、消息循环、消息队列

承接上文:

  1. win32窗口编程
  2. windows 开发基础
  3. win32-注册窗口类、创建窗口

本文目录

  • 显示窗口 ShowWindow function (winuser.h)
  • 消息循环
    • 消息基础
      • MSG 结构体的定义 MSG structure (winuser.h)
      • POINT structure 结构体 (windef.h)
      • DispatchMessage() 如何将消息派发给窗口的处理函数
      • 窗口处理函数
      • GetMessage() function (winuser.h)
      • TranslateMessage() function
    • 常见消息
      • WM_DESTROY
      • WM_CLOSE
      • WM_SYSCOMMAND
      • WM_CREATE
      • WM_SIZE
      • WM_QUIT
    • 消息循环的原理
      • 消息循环的阻塞 : GetMessage()函数 VS PeekMessage() 函数
      • 更加高效地抓取消息
    • 发送消息 : SendMessage()函数 VS PostMessage() 函数
    • 消息分类
  • 消息队列
    • 消息队列分类
    • 消息和消息队列的关系
  • 深入 GetMessage() 函数

显示窗口 ShowWindow function (winuser.h)

在前文中介绍了创建窗口的过程,注册窗口类,创建窗口并返回一个窗口句柄 hWnd,这个窗口句柄 hWnd 可以在内存中找到一块保存着窗口各种信息的内存(大小、位置等信息),创建完窗口后并不能看见窗口,必须还要在屏幕上进行绘制,这时候需要调用 show(hWnd, SW_SHOW); 函数。第一个参数即窗口的句柄,第二个参数显示窗口的方式,它可以是由 WinMain() 窗口主函数传进来的参数 nCmdShow 的值,也可以是自己指定的值:

  • SW_SHOW :按照创建窗口时的参数原样显示。
  • SW_SHOWNORMAL :显示窗口并激活它,窗口的大小和位置由操作系统确定。
  • SW_SHOWMAXIMIZED :显示窗口并将其最大化。
  • SW_SHOWMINIMIZED :显示窗口并将其最小化。
  • … …

在显示窗口之后最好更新一下窗口 UpdateWindow(hWnd);


Sets the specified window’s show state.

BOOL ShowWindow([in] HWND hWnd,   //A handle to the window.[in] int  nCmdShow/*Controls how the window is to be shown. This parameter is ignored the first time an application calls ShowWindow, if the program that launched the application provides a STARTUPINFO structure. Otherwise, the first time ShowWindow is called, the value should be the value obtained by the WinMain function in its nCmdShow parameter. In subsequent calls, this parameter can be one of the following values.参数 | 数值 | 解释1. SW_HIDE | 0 | Hides the window and activates another window.2. SW_SHOWNORMAL 或 SW_NORMAL | 1 | Activates and displays a window. If the window is minimized, maximized, or arranged, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time. 3. SW_SHOWMINIMIZED | 2 | Activates the window and displays it as a minimized window.4. SW_SHOWMAXIMIZED 或 SW_MAXIMIZE | 3 | Activates the window and displays it as a maximized window.5. SW_SHOWNOACTIVATE | 4 | Displays a window in its most recent size and position. This value is similar to SW_SHOWNORMAL, except that the window is not activated.6. SW_SHOW | 5 | Activates the window and displays it in its current size and position.7. SW_MINIMIZE | 6 | Minimizes the specified window and activates the next top-level window in the Z order.8. SW_SHOWMINNOACTIVE | 7 | Displays the window as a minimized window. This value is similar to SW_SHOWMINIMIZED, except the window is not activated.9. SW_SHOWNA | 8 | Displays the window in its current size and position. This value is similar to SW_SHOW, except that the window is not activated.10. SW_RESTORE | 9 | Activates and displays the window. If the window is minimized, maximized, or arranged, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.11. SW_SHOWDEFAULT | 10 | Sets the show state based on the SW_ value specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application.12. SW_FORCEMINIMIZE | 11 | Minimizes a window, even if the thread that owns the window is not responding. This flag should only be used when minimizing windows from a different thread. */
);

消息循环

//消息循环MSG msg = { 0 };    //msg 结构体while ( GetMessage(&msg, NULL, 0, 0)) {       //GetMessage()专门负责抓取消息(从消息队列中抓取消息),抓到消息后返回值非零,消息被保存在msg结构体中,&msg引用,类似于指针TranslateMessage(&msg);     //翻译消息,可以区分大小写字母DispatchMessage(&msg);      //派发消息给消息处理函数进行处理,前面定义的 WndProc 函数。}

MSG 是一个结构体。
GetMessage() 到消息队列中抓取消息。
TranslateMessage() 翻译消息。
DispatchMessage() 派发消息给窗口的处理函数。

消息基础

消息的组成 (在 Windows 系统上)

  • 窗口句柄 hWnd:有了窗口句柄就可以知道该消息属于哪个窗口。
  • 消息ID:消息的ID用来唯一标识一个消息。
  • 消息的两个参数(两个附带信息):lParam, wParam 附带信息,不同类型的消息附带信息的含义有所不同。
  • 消息产生的时间
  • 消息产生时的鼠标位置

消息的作用:当系统通知窗口工作时,就采用消息的方式派发给窗口(窗口的消息处理函数 WndProc(), 每个窗口都应有一个窗口消息处理函数,默认处理函数 DefWindowProc() 参见前文)。

Windows系统上,消息是一个结构体,用来保存消息的各种信息
在这里插入图片描述

MSG 结构体的定义 MSG structure (winuser.h)

Contains message information from a thread’s message queue.

typedef struct tagMSG {HWND   hwnd;      //A handle to the window whose window procedure receives the message. This member is NULL when the message is a thread message.UINT   message;      //The message identifier. Applications can only use the low word; the high word is reserved by the system.WPARAM wParam;     //Additional information about the message. The exact meaning depends on the value of the message member.LPARAM lParam;     //Additional information about the message. The exact meaning depends on the value of the message member.DWORD  time;      //The time at which the message was posted.POINT  pt;        //The cursor position, in screen coordinates, when the message was posted.DWORD  lPrivate;
} MSG, *PMSG, *NPMSG, *LPMSG;

POINT structure 结构体 (windef.h)

在 MSG 结构体中封装了 POINT 结构体成员变量 pt,它用来保存鼠标位置坐标(x, y)。

The POINT structure defines the x- and y-coordinates of a point.

typedef struct tagPOINT {LONG x;     //Specifies the x-coordinate of the point.LONG y;     //Specifies the y-coordinate of the point.
} POINT, *PPOINT, *NPPOINT, *LPPOINT;typedef struct _POINTL {LONG x;LONG y;
} POINTL, *PPOINTL;

The POINT structure is identical完全相同的 to the POINTL structure.

DispatchMessage() 如何将消息派发给窗口的处理函数

在 MSG 结构体中有一个成员变量 hWnd 窗口句柄,通过窗口句柄可以找到一块内存,内存中保存着各种数据(这些数据是窗口类和CreateWindow函数提供的),从这块窗口信息的内存中找到该窗口的消息处理函数 WndProc(),并调用该函数进行消息处理。WndProc() 函数是我们自己写的,所以也就回到了我们自己定义的消息处理代码中。窗口处理函数也可以指定为默认的 DefWindowProc(),它由微软提供,只是对于特定消息,它不能做出我们想要的处理效果。

派发消息伪代码:
在这里插入图片描述
调用 WndProc() 时传入了参数 msg.hWnd 窗口句柄,msg.message 消息ID(微软的消息ID总共有几千个,其本质是一个数字,用宏定义#define定义了别名,用来唯一标识一个消息),并传入了两个附带信息。

窗口处理函数

自定义的消息处理函数必须按照以下格式来:(函数名可以改,参数名可以改)

// 窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{return DefWindowProc(hwnd, uMsg, wParam, lParam);     //返回默认的消息处理函数,对各种消息做默认的处理,该函数由微软提供
}

对于不同的消息,可以用 switch() 语句来做不同的处理:

switch (uMsg)
{case WM_SIZE: // Handle window resizing// etc
}

GetMessage() function (winuser.h)

GetMessage() 从消息队列中获取消息。

BOOL GetMessaeg(LPMSG lpMsg, //将获取到的消息放入MSG结构体中HWND hWnd, //抓取指定窗口句柄的消息UINT wMsgFilterMin,   //获取消息ID所在区间的下限UINT wMsgFilterMax    //获取消息ID所在区间的上限//后两个参数用来指定抓取消息ID的范围,如果两个参数都填 0,那么就是不限定消息ID范围
);

while ( GetMessage(&msg, NULL, 0, 0)) GetMessage() 函数的返回值作为 while 循环是否继续执行下去的条件,如果窗口关闭了但进程仍未结束意味着进程并没有退出 while 循环。注意 GetMessage() 函数只抓取本进程的消息,不会抓取其他进程的消息。

在这里插入图片描述
GetMessage() 函数的返回值:

  • 当抓到的消息不是 WM_QUIT 的时候,返回值为非零。
  • 当抓到的消息是 WM_QUIT 的时候,返回值为零。
  • 出错的时候返回值是 -1。

尽量不要使用 while (GetMessage())... ... 这种形式,用下面的形式:

BOOL bRet;while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0) 
{if (bRet == -1) {//处理错误或者直接退出程序}else {TranslateMessage(&msg);DispatchMessage(&msg);}
}

或者:

//message bumpMSG msg;BOOL gResult;         // typedef int BOOL;while ((gResult = GetMessage(&msg, nullptr, 0, 0)) > 0){TranslateMessage(&msg);DispatchMessage(&msg);}if (gResult == -1){return -1;}else{return msg.wParam;    //此时 wParam 是 PostQuitMessage()的参数值}

之前的文章中提到,当窗口关闭时,进程仍然没有结束,需要添加以下代码:

LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{switch (msgID){case WM_CLOSE:     //窗口关闭的消息PostQuitMessage(0);      //发送一个退出的消息到消息队列中//发送的这个消息可以使GetMessage()函数返回零,从而结束while循环,退出程序break;}return DefWindowProc(hWnd, msgID, wParam, lParam);
}

当窗口关闭的消息产生时,调用 PostQuitMessage(0);,它会往消息队列中发送一个 WM_QUIT 消息,当 GetMessage() 函数抓到 WM_QUIT 消息时返回值为0,从而结束 while 循环。

TranslateMessage() function

BOOL TranslateMessage( CONST MSG *lpMsg );

翻译消息,将按键消息,翻译成字符消息。

  • 检查消息是否为按键消息,如果不是按键消息,不做任何处理,继续执行。

TranslateMessage() 函数只翻译可见字符消息,像 a~z 这是可见字符消息,像 上下左右 箭头按键是不可见字符消息。因为字母有大小写之分,所以要 TranslateMessage() 翻译消息。游戏角色的 WASD 移动不需要翻译,打字输入文本需要区分大小写,需要翻译。

GetMessage() 函数抓取的消息非常多,包括鼠标消息等等,只有是键盘消息的情况下才会进行翻译。

常见消息

所有的消息都是使用 #define 进行定义的:
在这里插入图片描述
每个消息都有一个数值,0x 表示十六进制数(消息的数值ID)。

WM_DESTROY

产生时间,窗口被销毁时的消息(不等于窗口被关闭),一般用法(不是必须用法)常用于窗口被销毁前,做相应的善后处理,例如资源、内存等。

WM_CLOSE

窗口关闭按钮被点击时产生。

WM_SYSCOMMAND

产生时间:当点击窗口的最大化、最小化、关闭等时。

附带信息:

  • wParam:具体点击的位置,例如关闭SC_CLOSE等
  • lParam:鼠标光标的位置。lParam 是一个占 4个字节 的长整型数据,低16位保存 x 坐标,高16位保存 y 坐标。
    • LOWORD(lParam); //水平位置
    • HIWORD(lParam); //垂直位置

一般用法:常用在窗口关闭时,提示用户处理。

LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{switch (msgID){case WM_CLOSE:PostQuitMessage(0);break;case WM_SYSCOMMAND:MessageBox(hWnd,"WM_SYSCOMMAND", "Infor", MB_OK);     //弹出提示框  break;}return DefWindowProc(hWnd, msgID, wParam, lParam);
}
case WM_CLOSE:PostQuitMessage(0);break;
case WM_SYSCOMMAND:if (wParam == SC_CLOSE)    //如果点击的是关闭按钮      {int nRet = MessageBox(hWnd, "是否退出?", "Infor", MB_YESNO);if (nRet == IDYES){//什么代码都不写,最后 return DefWindowProc(),该函数会默认处理关闭,给到 WM_CLOSE case}elsereturn 0;        //return 0;则不会执行最后的 return DefWindowProc()}
}

WM_CREATE

在窗口创建成功还未显示时,产生的消息。

附带信息:

  • wParam :为 0;
  • lParam :为 CREATESTRUCT 类型的指针,通过这个指针可以获取 CreateWindowEx 函数的全部 12 个参数的信息。

一本用法:常用于初始化窗口的参数、资源等等,包括创建子窗口等。

在创建窗口的时候,最后参数加一个附加消息:

char extraMsg[20] = "Extra Message";      
HWND hWnd = CreateWindowEx(0, pClassName, "My Window",WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_OVERLAPPEDWINDOW,200, 200, 640, 480,        //窗口位置(200,200),大小长宽(640,480)。nullptr, nullptr, hIns, extraMsg     //传入一个附加消息
);

消息处理函数中加入对 WM_CREATE 消息的处理:

case WM_CREATE:OnCreate(hWnd, lParam);    //调用 OnCreate()函数break;

OnCreate 函数的内容如下:

void OnCreate(HWND hWnd, LPARAM lParam)
{CREATESTRUCT* ptrToStruct = (CREATESTRUCT*)lParam;     //将附加信息强制转换成 CREATESTRUCT 类型的指针char* msgContent = (char*)ptrToStruct->lpCreateParams;     //取出附加信息MessageBox(NULL, msgContent, "Infor", MB_OK);     //提示框显示附加信息
}

在这里插入图片描述
运行后,在窗口还没有显示之前,弹出了一个提示框,并将创建窗口时最后一个参数的附带信息显示了出来。

WM_SIZE

在窗口的大小发生变化的时候产生。

附加信息:

  • wParam :窗口大小发生变化的原因。
  • lParam :窗口变化后的大小。
    • LOWORD(lParam) //低16位表示变化后的宽度
    • HIWORD(lParam) //高16位表示变化后的高度

一般用法:常用于窗口的大小变化后,调整窗口各个部分的布局。

添加DOS窗口:
图形界面的窗口并不能让我们知道程序在运行过程中发生了什么,为了方便调试,可以为窗口添加一个DOS窗口,通过往DOS窗口中打印信息进行反馈从而知道程序运行过程中发生了什么。

//添加全局变量
HANDLE g_dos_output = 0;   //接收标准输出句柄//WinMain()窗口主函数中添加以下两行代码:
AllocConsole();    //增加DOS窗口
g_dos_output = GetStdHandle(STD_OUTPUT_HANDLE);   //获得标准输出句柄

在这里插入图片描述
测试 WM_SIZE 消息

//switch语句中添加:
case WM_SIZE:OnSize(hWnd, lParam);break;//OnSize()函数:
void OnSize(HWND hWnd, LPARAM lParam) {short width = LOWORD(lParam);    //低两个字节窗口宽度short hight = HIWORD(lParam);    //高两个字节窗口高度char text[256] = { 0 };sprintf_s(text, "WM_SIZE: 宽 %d,高 %d\n", width, hight);WriteConsole(g_dos_output, text, strlen(text), NULL, NULL);
}//添加头文件
#include <stdio.h>

每次窗口发生变化的时候在DOS窗口中打印信息:
在这里插入图片描述

WM_QUIT

产生时间:程序员发送。

附带信息:

  • wParam :PostQuitMessage() 函数传递的参数。
  • lParam :0。

一般用法:用于结束消息循环,当 GetMessage() 抓到 WM_QUIT 消息后,返回 False , 结束 while 循环。

消息循环的原理

消息循环的阻塞 : GetMessage()函数 VS PeekMessage() 函数

  • GetMessage() 从系统获取消息,将消息从系统中移除,阻塞函数。当系统无消息的时候会等候消息。当消息队列中没有消息时,GetMessage() 函数会阻塞,也就意味着程序停在 GetMessage() 这里。只有有消息时才会继续执行下去。程序阻塞时不再参与 CPU 的调度,进入睡觉状态。如果消息队列中经常没有消息,意味着程序经常进入阻塞状态,这样的程序效率并不是很高。对于我们人的感觉来说,消息是每时每刻都有的,但对于高速运转的 CPU 来说,消息并不常有,意味着程序经常阻塞(对CPU来说)。
  • PeekMessage() 以查看的方式从系统中获取消息,可以不将消息从系统中移除,非阻塞函数。当系统无消息时,返回 False,继续执行后面的代码。
    • 函数定义:
    BOOL PeekMessage(LPMSG lpMsg,      //MSG结构体指针HWND hWnd,      //窗口句柄 handle to windowUINT wMsgFilterMin,      //消息ID的下限UINT wMsgFilterMax,    //消息ID的上限UINT wRemoveMsg,     //移除标识,是否从消息队列中移除消息// PM_REMOVE / PM_NOREMOVE
    );
    

更加高效地抓取消息

... WinMain(...) {... ...MSG nMsg = { 0 };BOOL gResult;while (1)     //先进入死循环,循环体中进行判断是否退出循环{if (PeekMessage(&nMsg, NULL, 0, 0, PM_NOREMOVE))  //PeekMessage侦察兵侦察是否有消息,如果有消息{if ((gResult = GetMessage(&nMsg, NULL, 0, 0 )) > 0)  //gResult值大于零意味着GetMessage没有抓到 WM_QUIT(返回值为0) 也没有出错(出错返回值为-1){TranslateMessage(&nMsg);DispatchMessage(&nMsg);}else      //如果抓到 WM_QUIT 或者 出错 退出while循环{break;}}else    //如果PeekMessage()没有侦察到消息,空闲处理{WriteConsole(g_dos_output, "No Message", strlen("No Message"), NULL, NULL);}}if (gResult == -1)   //GetMessage()出错返回值 -1{//错误处理或直接退出程序		return -1;}else   //抓到 WM_QUIT 消息,退出程序,返回 PostQuitMessage()的参数值{return nMsg.wParam;    //此时 wParam 是 PostQuitMessage()的参数值}
}

从DOS窗口打印的结果来看,进程绝大多数时间都处于没有消息的状态:

在这里插入图片描述

发送消息 : SendMessage()函数 VS PostMessage() 函数

消息如何产生的?
在这里插入图片描述
消息的产生:

  • 操作系统进程发送
  • 程序员编写的程序的进程发送

在Windows操作系统上,几乎所有的消息都是以下这两个函数发送的:

  • SendMessage() :发送消息,会等候消息的处理结果。
  • PostMessage() :投递消息,消息发出后立即返回,不等候消息执行结果。
BOOL SendMessage / PostMessage(HWND hWnd, //消息发送的目的窗口UINT Msg,   //消息IDWPARAM wParam,    //消息参数LPARAM lParam     //消息参数
);

包括程序退出发出 WM_QUIT 消息时调用的 PostQuitMessage(); 函数内部,也是调用了上面的 PostMessage() 函数。

case WM_CLOSE:    //窗口关闭//PostQuitMessage(0);PostMessage(hWnd, WM_QUIT, 0, 0);    //程序成功退出//SendMessage(hWnd, WM_QUIT, 0, 0);  //程序没有退出break;

这两个函数都是 Windows API 提供的函数,用于在应用程序之间或者在同一个应用程序的不同窗口之间发送消息。

  • SendMessage() 函数会同步发送消息,即函数调用会一直等待接收方处理完消息后才返回。这使得消息的发送和接收在时间上是连续的,适用于需要确保消息被及时处理的场景。

  • PostMessage() 函数则是异步发送消息,即函数调用后立即返回,不等待接收方处理完消息。这使得消息的发送和接收在时间上是分离的,适用于不需要立即响应的场景。

在这里插入图片描述
使用 SendMessage() 函数发送 WM_QUIT 消息,程序并没有成功退出,那么该函数把 WM_QUIT 消息发送到哪了呢?参见后文。

消息分类

  • 系统消息:微软官方定制好的消息,在操作系统内部,可以直接使用。ID范围:0 ~ 0x03FF
  • 用户自定义消息:如果系统消息中没有一个消息能够满足程序员自己的需求,那么我们可以自己定义消息。ID范围:0x400 ~ 0x7FFF(31743)。自定义消息宏:WM_USER。自己定义的消息需要自己发送并处理。
//自定义消息,添加宏定义
#define MY_MESSAGE WM_USER + n

n 取值 0 ~ 31743。

在这里插入图片描述

在这里插入图片描述

消息队列

  • 消息队列是用于存放消息的队列(数据结构)。
  • 消息在队列中先进先出(FIFO:First-In-First-Out)。
  • 所有的窗口程序都有消息队列。
  • 程序可以从队列中获取消息。

消息队列分类

  • 系统消息队列:由操作系统进行维护,存放系统产生的消息。系统的消息队列要保存所有进程产生的消息,所以它非常庞大。进程产生的消息首先要进系统的消息队列。
  • 程序消息队列:属于每一个应用程序(主线程)的消息队列。由应用程序(线程)维护。

在操作系统上可能同时运行着很多进程,各个进程的 GetMessage() 函数是到本进程的消息队列中抓取消息。绝大多数消息产生后先进系统消息队列,再由操作系统每隔一段时间转发到各个进程的消息队列中。

操作系统可以根据消息的 窗口句柄 hWnd 找到保存窗口数据的内存,在这块内存中有一个当前程序实例句柄 Instance,而当前程序的实例句柄 Instance 可以找到当前进程所占的一块内存,从而将每一个消息正确地转发给各个进程的消息队列。

消息和消息队列的关系

  • 消息和消息队列的关系
    1. 当鼠标、键盘等产生消息时,会将消息存放到系统消息队列。
    2. 系统会根据存放的消息,找到对应程序的消息队列。
    3. 将消息投递到程序的消息队列中。
  • 根据消息和消息队列之间的使用关系,将消息分类为:
    • 队列消息:消息的发送和获取,都是通过消息队列完成的。
    • 非队列消息:消息的发送和获取,是直接调用消息的窗口处理函数完成的。

在这里插入图片描述

PostMessage() 把消息发送到操作系统的消息队列中,由操作系统派发到进程的消息队列中。

SendMessage() 把消息直接发送给 WndProc() 进行处理并等待返回。

PostMessage() 发送的消息为 队列消息。常见队列消息:WM_PAINT、WM_QUIT(必须进队列)、键盘、鼠标、定时器等。

SendMessage() 发送的消息为 非队列消息。常见消息:WM_CREATE(必须不能进队列)、WM_SIZE(窗口第一次创建到显示时产生不进队列,后面可以进队列)等。

消息本身没有队列或非队列的属性。

深入 GetMessage() 函数

到本进程的消息队列中抓去本进程的消息。GetMessage() 函数做的事情如下:

  • 在程序(线程)消息队列中查找消息,如果队列有消息,检查消息是否满足指定条件(HWND, ID范围),不满足条件就不会取出消息,否则从消息队列中取出消息并返回。
  • 如果程序(线程)队列中没有消息,向操作系统消息队列要本程序的消息。如果系统队列中有消息属于本程序,系统会将消息转发到程序消息队列中。
  • 如果系统的消息队列中也没有属于本程序的消息,则检查当前进程的所有窗口的需要重新绘制的区域,如果发现有需要绘制的区域,产生 WM_PAINT 消息,取得消息返回处理。
  • 如果没有重新绘制的区域,检查定时器如果有到时的定时器,产生 WM_TIMER,返回处理执行。
  • 如果没有到时的定时器,整理程序的资源、内存等。
  • 如果以上条件都不满足,GetMessage() 才会进入阻塞状态。PeekMessage()会做以上同样的事情,但是不会阻塞等待消息,而是直接返回 False。


---------------------------------------------------------------------------- 后续更新,关注不迷路 ---------------------------------------------------------------

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XS9922驱动

XS9922B 是一款四通道多合一模拟高清解码器&#xff0c;支持HDcctv高清协议和CVBS标清协议。它最大支持1080p 30fps的视频分辨率&#xff0c;具有以下亮点&#xff1a; 四通道视频输入MIPI CSI-2 4-Lane视频输出支持音频传输封装&#xff1a;QFN88&#xff0c;尺寸为10mm x 1…

安装IntelliJ IDEA

文章目录 一、前言二、下载IDEA三、安装四、破解 一、前言 工欲善其事必先利其器&#xff0c;学习JAVA的第一步&#xff0c;首先是安装IDE&#xff0c;配置环境&#xff1b; 常用的JAVA IDE是IntelliJ IDEA和eclipse&#xff0c;我选择IntelliJ IDEA 二、下载IDEA 官网下载&…

MT3023 歌词中找单词

1.暴力 10/12 #include <bits/stdc.h> using namespace std; int n; string a[10005]; int main() {cin >> n;for (int i 0; i < n; i)cin >> a[i];string ll;cin >> ll;for (int i 0; i < n; i){string u a[i];int num 0;int j 0;for (in…

算法课程笔记——STL题目

长度为2的字符串&#xff0c;当in下标为一&#xff0c;也就是\n,当i&#xff01;n&#xff0c;就是输出空格 &&且 city从citys里面取 加速后就不能混用scanf

MySql运维篇

目录 一.日志 1.1日志分类 1.2Error Log 1.3BinaryLog 1.4SlowQuery Log 二.备份 2.1备份原因 2.2备份目标 2.3备份技术 2.3.1物理备份 2.3.2逻辑备份 2.4备份方式 2.4.1完全备份 2.4.2增量备份 2.4.3差异备份 2.5备份环境准备 2.6完全备份实验 2.6.1完全备…

Jenkins服务器IP更换,Jenkins URL地址更换

服务器的网络地址发生变动&#xff0c;修改jenkins服务器IP地址后&#xff0c;jenkins网页能够打开&#xff0c;但是job中的配置钩子没有自动改变&#xff0c;如图所示&#xff1a; 经过查询资料了解&#xff0c;需要修改jenkins本地化配置地址才可以显示正确&#xff1a; 1、…

上位机图像处理和嵌入式模块部署(树莓派4b和驱动的编写)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 树莓派4b上面还支持驱动代码的编写&#xff0c;这是我没有想到的。这里驱动&#xff0c;更多的是一种框架的编写&#xff0c;不一定是编写真正的驱…

苹果开发初学者指南:Xcode 如何为运行的 App 添加环境变量(Environmental Variable)

概览 Xcode 15 在运行 SwiftUI 代码时突然报告如下警告&#xff1a; Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem. 不仅如此…

scratch图章画图 2024年3月中国电子学会图形化编程 少儿编程 scratch编程等级考试四级真题和答案解析

目录 scratch图章画图 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、p…

mysql基础14——视图

视图 视图是一种虚拟表 可以把一段查询语句作为视图存储在数据库中 需要的时候把视图看作一个表&#xff0c;对里面的数据进行查询 视图并没有真正存储数据 避免了数据存储过程中可能产生的冗余 提高了存储的效率 子查询 嵌套在另一个查询中的查询 派生表 如果在查询中…

【linux】基础IO(软硬链接)

上一节我们已经搞懂了已经被打开的文件&#xff0c;还有没有被打开的文件都是怎样被管理起来的&#xff0c;同样&#xff0c;路径的重要性也不言而喻&#xff0c;是确定文件在那个分区&#xff0c;进而可以解析到目标文件与目录内容的关系&#xff0c;从而找到inode&#xff0c…

机器学习预测汽车油耗效率 MPG

流程 数据获取导入需要的包引入文件,查看内容划分训练集和测试集调用模型查看准确率 数据获取 链接&#xff1a;https://pan.baidu.com/s/1KeIJykbcVpsfEk0xjhiICA?pwd30oe 提取码&#xff1a;30oe --来自百度网盘超级会员V1的分享导入需要的包 import pandas as pd imp…