win32-鼠标消息、键盘消息、计时器消息、菜单资源



承接前文:

  1. win32窗口编程
  2. windows 开发基础
  3. win32-注册窗口类、创建窗口
  4. win32-显示窗口、消息循环、消息队列


本文目录

  • 键盘消息
    • 键盘消息的分类
    • WM_CHAR 字符消息
  • 鼠标消息
    • 鼠标消息附带信息
  • 定时器消息 WM_TIMER
    • 创建销毁定时器
  • 菜单资源
    • 资源相关
    • 菜单资源使用
      • 命令消息的处理 WM_COMMAND
    • 上下文菜单



键盘消息

键盘消息的分类

  • WM_KEYDOWN :按键被按下时产生。
  • WM_KEYUP :按键被放开时产生。
  • WM_SYSKEYDOWN :系统按键被按下时产生,比如:ALT、F10等。
  • WM_SYSKEYUP :系统按键放开时产生。
    • 附带信息:
      • WPARAM :按键的 Virtual Key Code(虚拟键码),虚拟键码是操作系统定义的一组唯一标识不同键的整数值,用来表示每个键盘键的抽象标识。虚拟键码与具体的物理键盘码(如扫描码)或字符不同,它不依赖于特定的键盘布局。应用程序通过检查wParam的值可以得知是哪个键被按下了,然后可以进行相应的处理逻辑。因为虚拟键码是统一的跨越不同键盘布局的标识符,这样设计帮助开发者编写跨平台和可移植的应用程序。
      • LPARAM :按键的参数,例如按下的次数

在这里插入图片描述

  • 按下一个按键并松开,会产生一个 WM_KEYDOWN 消息和一个 WM_KEYUP 消息(成对出现)。
  • 按下一个按键不松开,会连续产生 WM_KEYDOWN 消息,知道松开时会产生 一个 WM_KEYUP 消息。
  • 无论大小写锁定键是否被打开,按下相同的字母时键码值是一样的,意味着单凭键码值无法区分大小写,所以按键消息需要翻译,以区分大小写。
  • 在Windows系统上,Alt 键和 F10 键,这俩按键是系统按键,需要用 WM_SYSKEYDOWNWM_SYSKEYUP


WM_CHAR 字符消息

  • TranslateMessage() 在转换 WM_KEYDOWN 消息时,对于可见字符可以产生 WM_CHAR 消息,不可见字符无此消息。
  • 附带信息:
    • WPARAM :输入字符的 ASCII 码值。
    • LPARAM :按键的相关参数。
//TranslateMessage伪代码
TranlateMessage(){
	if (nMsg.message != WM_KEYDOWN)
		return ...//如果不是 WM_KEYDOWN 消息直接return
	//根据 nMsg.wParam (键码值) 可以获知哪个按键被按下
	if (不可见字符的按键)
		return ...;
	//查看CapsLock (大小写锁定键) 是否被打开
	if (打开)
		PostMessage(nMsg.hWnd, WM_CHAR, 按键的大写ASCII码值, ... );
	else
		PostMessage(nMsg.hWnd, WM_CHAR, 按键的小写ASCII码值, ... );	
}

在这里插入图片描述

  • CapsLock 键没有打开时,按下键盘 A 键 产生的 WM_CHAR 消息的 wParam 值为 小写字母 a 的ASCII码值 97。按下 CapsLock 键(键码值20)后,再按下键盘 A 键,产生的 WM_CHAR 消息的 wParam 值为 大写字母 A 的ASCII码值 65



鼠标消息

鼠标基本消息

  • WM_LBUTTONDOWN :鼠标左键按下。
  • WM_LBUTTONUP :鼠标左键抬起。
  • WM_RBUTTONDOWN :鼠标右键按下。
  • WM_RBUTTONUP :鼠标右键抬起。
  • WM_MOUSEMOVE :鼠标移动消息。

双击消息

  • WM_LBUTTONDBLCLK :左键双击。
  • WM_RBUTTONDBLCLK :鼠标右键双击。

使用双击消息需要在注册窗口类时增加 CS_DBLCLKS 风格,否则无论鼠标表点击得多么快都是多次单击。

滚轮消息

  • WM_MOUSEWHEEL

