当前位置: 首页 > news >正文

Windows窗口

Windows窗口

Unit01注册窗口类

01窗口类的概念

  • 窗口类是包括了窗口的各种参数信息数据结构
  • 每个窗口都具有窗口类,基于窗口类创建窗口
  • 每个窗口都具有一个名称,使用前必须注册到系统

02窗口类的分类

  • 系统窗口类
    系统已经定义好的窗口类,所有应用程序都可以直接使用
  • 应用程序全局窗口类
    由用户自己定义,当前应用程序所有模块都可以使用
  • 应用程序局部窗口类
    由用户自己定义,当前应用程序中本模块可以使用

03系统窗口

  • 不需要注册,直接使用窗口类即可。系统已经注册好了
    例如:

    • 按钮:BUTTON
    • 编辑框:EDIT
  • 示例:创建一个巨大的按钮

#include <windows.h>//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{//在内存创建窗口HWND hWnd = CreateWindow("Button","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}

在这里插入图片描述

04全局及局部窗口类

  • 注册窗口类的函数
ATON RegisterClass(CONST WNDCLASS *lpWndClass//窗口类的数据
);//注册成功后,返回一个数字标识(返回0注册失败,非0注册成功)
  • 注册窗口类的结构体
typedef struct _WNDCLASS{UINT style;//窗口类的风格WNDPROC lpfnWndProc;//窗口处理函数int cbClsExtra;//窗口类的附加数据buff的大小int cbWndExtra;//窗口的附加数据buff的大小HINSTANCE hInstance;//当前模块的实例句柄HICON hIcon;//窗口图标句柄HCURSOR hCursor,//鼠标的句柄HBRUSH hbrBackground,//绘制窗口背景的画刷句柄LPCTSTR lpszMenuName,//窗口菜单的资源ID字符串LPCTSTR lpszClassName//窗口类的名称
}WNDCLASS,*PWNDCLASS;
  • style窗口类风格
    • 应用程序全局窗口类的注册,需要在窗口类的风格中增加CS_GLOBALCLASS
      例如:
    WNDCLASS wce = {0};
    wce.style = ...|CS_GLOBALCLASS;
    
    • 应用程序局部窗口类:在注册窗口类时,不添加CS_GLOBALCLASS风格
    • 其他窗口类风格:
      • CS_HREDREAW:当窗口水平发生变化时,窗口重新绘制
      • CS_VREDREAW:当窗口垂直发生变化时,窗口重新绘制
      • CS_DBLCLKS:允许窗口接收鼠标双击
      • CS_NOCLOSE:窗口没有关闭按钮

Unit02窗口创建

01窗口创建

  • CreateWindow/CreateWindowEx
HWND CreateWindowEx{DWORD dwExStyle,//窗口的扩建风格LPCTSTR lpClassName,//已经注册的窗口类名称LPCTSTR lpWindowName,//窗口标题栏的名字DWORD dwStyle,//窗口的基本风格int x,//窗口左上角水平坐标位置int y,//窗口左上角的垂直坐标位置int nWidth,//窗口的宽度int nHeight,//窗口的高度HWND hWndParent,//窗口的父窗口句柄HMENU hMenu,//窗口菜单句柄HINSTANCE hInstance,//应用程序实例句柄LPVOID lpParam//窗口创建时俯角参数
};//创建成功返回窗口句柄
#include <windows.h>//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}

02窗口创建执行过程

  • 1.系统(CreateWindowEx函数内部)根据传入的窗口类名称,在因用程序局部窗口类中查找,如果找到执行第2步,否则执行第3步
  • 2.比较局部窗口类与创建时传入的HINSTANCE变量。如果发现相等,创建和注册的窗口类在同一模块,创建窗口返回。如果不相等,继续执行第3步
  • 3.在应用程序全局窗口类,如果找到执行第4步,否则执行第5步
  • 4.使用找到的窗口类的信息,创建窗口返回
  • 5.在系统窗口类中查找,如果找到创建窗口返回,否则创建窗口失败
    在这里插入图片描述
    解决遗留问题:点击窗口的关闭按钮可以完全退出进程,不用在任务管理器中杀死进程
#include <windows.h>//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;}return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}

