• 【C语言】控制台窗口图形界面编程(七):鼠标事件


    00. 目录

    01. INPUT_RECORD结构

    描述控制台输入缓冲区中的输入事件。可以使用ReadConsoleInputPeekConsoleInput函数从输入缓冲区读取这些记录,也可以使用WriteConsoleInput函数将这些记录写入输入缓冲区。

    类型声明:

    typedef struct _INPUT_RECORD {
      WORD  EventType;
      union {
        KEY_EVENT_RECORD          KeyEvent;
        MOUSE_EVENT_RECORD        MouseEvent;
        WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
        MENU_EVENT_RECORD         MenuEvent;
        FOCUS_EVENT_RECORD        FocusEvent;
      } Event;
    } INPUT_RECORD;
    

    EventType

    输入事件类型的句柄和存储在Event成员中的事件记录。

    该成员可以是以下值之一。

    含义
    FOCUS_EVENT 0x0010 事件成员包含一个FOCUS_EVENT_RECORD结构。这些事件在内部使用,应该被忽略。
    KEY_EVENT 0x0001 事件成员包含一个KEY_EVENT_RECORD结构有关键盘事件的信息。
    MENU_EVENT 0x0008 事件成员包含一个MENU_EVENT_RECORD结构。这些事件在内部使用,应该被忽略。
    MOUSE_EVENT 0x0002 所述事件构件包含MOUSE_EVENT_RECORD结构用约鼠标移动或按键按压事件的信息。
    WINDOW_BUFFER_SIZE_EVENT 0x0004 事件成员包含一个WINDOW_BUFFER_SIZE_RECORD结构有关控制台屏幕缓冲区的新大小信息。

    事件
    事件信息。此成员的格式取决于EventType成员指定的事件类型。

    02. MOUSE_EVENT_RECORD结构

    描述控制台INPUT_RECORD结构中的鼠标输入事件。

    类型声明:

    typedef struct _MOUSE_EVENT_RECORD {
      COORD dwMousePosition;
      DWORD dwButtonState;
      DWORD dwControlKeyState;
      DWORD dwEventFlags;
    } MOUSE_EVENT_RECORD;
    

    成员说明

    dwMousePosition
    一个COORD结构,它根据控制台屏幕缓冲区的字符单元格坐标包含光标的位置。

    dwButtonState
    鼠标按钮的状态。最低有效位对应于最左边的鼠标按钮。下一个最低有效位对应于最右边的鼠标按钮。下一位表示从左到右的鼠标按钮。然后,这些位从左到右对应鼠标按钮。如果按下按钮,则位为1。

    为前五个鼠标按钮定义了以下常量。

    含义
    FROM_LEFT_1ST_BUTTON_PRESSED 0x0001 最左边的鼠标按钮。一般来说鼠标左键
    FROM_LEFT_2ND_BUTTON_PRESSED 0x0004 左起第二个按钮。一般来说是鼠标中键,就是滚轮键
    FROM_LEFT_3RD_BUTTON_PRESSED 0x0008 左起第三个按钮。
    FROM_LEFT_4TH_BUTTON_PRESSED 0x0010 左起第四个按钮。
    RIGHTMOST_BUTTON_PRESSED 0x0002 最右边的鼠标按钮。一般来说鼠标右键

    dwControlKeyState
    控制键的状态。该成员可以是以下一个或多个值。

    含义
    CAPSLOCK_ON 0x0080 大写锁定被打开
    ENHANCED_KEY 0x0100 扩展键被按下
    LEFT_ALT_PRESSED 0x0002 按下左ALT键。
    LEFT_CTRL_PRESSED 0x0008 按下左CTRL键。
    NUMLOCK_ON 0x0020 数字锁定被打开
    RIGHT_ALT_PRESSED 0x0001 按下右ALT键。
    RIGHT_CTRL_PRESSED 0x0004 按下右CTRL键。
    SCROLLLOCK_ON 0x0040 滚动锁定被打开
    SHIFT_PRESSED 0x0010 按下SHIFT键。

    dwEventFlags
    鼠标事件的类型。如果此值为零,则表示正在按下或释放鼠标按钮。否则,此成员是以下值之一。

    含义
    DOUBLE_CLICK 0x0002 双击的第二次单击(按下按钮)发生。第一次单击作为常规按钮事件返回。
    MOUSE_HWHEELED 0x0008 水平鼠标滚轮被移动了。如果dwButtonState成员的高位字包含正值,则轮子向右旋转。否则,车轮向左旋转。
    MOUSE_MOVED 0x0001 发生了鼠标位置的变化。
    MOUSE_WHEELED 0x0004 垂直鼠标滚轮被移动。如果dwButtonState成员的高位字包含正值,则轮向前旋转,远离用户。否则,车轮向后旋转,朝向用户。

    03. ReadConsoleInput函数

    从控制台输入缓冲区读取数据并将其从缓冲区中删除。

    函数声明:

    BOOL WINAPI ReadConsoleInput(
      _In_  HANDLE        hConsoleInput,
      _Out_ PINPUT_RECORD lpBuffer,
      _In_  DWORD         nLength,
      _Out_ LPDWORD       lpNumberOfEventsRead
    );
    功能:
    	从控制台输入缓冲区读取数据并将其从缓冲区中删除。
    参数:
    	hConsoleInput 控制台输入缓冲区的句柄。句柄必须具有GENERIC_READ访问权限。
    	lpBuffer 指向接收输入缓冲区数据的INPUT_RECORD结构数组的指针。
    	nLength 数组元素中lpBuffer参数 指向的数组大小。
    	lpNumberOfEventsRead 指向接收读取的输入记录数的变量的指针。
    	
    返回值:
    	如果函数成功,则返回值为非零值。
    	如果函数失败,则返回值为零。要获取扩展错误信息,请调用GetLastError。
    

    官方参考网址:https://docs.microsoft.com/en-us/windows/console/readconsoleinput

    04. 示例程序

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    #include <Windows.h>
    #include <conio.h>
    
    
    int main(void)
    {
    	//定义句柄变量
    	HANDLE hOut = NULL;
    	HANDLE hIn = NULL;
    
    	//定义输入事件结构体
    	INPUT_RECORD mouseRecord;
    
    	//用于存储读取记录
    	DWORD res;
    
    	//用于存储鼠标当前位置
    	COORD pos;
    
    
    	//获取标准输出句柄
    	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    
    	//获取标准输入句柄
    	hIn = GetStdHandle(STD_INPUT_HANDLE);
    	
    	while (1)
    	{
    		//读取输入事件
    		ReadConsoleInput(hIn, &mouseRecord, 1, &res);
    
    		//获取鼠标当前位置
    		pos = mouseRecord.Event.MouseEvent.dwMousePosition;
    
    		//如果当前事件是鼠标事件
    		if (mouseRecord.EventType == MOUSE_EVENT)
    		{
    			//单击鼠标左键
    			if (mouseRecord.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
    			{
    				printf("鼠标左键单击 x: %d y: %d
    ", pos.X, pos.Y);
    			}
    
    			//单击鼠标右键
    			if (mouseRecord.Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
    			{
    				printf("鼠标右键单击 x: %d y: %d
    ", pos.X, pos.Y);
    			}
    
    			//如果是双击就退出循环
    			if (mouseRecord.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
    			{
    				break;
    			}
    
    		}
    	}
    
    	//关闭句柄
    	CloseHandle(hOut);
    	CloseHandle(hIn);
    
    	//system("pause");
    	getchar();
    	return 0;
    }
    
    宝剑锋从磨砺出,梅花香自苦寒来。
  • 相关阅读:
    如何提高Java并行程序性能??
    《实战Java虚拟机》,最简单的JVM入门书,京东活动,满200就减100了,该出手了
    看JVM就推荐这本书
    【Java】实战Java虚拟机之五“开启JIT编译”
    实战Java虚拟机之四:提升性能,禁用System.gc() ?
    实战Java虚拟机之三“G1的新生代GC”
    实战Java虚拟机之二“虚拟机的工作模式”
    实战Java虚拟机之一“堆溢出处理”
    实战java虚拟机的学习计划图(看懂java虚拟机)
    aspose.cells 复制单元格
  • 原文地址:https://www.cnblogs.com/szitcast/p/10924270.html
Copyright © 2020-2023  润新知