鼠标消息附带信息

  • wParam :其他按键的状态,例如Ctrl / Shift 等。

  • lParam :鼠标的位置,窗口客户区坐标系。

    • LOWORD x坐标位置
    • HIWORD y坐标位置
  • 一般情况下鼠标按下 / 抬起 成对出现。在鼠标移动过程中,会根据移动速度产生一系列的 WM_MOUSEMOVE 消息。

case WM_LBUTTONDOWN:
	OnLButtonDown(hWnd, wParam, lParam);
	break;
case WM_LBUTTONUP:
	OnLButtonUp(hWnd, wParam, lParam);
	break;

void OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam) {
	char text[128] = { 0 };
	sprintf_s(text, "WM_LBUTTONDOWN:其他按键状态:%d,x = %d, y = %d\n", wParam, LOWORD(lParam), HIWORD(lParam));
	WriteConsole(g_dos_output, text, strlen(text), NULL, NULL);
}

void OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam) {
	char text[128] = { 0 };
	sprintf_s(text, "WM_LBUTTONUP:其他按键状态:%d,x = %d, y = %d\n", wParam, LOWORD(lParam), HIWORD(lParam));
	WriteConsole(g_dos_output, text, strlen(text), NULL, NULL);
}

在这里插入图片描述

鼠标左键按下时,wParam 值为1,按住 Ctrl 同时按下鼠标左键 wParam 值为 1+8 = 9,松开时 wParam 值为 9 - 1 = 8。

双击
在这里插入图片描述

在这里插入图片描述

滚轮的附带信息

  • wParam
    • LOWORD :其他键的状态。
    • HIWORD :滚轮的偏移量,通过正负表示滚轮方向。
  • lParam,坐标原点为屏幕原点下的鼠标当前位置。
    • LOWORD :x 坐标。
    • HIWORD :y坐标。
case WM_MOUSEWHEEL:
	OnWheel(hWnd, wParam, lParam);
	break;

void OnWheel(HWND hWnd, WPARAM wParam, LPARAM lParam) {
	char text[128] = { 0 };
	short nDelta = HIWORD(wParam);
	sprintf_s(text, "WM_MOUSEWHEEL, 其他键状态:%d,偏移量 %d, x:%d,y:%d\n", LOWORD(wParam), nDelta, LOWORD(lParam), HIWORD(lParam));
	WriteConsole(g_dos_output, text, strlen(text), NULL, NULL);
}

在这里插入图片描述
滚轮的距离以 120 为单位,往前滚动是正数,往后滚动是负数。




定时器消息 WM_TIMER

  • 产生时间:
    在程序中创建定时器,当到达指定时间时,定时器会向程序发送一个 WM_TIMER 消息。定时器的经度是毫秒级,但是准确度很低。例如设置的时间是1000ms后,但是可能会在非1000m后到达。
  • 附带信息:
    wParam :定时器ID。
    lParam :定时器处理函数指针。

定时器消息其实由 GetMessage() 发送,在前面的文章中提到过,因为 GetMessage() 函数做的事情特别多,特别忙碌,所以定时器消息不是很准,但误差也不会太大,通常也就几毫秒。

WM_TIMER消息的应用范围如下:

定时器功能:WM_TIMER消息通常与SetTimer函数一起使用,用于创建定时器。当定时器到达设定的时间间隔时,系统会发送WM_TIMER消息给窗口,从而触发相应的处理逻辑。开发者可以在接收到WM_TIMER消息时进行特定的操作,比如更新UI界面、执行一段代码等。

动画效果:WM_TIMER消息可以用于实现一些简单的动画效果,例如平滑的滚动、闪烁等。通过定时器不断发送WM_TIMER消息,可以控制界面元素的变化,从而营造出动态的视觉效果。

定时任务:WM_TIMER消息也可以用于执行定时任务,比如定时检查网络连接状态、定时备份数据等。通过设置定时器并处理WM_TIMER消息,可以实现定时执行任务的功能。

总的来说,WM_TIMER消息主要用于定时器相关的功能,可以帮助开发者管理定时事件、实现动画效果以及执行定时任务等操作。

创建销毁定时器

  • 创建定时器:
    UINT_PTR SetTime(
    	HWND hWnd, //定时器窗口句柄
    	UINT_PTR nIDEvent,   //定时器ID
    	UINT uElapse,     //时间间隔
    	TIMERPROC lpTimerFunc     //定时器处理函数指针(一般不使用,为NULL)
    };    //创建成功,返回非0
    
  • 关闭定时器:
    BOOL KillTimer(
    	HWND hWnd,    //定时器窗口句柄
    	UINT_PTR uIDEvent    //定时器ID
    };
    