03 子窗口创建

  • 创建时要设置父窗口句柄
  • 创建风格要增加WS_CHILD|WS_VISIBLE
#include <windows.h>//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;}return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);//子窗口窗口类wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Child";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//子窗口1HWND hChild1 = CreateWindowEx(0,"Child","c1",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,0,0,200,200,hWnd,NULL,hIns,NULL);//子窗口2HWND hChild2 = CreateWindowEx(0,"Child","cc",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,200,0,200,200,hWnd,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}

在这里插入图片描述

Unit03消息基础

01消息的概念和作用

  • 消息组成(Windows平台下的消息)
    • 窗口句柄
    • 消息ID
    • 消息的两个参数(两个附带信息)
    • 消息的产生时间
    • 消息产生时的鼠标位置
  • 消息的作用
    • 当系统通知窗口工作时,就采用消息的方式(DispatchMessage)派发给窗口的窗口处理函数
/** Message structure*/
typedef struct tagMSG {HWND        hwnd;UINT        message;WPARAM      wParam;LPARAM      lParam;DWORD       time;POINT       pt;
#ifdef _MACDWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

在这里插入图片描述

02窗口处理函数

  • 每个窗口都必须具有窗口处理函数
LRESULT CALLBACK WindowProc(HWND hwnd,//窗口句柄UINT uMsg,//消息IDWPARAM wParam,//消息参数LPARAM lParam//消息参数
);
  • 当系统通知窗口时,会调用窗口处理函数,同时将消息ID和消息参数床底给窗口处理函数。在窗口处理函数中,不处理的消息,使用缺省窗口处理函数。例如:DefWindowProc

03 浅谈消息相关函数

  • GetMessage获取本进程的消息
BOOL GetMessage(LPMSG lpMsg,//存放获取到的消息BUFF//后面三个参数都是指定抓取消息的范围HWND hWnd,//窗口句柄(如果指定为NULL,表示抓取全部窗口的消息)UINT wMsgFilterMin,//获取消息的最小IDUINT wMsgFilteMax//获取消息的最大ID
);
//lpMsg:当获取到消息后,将消息的参数存放到MSG结构中
//hWnd:获取到hWnd所指定窗口的消息
//wMsgFilterMin和wMsgFilteMax:只能获取到由它们指定的消息范围内的消息,如果都为0,表示没有范围

在这里插入图片描述

  • TranslateMessage翻译消息,将按键消息,翻译成字符消息
    检查消息是否是按键的消息,如果不是按键消息,不做任何处理,继续执行(该函数只翻译可见字符的按键消息)
BOOL TranslateMessage(const MSG* lpMsg//要翻译的消息地址
); 
  • DispatchMessage派发消息
    将消息派发到该消息所属窗口的窗口处理函数上
LONG LONG DispatchMessage(  const MSG* lpmsg //要派发的消息
);

Unit04常见消息

01WM_DESTORY

  • 产生时间:窗口被销毁时的消息
  • 附带信息:
    • wParam:0
    • lParam:0
  • 一般用法:常用语在窗口销毁之前,做相应的善后处理,例如资源、内存的释放等
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;}return DefWindowProc(hWnd, msgID, wParam, lParam);//给各种消息默认处理
} 

02WM_SYSCOMMAND

  • 产生时间:当点击窗口的最大化、最小化、关闭等
  • 附带信息:
    • wParam:具体点击的位置,例如关闭SC_CLOSE
    • lParam:鼠标光标的位置(使用一个long类型的高低位分别存储两个数,使用下面的两个宏定义取出两个数)
      • LOWORD(lParam);//水平位置
      • HIWORD(lParam);//垂直位置
  • 一般用法:常用在窗口关闭时,提示用户处理
#include <windows.h>//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;case WM_SYSCOMMAND:MessageBox(hWnd,"02WM_SYSCOMMAND","Info",MB_OK);break;}return DefWindowProc(hWnd, msgID, wParam, lParam);//给各种消息默认处理
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);//子窗口窗口类wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Child";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//子窗口1HWND hChild1 = CreateWindowEx(0,"Child","c1",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,0,0,200,200,hWnd,NULL,hIns,NULL);//子窗口2HWND hChild2 = CreateWindowEx(0,"Child","cc",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,200,0,200,200,hWnd,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}

在这里插入图片描述