实验:在窗口创建之后显示之前创建两个定时器,一个每隔1秒触发,一个每个两秒触发,每次触发打印定时器的ID。

case WM_CREATE:     //WM_CREATE消息产生时间即窗口创建成功显示之前
	SetTimer(hWnd, 1, 1000, NULL);
	SetTimer(hWnd, 2, 2000, NULL);      
	//定时器创建成功后开始计时,设定的时间之后就会触发WM_TIMER消息
	break;
	
case WM_TIMER:    //处理定时器触发
	OnTimer(hWnd, wParam);      //调用OnTimer()函数处理
	break;

//OnTimer()函数内容如下:
void OnTimer(HWND hWnd, WPARAM wParam) {       //这里传进来的wParam是定时器的ID
	/*switch(wParam){
	case 1:
	break;
	case 2:
	break;
	}*/    //一般对定时器的ID wParam使用switch语句,对不同的定时器ID做不同的处理
	char txt[128] = { 0 };
	sprintf_s(txt, "WM_TIMER: 定时器ID=%d\n", wParam);
	WriteConsole(g_dos_output, txt, strlen(txt), NULL, NULL);
}

运行结果:每产生一个定时器2就会产生两个定时器1。

在这里插入图片描述




菜单资源

菜单分类:

  • 窗口的顶层菜单(窗口顶层一长条,新建、编辑等)
  • 弹出式菜单(右键点击弹出,顶层菜单被点击弹出)
  • 系统菜单(点击窗口图标弹出)

HMENU 类型表示菜单句柄,ID表示菜单项。

资源相关

  • 资源脚本文件 :*.rc 文件,描绘资源文件的脚本代码。
  • 编译器:RC.exe,用来编译资源脚本文件。

.c / cpp 文件经过 CL.exe 编译器编译成 .obj 文件,.rc 文件经过 RC.exe 编译成 .res 文件,.obj 文件和 .res 文件经过链接器 LINK.exe 链接成最终可执行文件 .exe

菜单资源使用

  • 添加菜单资源

  • 加载菜单资源

    • 注册窗口类时设置菜单
    • 创建窗口传参设置菜单
    • 在主窗口 WM_CREATE 消息中利用 SetMenu 函数设置菜单

    加载菜单资源:

    HMENU LoadMenu(
    	HINSTANCE hInstance,    //handle to module
    	LPCTSTR lpMenuName      //menu name or resource identifier
    );
    

添加资源文件:

在这里插入图片描述


添加资源:

在这里插入图片描述


在这里插入图片描述


编辑菜单:

在这里插入图片描述


顶层的 文件 编辑 视图 项目 帮助 这些并没有ID,因为点击它们就做一件事情——弹出下拉框,而下拉框里面的每一项都有一个 ID ,以区分鼠标点击的哪一个内容。


在这里插入图片描述

菜单资源ID:IDR_MENU1


Resource.rc 文件内容:

在这里插入图片描述


在这里插入图片描述


添加菜单到窗口中

方法一:在注册窗口类时添加菜单。

#include "resource.h"    //添加资源头文件

//注册窗口类时添加菜单ID:
wc.lpszMenuName = (char*)IDR_MENU1;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);    //顺便添加一个默认鼠标资源,这样可以使鼠标在一些情况下正常显示

在这里插入图片描述


方法二:在创建窗口时添加菜单(倒数第三个参数,注意是菜单的句柄不是菜单ID)

//创建窗口时添加菜单:
HMENU hMenu = LoadMenu(hIns, (char*)IDR_MENU1);
HWND hWnd = CreateWindowEx(
	0, pClassName, "My Window",
	WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_OVERLAPPEDWINDOW,
	200, 200, 640, 480,        //窗口位置(200,200),大小长宽(640,480)。
	nullptr, hMenu, hIns, nullptr
);

使用 LoadMenu() 函数来加载菜单的句柄。项目编译成功后,菜单资源也就在可运行文件.exe 中,在运行该可执行文件时,可执行文件又被加载到内存,通过 hInstance 可以找到当前进程所在的内存,再用菜单资源的ID可以找到菜单所在内存的句柄。