#include <windows.h>//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;case WM_SYSCOMMAND:if(wParam == SC_CLOSE){MessageBox(hWnd,"是否退出","Info",MB_YESNO);}else{return 0;}break;}return DefWindowProc(hWnd, msgID, wParam, lParam);//给各种消息默认处理
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);//子窗口窗口类wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Child";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//子窗口1HWND hChild1 = CreateWindowEx(0,"Child","c1",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,0,0,200,200,hWnd,NULL,hIns,NULL);//子窗口2HWND hChild2 = CreateWindowEx(0,"Child","cc",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,200,0,200,200,hWnd,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}

在这里插入图片描述

03WM_CREATE

  • 产生时间:在窗口创建成功但还没显示时
  • 附带信息:
    • wParam:0
    • lParam:为CREATESTRUCT类型的指针。通过这个指针获取CreateWindowEx中的全部12个参数的信息
  • 一般用法:常用于初始化窗口的参数、资源等等,包括创建子窗口等
#include <windows.h>void onCreate(HWND hWnd, LPARAM lParam){CREATESTRUCT* psc = (CREATESTRUCT*)lParam;char* pszText = (char*)psc->lpCreateParams;MessageBox(NULL, pszText,"Info",MB_OK);//创建子窗口CreateWindowEx(0,"EDIT","hello",WS_CHILD|WS_VISIBLE|WS_BORDER,0,0,200,200,hWnd,NULL,0,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_CREATE:onCreate(hWnd, lParam);break;case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;case WM_SYSCOMMAND:if(wParam == SC_CLOSE){MessageBox(hWnd,"是否退出","Info",MB_YESNO);}else{return 0;}break;}return DefWindowProc(hWnd, msgID, wParam, lParam);//给各种消息默认处理
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口char* pszText = "hello data";HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,pszText);//子窗口窗口类wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Child";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//子窗口1HWND hChild1 = CreateWindowEx(0,"Child","c1",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,0,0,200,200,hWnd,NULL,hIns,NULL);//子窗口2HWND hChild2 = CreateWindowEx(0,"Child","cc",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,200,0,200,200,hWnd,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}

04WM_SIZE

  • 产生时间:在窗口的大小发生变化
  • 附带信息:
    • wParam:窗口大小变化的原因
    • lParam:窗口变化后的大小
      • LOWORD(lParam);//水平位置
      • HIWORD(lParam);//垂直位置
  • 一般用法:常用于窗口大小变化后,调整窗口内各个部分的布局