方法三:在主窗口 WM_CREATE 消息中利用 SetMenu 函数设置菜单。

case WM_CREATE:
	{
		HMENU hMenu = LoadMenu(nullptr, (char*)IDR_MENU1);
		SetMenu(hWnd, hMenu);
	}
	break;

在这里插入图片描述


命令消息的处理 WM_COMMAND

附带信息:
LOWORD(wParam) 菜单项的ID。

//WndProc 的 switch语句添加以下代码:
case WM_COMMAND:
	OnCommand(hWnd, wParam);
break;

//OnCommand() 函数代码:
void OnCommand(HWND hWnd, WPARAM wParam) {
	switch (LOWORD(wParam)) {
		case ID_40001:
			MessageBox(hWnd, "新建被点击", "Information", MB_OK);
		    break;
		case ID_40002:
			MessageBox(hWnd, "打开被点击", "Information", MB_OK);
			break;
		case ID_40003:
			MessageBox(hWnd, "退出被点击", "Information", MB_OK);
			break;
	}
}

运行结果:

在这里插入图片描述
在这里插入图片描述

上下文菜单

  • 显示上下文菜单:
    BOOL TrackPopupMenu(
    	HMENU hMenu,    //菜单句柄
    	UINT uFlags,    //显示方式
    	int x,          //水平位置,屏幕坐标系下
    	int y,          //垂直位置,屏幕坐标系下
    	int nReserved,  //保留参数,必须为0
    	HWND hWnd,      //处理菜单消息的窗口句柄
    	CONST RECT *prcRect   //NULL 忽略
    }; //TrackPopupMenu 是阻塞函数
    

使用:

case WM_RBUTTONUP:         //右键弹起时显示上下文菜单
	OnRButtonUp(hWnd, lParam);
	break;

void OnRButtonUp(HWND hWnd, LPARAM lParam) {
	HMENU hMenu = LoadMenu(nullptr, (char*)IDR_MENU1);      //加载菜单资源,拿到菜单句柄
	HMENU hPopup = GetSubMenu(hMenu, 0);       //获取顶层菜单的子菜单,0就是文件下的子菜单
	POINT clientPoint = { LOWORD(lParam), HIWORD(lParam) };      //创建客户区的坐标
	
	ClientToScreen(hWnd, &clientPoint);      //将客户区的坐标位置转化为屏幕坐标系
	
	TrackPopupMenu(hPopup, 
	TPM_CENTERALIGN | TPM_VCENTERALIGN,       //菜单中心显示,水平居中、垂直居中
	clientPoint.x, clientPoint.y, 
	0, hWnd, NULL);
}

运行:

在这里插入图片描述

或者使用专门的显示上下文菜单的消息:

  • WM_CONTEXTMENU :鼠标右键抬起来 WM_RBUTTONUP 消息之后产生。
    • wParam :右键点击的窗口句柄。
    • lParam :LOWORD,x 坐标,屏幕坐标系;HIWORD,y 坐标,屏幕坐标系。
#include <Windows.h>
#include <stdio.h>

#include "resource.h"

HANDLE g_dos_output = 0;

void OnCommand(HWND hWnd, WPARAM wParam) {
	switch (LOWORD(wParam)) {
		case ID_40001:
			MessageBox(hWnd, "新建被点击", "Information", MB_OK);
		    break;
		case ID_40002:
			MessageBox(hWnd, "打开被点击", "Information", MB_OK);
			break;
		case ID_40003:
			MessageBox(hWnd, "退出被点击", "Information", MB_OK);
			break;
	}
}

void OnRButtonUp(HWND hWnd, LPARAM lParam) {
	HMENU hMenu = LoadMenu(nullptr, (char*)IDR_MENU1);
	HMENU hPopup = GetSubMenu(hMenu, 0);
	TrackPopupMenu(hPopup, 
	TPM_LEFTALIGN | TPM_TOPALIGN,       //左上角显示
	LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
	switch (msgID)
	{
		case WM_CLOSE:
			PostQuitMessage(0);
			break;
		case WM_COMMAND:
			OnCommand(hWnd, wParam);
			break;
		case WM_CONTEXTMENU:
			OnRButtonUp((HWND)wParam, lParam);
			break;
	}
	return DefWindowProc(hWnd, msgID, wParam, lParam);
}

int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow)
{
	AllocConsole();
	g_dos_output = GetStdHandle(STD_OUTPUT_HANDLE);   //获得标准输出句柄

	const auto pClassName = "Main";

	WNDCLASSEX wc = { 0 };
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hIcon = nullptr;
	wc.hInstance = hIns;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = pClassName;
	wc.lpszMenuName = (char*)IDR_MENU1;
	wc.hIconSm = nullptr;
	wc.style = CS_HREDRAW | CS_VREDRAW |CS_DBLCLKS;
	wc.cbSize = sizeof(wc);

	RegisterClassEx(&wc);

	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, nullptr
	);

	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);

	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()的参数值
	}
}



后续更新… …

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

远动通讯屏具体干啥作用

远动通讯屏具体干啥作用 远动通讯屏主要用于电力系统中的各类发电厂、变电站、光伏电站、开闭所、配电房等&#xff0c;具有实时传输数据和远程控制功能。它的主要作用包括&#xff1a; 数据采集&#xff1a;远动通讯屏能够采集各种模拟量、开关量和数字量等信息&#xff0c…

python查找内容在文件中的第几行(利用了滑动窗口)

def find_multiline_content(file_path, multiline_content):with open(file_path, r) as file:# 文件内容file_lines file.readlines()# 待检测内容multiline_lines multiline_content.strip().split(\n)# 待检测内容总行数num_multiline_lines len(multiline_lines)matchi…

【CALayer-CALayer的transform属性 Objective-C语言】

一、接下来,我们来说的是这个,transform的属性 1.layer的transform属性, 把最后一份代码command + C、command + V、一份儿,改个名字, Name:04-CALayer的transform属性, 我们把这个代码稍微修改一下, 我们先添加了一个layer,到控制器的view上, 然后呢,这两句话不…

Tina-Linux -- 5. 网络通信(有线网络,无线网络,SSH链接)

有线网络 bash 指令 ifconfig eth0 192.168.2.222 netmask 255.255.255.0 up route add default gw 192.168.2.1开机自启 修改网络设置文件 /etc/init.d/S40network #!/bin/sh # # Start the network.... ## Debian ifupdown needs the /run/network lock directory mkdir …

Vue3实现简单的瀑布流效果,可抽离成组件直接使用

先来看下效果图&#xff1a; 瀑布流中的内容可进行自定义&#xff0c;这里的示例图是通过不同背景颜色的展示进行区分&#xff0c;每个瀑布流中添加了自定义图片和文字描述。 实现方式&#xff1a; 1.建立子组件&#xff08;可单独抽离&#xff09;写出瀑布流的样式 文件名为…

C++-逻辑语句

if语句 基本格式&#xff1a; 只有判断结果为true&#xff0c;才会执行后续{}内的代码 if (要执行的判断&#xff0c;结果需是bool型) {判断结果true&#xff0c;才会执行的代码; }if (条件判断) { 如果判断结果为true&#xff0c;会执行的代码; }else{如果判断结果为false…

【工具】AFL+Unicorn|二进制程序模糊测试工具 AFL 和 Unicorn 的前世今生、安装以及 Python 使用实例

文章目录 【工具】AFLUnicorn&#xff5c;二进制程序模糊测试基础工具&#xff08;AFLUnicorn&#xff09;写在最前1. 系统环境2. 软件版本3. 背景知识3.1 AFL vs AFLplusplus3.2 QEMU vs Unicorn3.3 Unicorn vs UnicornAFL 4. 工具安装4.1 Ubuntu184.2 Ubuntu 20~224.3 收尾 5…

分布式事务——9种解决方案的原理与分类

目录 一、概要1. 分布式事务的概念2. 分布式事务解决方案分类 二、常见的分布式事务解决方案1. 基础的 2PC&#xff08;二阶段提交&#xff09;1.1 核心思想1.2 简介1.3 主要特点1.3.1 优点1.3.2 缺点 2. 基础的 3PC&#xff08;三阶段提交&#xff09;2.1 核心思想2.2 简介2.3…

【系统架构师】-案例篇(十五)SOA、微服务与数据库

1、可复用构件应具备哪些属性 可用性&#xff1a;构件必须易于理解和使用。 质量&#xff1a;构件及其变形必须能正确工作。 适应性&#xff1a;构件应该易于通过参数化等方式在不同语境中进行配置。 可移植性&#xff1a;构件应能在不同的硬件运行平台和软件环境中工作。 可变…