#include <windows.h>
#include <stdio.h>HANDLE g_hOutput = 0;//接收标准输出句柄
void onSize(HWND hWnd, LPARAM lParam){short nWidth = LOWORD(lParam);short nHight = HIWORD(lParam);char szText[256] = {0};sprintf(szText, "WM_SIZE:宽:%d,高:%d\n", nWidth, nHight);WriteConsole(g_hOutput, szText,strlen(szText),NULL,NULL);
}void onCreate(HWND hWnd, LPARAM lParam){CREATESTRUCT* psc = (CREATESTRUCT*)lParam;char* pszText = (char*)psc->lpCreateParams;MessageBox(NULL, pszText,"Info",MB_OK);//创建子窗口CreateWindowEx(0,"EDIT","hello",WS_CHILD|WS_VISIBLE|WS_BORDER,0,0,200,200,hWnd,NULL,0,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_SIZE:onSize(hWnd, lParam);break;case WM_CREATE://onCreate(hWnd, lParam);break;case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;case WM_SYSCOMMAND:if(wParam == SC_CLOSE){MessageBox(hWnd,"是否退出","Info",MB_YESNO);}else{return 0;}break;}return DefWindowProc(hWnd, msgID, wParam, lParam);//给各种消息默认处理
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{AllocConsole();//增加一个DOC窗口g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口char* pszText = "hello data";HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,pszText);//子窗口窗口类wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Child";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//子窗口1HWND hChild1 = CreateWindowEx(0,"Child","c1",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,0,0,200,200,hWnd,NULL,hIns,NULL);//子窗口2HWND hChild2 = CreateWindowEx(0,"Child","cc",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,200,0,200,200,hWnd,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}

在这里插入图片描述

05WM_QUIT

  • 产生时间:程序员发送
  • 附带信息:
    • wParam:PostQuitMessage函数传递参数
    • lParam:0
  • 一般用法:用于结束消息循环,当GetMessage收到这个消息后,会返回FALSE,结束while处理,退出消息循环

Unit05消息循环的原理

01消息循环的阻塞

  • GetMessage从系统获取消息,将消息从系统中移除,是一个阻塞函数。当系统无消息时,会一直等待下一条消息的到来。
  • PeekMessage以查看的方式从系统中获取消息,可以不将消息从系统中移除,是一个非阻塞函数。当系统无消息时,返回FALSE,继续执行后续程序(相当于只负责侦查而不负责处理消息)
BOOL PeekMessage( LPMSG lpMsg,   //message informationHWND hWnd,   //handle to windowUINT wMsgFilterMin, //first messageUINT wMsgFilterMax, //last messageUINT wRemoveMsg//移除标识,赋值PM_NOREMOVE或PM_REMOVE); 

在这里插入图片描述

	while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}
//将处理消息的while循环可以换一种高效的写法了while(1){if(PeekMessage(&nMsg,NULL,0,0,PM_NOREMOVE)){//有消息if(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);}else{return 0;}}else{//空闲处理WriteConsole(g_hOutput,"OnIdle",strlen("OnIdle"),NULL,NULL);}}

示例:

#include <windows.h>
#include <stdio.h>HANDLE g_hOutput = 0;//接收标准输出句柄
void onSize(HWND hWnd, LPARAM lParam){short nWidth = LOWORD(lParam);short nHight = HIWORD(lParam);char szText[256] = {0};sprintf(szText, "WM_SIZE:宽:%d,高:%d\n", nWidth, nHight);WriteConsole(g_hOutput, szText,strlen(szText),NULL,NULL);
}void onCreate(HWND hWnd, LPARAM lParam){CREATESTRUCT* psc = (CREATESTRUCT*)lParam;char* pszText = (char*)psc->lpCreateParams;MessageBox(NULL, pszText,"Info",MB_OK);//创建子窗口CreateWindowEx(0,"EDIT","hello",WS_CHILD|WS_VISIBLE|WS_BORDER,0,0,200,200,hWnd,NULL,0,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_SIZE:onSize(hWnd, lParam);break;case WM_CREATE://onCreate(hWnd, lParam);break;case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;case WM_SYSCOMMAND:if(wParam == SC_CLOSE){MessageBox(hWnd,"是否退出","Info",MB_YESNO);}else{return 0;}break;}return DefWindowProc(hWnd, msgID, wParam, lParam);//给各种消息默认处理
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{AllocConsole();//增加一个DOC窗口g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口char* pszText = "hello data";HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,pszText);//子窗口窗口类wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Child";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//子窗口1HWND hChild1 = CreateWindowEx(0,"Child","c1",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,0,0,200,200,hWnd,NULL,hIns,NULL);//子窗口2HWND hChild2 = CreateWindowEx(0,"Child","cc",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,200,0,200,200,hWnd,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(1){if(PeekMessage(&nMsg,NULL,0,0,PM_NOREMOVE)){//有消息if(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);}else{return 0;}}else{//空闲处理WriteConsole(g_hOutput,"OnIdle",strlen("OnIdle"),NULL,NULL);}}return 0;
}

02 发送消息

  • 消息的处理过程
    在这里插入图片描述
  • SendMessage发送消息,会等候消息处理的结果
  • PostMessage投递消息,消息发出后立即返回,不等待消息执行结果
LRESULT SendMessage / PostMessage(  HWND hWnd, //消息发送的目的窗口UINT Msg,   //消息IDWPARAM wParam,//消息参数  LPARAM lParam //消息参数
); 
#include <windows.h>
#include <stdio.h>HANDLE g_hOutput = 0;//接收标准输出句柄
void onSize(HWND hWnd, LPARAM lParam){short nWidth = LOWORD(lParam);short nHight = HIWORD(lParam);char szText[256] = {0};sprintf(szText, "WM_SIZE:宽:%d,高:%d\n", nWidth, nHight);WriteConsole(g_hOutput, szText,strlen(szText),NULL,NULL);
}void onCreate(HWND hWnd, LPARAM lParam){CREATESTRUCT* psc = (CREATESTRUCT*)lParam;char* pszText = (char*)psc->lpCreateParams;MessageBox(NULL, pszText,"Info",MB_OK);//创建子窗口CreateWindowEx(0,"EDIT","hello",WS_CHILD|WS_VISIBLE|WS_BORDER,0,0,200,200,hWnd,NULL,0,NULL);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_SIZE:onSize(hWnd, lParam);break;case WM_CREATE://onCreate(hWnd, lParam);break;case WM_DESTROY://PostQuitMessage(0);//可以使GetMessage函数返回0//窗口能顺利关闭,说明GetMessage能抓到PostMessage发送的消息PostMessage(hWnd, WM_QUIT, 0, 0);//PostQuitMessage内部调用此函数//窗口不能顺利关闭,说明GetMessage不能抓到SendMessage发送的消息//SendMessage(hWnd, WM_QUIT, 0, 0);break;case WM_SYSCOMMAND:if(wParam == SC_CLOSE){MessageBox(hWnd,"是否退出","Info",MB_YESNO);}else{return 0;}break;}return DefWindowProc(hWnd, msgID, wParam, lParam);//给各种消息默认处理
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{AllocConsole();//增加一个DOC窗口g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口char* pszText = "hello data";HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,pszText);//子窗口窗口类wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Child";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//子窗口1HWND hChild1 = CreateWindowEx(0,"Child","c1",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,0,0,200,200,hWnd,NULL,hIns,NULL);//子窗口2HWND hChild2 = CreateWindowEx(0,"Child","cc",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,200,0,200,200,hWnd,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(1){if(PeekMessage(&nMsg,NULL,0,0,PM_NOREMOVE)){//有消息if(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);}else{return 0;}}else{//空闲处理WriteConsole(g_hOutput,"OnIdle",strlen("OnIdle"),NULL,NULL);}}return 0;
}

03消息分类

  • 系统消息:ID范围0-0x3FF,由系统定义好的消息,可以在程序中直接使用(注意系统消息要么程序员只负责处理不负责发送,如WM_SIZE,要么只负责发送不负责处理,如WM_QUIT)
  • 用户自定义消息:ID范围0x0400-0x7FFF(31743)'
    • 由用户自己定义,满足用户自己的需求,由用户自己发出消息,并相应处理
    • 自定义消息宏:WM_USER

自定义消息示例

#include <windows.h>
#include <stdio.h>
//自定义消息
#define WM_MYMESSAGE WM_USER+1001HANDLE g_hOutput = 0;//接收标准输出句柄
void onSize(HWND hWnd, LPARAM lParam){short nWidth = LOWORD(lParam);short nHight = HIWORD(lParam);char szText[256] = {0};sprintf(szText, "WM_SIZE:宽:%d,高:%d\n", nWidth, nHight);WriteConsole(g_hOutput, szText,strlen(szText),NULL,NULL);
}void onCreate(HWND hWnd, LPARAM lParam){CREATESTRUCT* psc = (CREATESTRUCT*)lParam;char* pszText = (char*)psc->lpCreateParams;MessageBox(NULL, pszText,"Info",MB_OK);//发送自定消息(自己爱在哪里发送就写在哪里)PostMessage(hWnd,WM_MYMESSAGE,1,2);//创建子窗口CreateWindowEx(0,"EDIT","hello",WS_CHILD|WS_VISIBLE|WS_BORDER,0,0,200,200,hWnd,NULL,0,NULL);
}void onMyMessage(HWND hWnd, WPARAM wParam, LPARAM lParam){char szText[256] = {0};sprintf(szText,"自定义消息被处理:wParam=%d,lParam=%d\n", wParam, lParam);MessageBox(hWnd, szText, "Infor", MB_OK);
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_MYMESSAGE:onMyMessage(hWnd,wParam, lParam);break;case WM_SIZE:onSize(hWnd, lParam);break;case WM_CREATE://onCreate(hWnd, lParam);break;case WM_DESTROY://PostQuitMessage(0);//可以使GetMessage函数返回0//窗口能顺利关闭,说明GetMessage能抓到PostMessage发送的消息PostMessage(hWnd, WM_QUIT, 0, 0);//PostQuitMessage内部调用此函数//窗口不能顺利关闭,说明GetMessage不能抓到SendMessage发送的消息//SendMessage(hWnd, WM_QUIT, 0, 0);break;case WM_SYSCOMMAND:if(wParam == SC_CLOSE){MessageBox(hWnd,"是否退出","Info",MB_YESNO);}else{return 0;}break;}return DefWindowProc(hWnd, msgID, wParam, lParam);//给各种消息默认处理
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{AllocConsole();//增加一个DOC窗口g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口char* pszText = "hello data";HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,pszText);//子窗口窗口类wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Child";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//子窗口1HWND hChild1 = CreateWindowEx(0,"Child","c1",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,0,0,200,200,hWnd,NULL,hIns,NULL);//子窗口2HWND hChild2 = CreateWindowEx(0,"Child","cc",WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,200,0,200,200,hWnd,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(1){if(PeekMessage(&nMsg,NULL,0,0,PM_NOREMOVE)){//有消息if(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);}else{return 0;}}else{//空闲处理WriteConsole(g_hOutput,"OnIdle",strlen("OnIdle"),NULL,NULL);}}return 0;
}

相关文章:

Windows窗口

Windows窗口 Unit01注册窗口类 01窗口类的概念 窗口类是包括了窗口的各种参数信息的数据结构每个窗口都具有窗口类&#xff0c;基于窗口类创建窗口每个窗口都具有一个名称&#xff0c;使用前必须注册到系统 02窗口类的分类 系统窗口类 系统已经定义好的窗口类&#xff0c;…...

Spring Transaction 源码解读

Spring Transaction 规范的maven坐标如下&#xff1a; <dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>...</version></dependency>该包提供了spring事务规范和默认的jta(ja…...

[Netty] Channel和ChannelFuture和ChannelFutureListener (六)

文章目录1.Channel介绍2.ChannelFuture接口介绍3.GenericFutureListener接口介绍1.Channel介绍 NIO的Channel与Netty的Channel 不一样 Netty重新设计了Channel接口,并且给予了很多不同的实现, Channel是Netty网络的抽象类, 除了NIO中Channel所包含的网络I/O操作, 主动建立和关…...

条件渲染

组件经常需要根据不同条件显示不同内容。在React中&#xff0c;你可以使用类似于if语句、&&和?:运算符的JavaScript语法有条件地呈现JSX。你将学到&#xff1a;如何根据条件返回不同的JSX如何有条件地包含或排除一段JSX在React代码库中常见的条件语法快捷方式有条件地…...

springboot(10)异步任务

文章目录1、SpringBoot异步任务1.1使用注解EnableAsync开启异步任务支持1.2使用Async注解标记要进行异步执行的方法1.3controller测试2.异步任务相关限制3.1自定义 Executor3.1.1应用层级&#xff1a;3.1.2方法层级&#xff1a;3.2自定义 Executor (第二种方式)4.1异常处理4.1.…...

清华大学开源的chatGLM-6B部署实战

Windows部署 win10 通过wsl部署 常见问题: torch.cuda.OutOfMemoryError: CUDA out of memory. 在Windows的系统环境变量中增加 变量名:PYTORCH_CUDA_ALLOC_CONF 变量值:max_split_size_mb:32 文档书写时使用3090 24G显存配置,其他规格酌情调整 32 至其他值,如未设置变…...

通过矩阵从整体角度搞懂快速傅里叶变换原理

离散傅里叶变换公式 公式 f[k]∑n0N−1g[n]e−i(2π/N)kn,其中(0<n<N)f[k]\sum_{n0}^{N-1}g[n]e^{-i(2\pi/N)kn}, 其中(0<n<N) f[k]n0∑N−1​g[n]e−i(2π/N)kn,其中(0<n<N) 逆变换公式 g[n]1N∑k0N−1f[k]ei(2π/N)kn,其中(0<k<N)g[n]\frac{1}{N}\…...

【C++从0到1】25、C++中嵌套使用循环

C从0到1全系列教程 1、实例代码 #include <iostream> // 包含头文件。 using namespace std; // 指定缺省的命名空间。int main() {// 超女分4个小组&#xff0c;每个小组有3名超女&#xff0c;在控制台显示每个超女的小组编号和组内编号。// 用一个循环…...

FastDFS与Nginx结合搭建文件服务器,并内网穿透实现公网访问

文章目录前言1. 本地搭建FastDFS文件系统1.1 环境安装1.2 安装libfastcommon1.3 安装FastDFS1.4 配置Tracker1.5 配置Storage1.6 测试上传下载1.7 与Nginx整合1.8 安装Nginx1.9 配置Nginx2. 局域网测试访问FastDFS3. 安装cpolar内网穿透4. 配置公网访问地址5. 固定公网地址5.1 …...

密集场景下的行人跟踪替代算法,头部跟踪算法 | CVPR 2021

一个不知名大学生&#xff0c;江湖人称菜狗 original author: Jacky LiEmail : 3435673055qq.com Time of completion&#xff1a;2023.4.8 Last edited: 2023.4.8 目录 摘要 主要内容 结果 这篇文章是CVPR 2021 的最新论文&#xff0c;文章的标题&#xff1a; 文章的主要内…...

Matlab与ROS(1/2)---服务端和客户端数据通信(五)

0. 简介 在前几讲我们讲了Matlab中的Message以及Topic的相关知识。而ROS主要支持的通信机制还有服务这一类。服务通过允许请求以及响应的通信方式&#xff0c;来给整个系统完成更紧密的耦合。服务客户端向服务服务器发送请求消息并等待响应。服务器将使用请求中的数据构造响应…...

数字化转型的避坑指南:细说数字化转型十二大坑

随着信息技术的快速发展&#xff0c;数字化转型已经成为许多企业发展的必经之路。然而&#xff0c;数字化转型过程中也存在许多坑&#xff0c;如果不谨慎处理&#xff0c;就可能导致企业陷入困境。本文将细说数字化转型的十二大坑&#xff0c;并提供相应的避坑指南。 1、不了解…...

pt05Encapsulationinherit

Encapsulation &inherit 封装继承 封装 向类外提供必要的功能&#xff0c;隐藏实现的细节, 代码可读性更高优势&#xff1a;简化编程&#xff0c;使用者不必了解具体的实现细节&#xff0c;只需要调用对外提供的功能。私有成员&#xff1a;作用&#xff1a;无需向类外提供…...

面向对象编程(基础)9:封装性(encapsulation)

目录 9.1 为什么需要封装&#xff1f; 而“高内聚&#xff0c;低耦合”的体现之一&#xff1a; 9.2 何为封装性&#xff1f; 9.3 Java如何实现数据封装 9.4 封装性的体现 9.4.1 成员变量/属性私有化 实现步骤&#xff1a; 成员变量封装的好处&#xff1a; 9.4.2 私有化…...

fate-serving-server增加取数逻辑并源码编译

1.什么是fate-serving-server? FATE-Serving 是一个高性能、工业化的联邦学习模型服务系统&#xff0c;专为生产环境而设计,主要用于在线推理。 2.fate-serving-server源码编译 下载fate-serving-serving项目&#xff08;GitHub - FederatedAI/FATE-Serving: A scalable, h…...

循环队列、双端队列 C和C++

队列 目录 概念 实现方式 顺序队列 循环队列 队列的数组实现 用循环链表实现队列 STL 之 queue 实现队列 STL 之 dequeue 实现双端队列 概念 队列是一种特殊的线性表&#xff0c;它只允许在表的前端&#xff08;称为队头&#xff0c;front&#xff09;进行删除操作…...

正则表达式(语法+例子)

文章目录一、介绍二、语法1、匹配字符2、表示数量的字符3、边界字符4、其他字符5、转义字符三、例子1、邮箱2、用逗号分隔的数字集合1,23、允许一位小数4、20yy-mm-dd日期格式5、手机号6、匹配html、xml标签一、介绍 正则表达式&#xff08;Regular Expression&#xff09;&am…...

Properties和IO流集合的方法

方法名说明void load(InputStream inStream)从输入字节流读取属性列表&#xff08;键和元素&#xff09;void load(Reader reader)从输入字符流读取属性列表&#xff08;键和元素对&#xff09;void store(OutputStream out,String comments)将此属性列表&#xff08;键和元素对…...

python 生成器、迭代器、动态新增属性及方法

目录 一、生成器 1、生成器定义 2、生成器存在的意义 3、创建生成器方式一&#xff08;生成器表达式&#xff09; 4. 创建生成器方式二&#xff08;生成器函数&#xff09; 1. 生成器函数 2. 生成器函数的工作原理 5. 总结 1. 什么是生成器 2. 生成器特点 二、迭代器…...

Java处理JSON

Java处理json有很多种方法&#xff0c;在这里总结一下。 1 Jackson Spring MVC 默认采用Jackson解析Json&#xff0c;出于最小依赖的考虑&#xff0c;也许Json解析第一选择就应该是Jackson。 1.1 引入的包 Jackson核心模块由三部分组成&#xff1a;jackson-core、jackson-a…...

58-Map和Set练习-LeetCode692前k个高频单词

题目 给定一个单词列表 words 和一个整数 k &#xff0c;返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率&#xff0c; 按字典顺序 排序。 示例 1&#xff1a; 输入: words ["i", "love", …...

线程生命周期及五种状态

文章目录一、线程生命周期及五种状态1、New(初始化状态)2、Runnable(就绪状态)3、Running(运行状态)4、Blocked(阻塞状态)5、Terminated&#xff08;终止状态&#xff09;二、线程基本方法1、线程等待&#xff08;wait&#xff09;2、线程睡眠&#xff08;sleep&#xff09;3、…...

OBCP第八章 OB运维、监控与异常处理-灾难恢复

灾难恢复是指当数据库中的数据在被有意或无意破坏后复原数据库所需要执行的活动 回收站&#xff1a;回收站在原理上说就是一个数据字典表&#xff0c;放置用户删除的数据库对象信息。用户删除的东西被放入回收站后&#xff0c;其实仍然占据着物理空间&#xff0c;除非您手动进…...

亚马逊云科技Serverless Data:数字经济下的创新动能

Serverless时代已经到来&#xff01;企业的技术架构&#xff0c;总是伴随着不断增长的数据与日趋复杂的业务持续演进。如何通过构建更易用的技术架构来聚焦在业务本身&#xff0c;而不必在底层基础设施的管理上投入过多的精力&#xff0c;是数据驱动型企业需要思考的重要议题。…...

【Ruby学习笔记】15.Ruby 异常

Ruby 异常 异常和执行总是被联系在一起。如果您打开一个不存在的文件&#xff0c;且没有恰当地处理这种情况&#xff0c;那么您的程序则被认为是低质量的。 如果异常发生&#xff0c;则程序停止。异常用于处理各种类型的错误&#xff0c;这些错误可能在程序执行期间发生&…...

聊聊MySQL主从延迟

文章目录 MySQL 的高可用是如何实现的呢?二、什么是主备延迟?三、主备延迟常见原因1、备库机器配置差2、备库干私活3、大事务四、主库不可用,主备切换有哪些策略?1、可靠优先2、可用优先实验一实验二3、结论MySQL 的高可用是如何实现的呢? 高可用性(high availability,缩…...

【C++从0到1】19、C++中多条件的if语句

C从0到1全系列教程 1、多条件的if语句 语法&#xff1a; if (表达式一) { // 表达式一为真时执行的语句。 } else if (表达式二) {// 表达式二为真时执行的语句。 } else if (表达式三) {// 表达式三为真时执行的语句。 } …… else if (表达式n) {// 表达式n为真时执行的语句。…...

【多微电网】计及碳排放的基于交替方向乘子法(ADMM)的多微网电能交互分布式运行策略研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

Linux(centos7)安装防火墙firewalld及开放端口相关命令

安装firewalld 防火墙命令&#xff1a; yum install firewalld 安装完成&#xff0c;查看防火墙状态为 not running&#xff0c;即未运行&#xff0c;输入命令开启&#xff1a; 添加开放端口&#xff1a; 防火墙相关命令&#xff1a; 查看防火墙状态 systemctl status firewa…...

Linux部署.Net Core Web项目

本文主要记录我在Linux(Ubuntu)上部署.net core 的操作记录&#xff0c;也便于以后部署。 如对您有所帮助&#xff0c;不胜荣幸~ 文章目录前言一、准备工作1. 版本信息2. windows端web项目二、操作步骤1. Linux 配置 .net 运行环境1.1 查看最新 .net 运行环境的下载路径1.2 安装…...