# 全面解剖 消息中间件 RocketMQ-(2)

全面解剖 消息中间件 RocketMQ-&#xff08;2&#xff09; 一、RocketMQ – RocketMQ 各角色介绍 1、RocketMQ 各角色介绍 Producer : 消息的发送者; 举例:发信者。Consumer : 消息接收者; 举例:收信者。Broker : 暂存和传输消息; 举例:邮局。NameServer : 管理 Broker; 举例…

全网最全爬取-b站爬取弹幕+评论之js逆向与xml降本增效

&#x1f31f; ❤️ 作者&#xff1a;yueji0j1anke 首发于公号&#xff1a;剑客古月的安全屋 字数&#xff1a;801 阅读时间: 10min 声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及…

K-means聚类模型

目录 1.定义 2.K-means聚类模型的优点 3.K-means聚类模型的缺点 4.K-means聚类模型的应用场景 5.对K-means聚类模型未来的展望 6.小结 1.定义 什么是 K-means 聚类模型&#xff1f;K-means 聚类模型是一种无监督学习算法&#xff0c;用于将数据划分为不同的组或簇&#…

概念+bug

模型 迭代模型和增量模型 增量模型是将一个大的需求变成小的功能&#xff0c;然后将每个功能逐个开发几乎完整再上线。 迭代模型会上线一个基础版本&#xff0c;但是基础版本所有的功能都有但是非常简陋&#xff0c;之后再迭代优化上线。 一般都是两个一起用&#xff0c;不…

微服务Day7学习

文章目录 数据聚合聚合分类 自动补全DSL实现Bucket聚合DSL实现Metrics聚合RestAPI实现聚合多条件聚合对接前端接口拼音分词器自定义分词器自动补全查询实现酒店搜索框自动补全 数据同步数据同步思路分析利用mq实现mysql与elasticsearch数据同步 集群介绍搭建ES集群 数据聚合 聚…

T01.如何寻找隐藏目录usr?

当我们打开Mac自带的Shell或者另外安装的zsh等工具时&#xff0c;我们所在的默认目录为用户目录usr。 Mac的这个bin目录&#xff0c;是一个已经包含在环境变量里的目录&#xff0c;程序放在里面或者链接到里面就可以在终端里直接执行。Mac的usr/bin目录是不允许增删文件的&…

tomcat三级指导

版本 ./catalina.sh linux version.bat win 1.确认是否使用了tomcat管理后台 我们先找到配置文件&#xff1a;tomcat主目录下/conf/server.xml 可以查看到连接端口&#xff0c;默认为8080 然后查看manager-gui管理页面配置文件&#xff0c;是否设置了用户登录 配置文件…

Obsidian Git 多端同步

2023年6月&#xff0c;某云笔记限制了免费用户最多同时登录 2 台设备&#xff0c;想要增加设备数量需要付费开通会员。之后我一直想找一款合适的笔记本软件&#xff0c;年底尝试了Obsidian&#xff0c;断断续续摸索了好几天终于成功了。将那时的笔记拿来分享一下。 相关地址&am…

Java轻松转换Markdown文件到Word和PDF文档

Markdown 凭借其简洁易用的特性&#xff0c;成为创建和编辑纯文本文档的常用选择。但某些时候我们需要更加精致的展示效果&#xff0c;例如在专业分享文档或打印成离线使用的纸质版时&#xff0c;就需要将Markdown文件以其他固定的文档格式呈现。通过将 Markdown 转换为 Word 和…

错误代码126:加载x3daudio1_7.dll失败的几种修复方法分享

在使用电脑玩游戏或者工作的过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中最常见的就是“错误代码[126]:加载x3daudio1_7.dll失败&#xff0c;该文件缺失或损坏!”&#xff0c;那么&#xff0c;什么是x3daudio17.dll文件&#xff1f;它为什么会丢失&#xff1…

剪画小程序:3个方法:告诉你如何将普通的照片转换成动漫二次元风格!

Hello&#xff01;亲爱的小伙伴们&#xff01; 你是否还在纠结于自己的自拍太普通&#xff0c;每次分享到社交账号上都觉得平平无奇&#xff0c;引不起波澜&#xff1f; 假如&#xff0c;你和朋友们一起出去玩&#xff0c;大家都开心地拍着自拍。你看着自己的照片&#xff0c…