SimpleCG程序交互操作

news2024/11/29 18:23:49

 前言

        之前所有示例程序都是属于展示型的,只是作为展示板输出使用,不涉及键盘和鼠标的输入交互,下面我们开始接触具有交互功能的程序。

        没有交互功能的程序可以满足一定需求,不过大部分的程序是不能脱离交互功能的。程序依据使用者的操作进行相应反应并进行相关输出从而达到互动,将让程序的魅力提高一个层次。一个典型的应用就是游戏,所以学习完本篇内容后将可以进行一些游戏程序的编写。当前SimpleCG库主要支持的输入操作是鼠标和键盘,下面看看具体如何操作吧。

一、消息处理基础

        想要在SimpleCG中处理Windows的交互操作,就是需要定义一个消息处理函数,消息处理函数名字可以随便定义,但形式是固定的。例如鼠标消息固定形式如下所示:

LRESULT OnLButtonDown( HWND hWnd, WPARAM wParam, int nX, int nY )
{
}

名字OnLButtonDown是可以自己定义的,一般也是按消息功能命名。定义完消息函数后,依据想要接收的消息进行注册,所谓注册也就是调用一个设置函数。例如想要接收左键点击消息,按如下方式设置:

SetMouseProcess( enumINMSG_LBUTTONDOWN, OnLButtonDown);

这里要注意的是,设置函数一定要在初始化阶段设置,一般是程序开始处设置。

二、鼠标操作

支持的鼠标消息如下所示:

    enumINMSG_MOUSEMOVE            //鼠标移动
	, enumINMSG_LBUTTONDOWN        //左键按下
	, enumINMSG_LBUTTONUP          //左键抬起
	, enumINMSG_LBUTTONDBLCLK      //左键双击
	, enumINMSG_RBUTTONDOWN        //右键按下
	, enumINMSG_RBUTTONUP          //右键抬起
	, enumINMSG_RBUTTONDBLCLK      //右键双击
	, enumINMSG_MBUTTONDOWN        //中键按下
	, enumINMSG_MBUTTONUP          //中键抬起
	, enumINMSG_MBUTTONDBLCLK      //中键双击
	, enumINMSG_MOUSEWHEEL         //滚轮消息

当需要处理相应消息时,只要按上面说到的两个步骤定义相应函数即可。下面用一个绘图功能的程序来演示一下鼠标左键消息的处理。

#include "../import/include/CGBoard.h"
#include "math.h"
#ifdef _DEBUG
#pragma comment(lib,"../import/lib/SimpleCG_MDd.lib")
#else
#pragma comment(lib,"../import/lib/SimpleCG_MD.lib")
#endif


int g_nWidth = 500;		//画面宽度
int g_nHeight= 400;		//画面高度

int g_bIsDrawing = 0;
POINT g_ptLast;
void DrawProcess()
{
}

LRESULT OnLButtonDown( HWND hWnd, WPARAM wParam, int nX, int nY )
{
	g_ptLast.x = nX;
	g_ptLast.y = nY;
	g_bIsDrawing = 1;
	return TRUE;
}
LRESULT OnLButtonUp( HWND hWnd, WPARAM wParam, int nX, int nY )
{
	
	if(g_bIsDrawing)
	{
		line(g_ptLast.x,g_ptLast.y,nX,nY);
		g_ptLast.x = nX;
		g_ptLast.y = nY;
		g_bIsDrawing = 0;
	}
	return TRUE;
}
LRESULT OnMouseMove( HWND hWnd, WPARAM wParam, int nX, int nY )
{
	if(g_bIsDrawing)
	{
		line(g_ptLast.x,g_ptLast.y,nX,nY);
		g_ptLast.x = nX;
		g_ptLast.y = nY;
	}
	return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
	//设置消息处理函数
	SetMouseProcess( enumINMSG_LBUTTONDOWN, OnLButtonDown);
	SetMouseProcess( enumINMSG_LBUTTONUP,	OnLButtonUp);
	SetMouseProcess( enumINMSG_MOUSEMOVE,	OnMouseMove);

	//初始化
	if( !ShowingBoard(g_nWidth,g_nHeight, DrawProcess))
		return 1;
	//关闭图库
	CloseBoard();
	return 0;
}

该程序可以用鼠标在窗口点击要绘制的地方,然后移动鼠标绘制出鼠标轨迹,直至左键抬起。

另外函数

LRESULT OnLButtonDown( HWND hWnd, WPARAM wParam, int nX, int nY )
{
}

 中各参数意义如下:

hWnd是窗口句柄,暂时不需要了解

wParam附带有消息产生时的按键信息,可通过如下方法判断。

MK_CONTROL 按下了 CTRL 键。
MK_LBUTTON 按下了鼠标左键。
MK_MBUTTON 按下了鼠标中键。
MK_RBUTTON 按下了鼠标右键。
MK_SHIFT 按下了 SHIFT 键。
MK_XBUTTON1 按下了第一个 X 按钮。
MK_XBUTTON2 按下了第二个 X 按钮。

例如通过代码

if(wParam&MKCONTROL)就可以判断CTRL键是否按下。

nX和nY是鼠标在窗口中的坐标

三、键盘消息

 键盘支持的消息如下:

    enumINMSG_KEYDOWN    //按键按下
	, enumINMSG_KEYUP    //按键放开

按键消息响应函数如下

//按键消息响应函数
LRESULT OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
}

其中wParam代表当前虚拟键,各个虚拟键值可在此网站查找。

lParam是32位数含义如下:

0-15    当前消息的重复计数。 该值是由于用户按住键而自动重复击键的次数。 
16-23    扫描代码。 该值取决于 OEM。
24    指示键是扩展键,例如在增强型 101 键或 102 键键盘上显示的右侧 Alt 键和 Ctrl 键。 如果是扩展键,则值为 1;否则为 0。
25-28    保留;请勿使用。
29    上下文代码。 对于 WM_KEYDOWN 消息,该值始终为 0。
30    上一个键状态。 如果键在发送消息之前关闭,则值为 1;如果键已打开,则值为 0。
31    转换状态。 对于 WM_KEYDOWN 消息,该值始终为 0。

下面用一个可以用方向键控制移动的小球来演示按键的交互

#include "../import/include/CGBoard.h"
#include "math.h"
#ifdef _DEBUG
#pragma comment(lib,"../import/lib/SimpleCG_MDd.lib")
#else
#pragma comment(lib,"../import/lib/SimpleCG_MD.lib")
#endif


int g_nWidth = 500;		//画面宽度
int g_nHeight= 400;		//画面高度

int g_nXCircle = 100;
int g_nYCircle = 100;
void DrawProcess()
{
	setfillcolor(RGB(0xAA,0xAA,0xFF));
	fillcircle(g_nXCircle, g_nYCircle, 10 );
}

//按键消息响应函数
LRESULT OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
	int nStepX = 0;
	int nStepY = 0;
	switch( wParam )
	{
	case VK_DOWN:
		nStepY = 1;
		break;
	case VK_UP:
		nStepY = -1;
		break;
	case VK_LEFT:
		nStepX = -1;
		break;
	case VK_RIGHT:
		nStepX = 1;
		break;
	}
	_clearcircle(g_nXCircle, g_nYCircle, 12 );
	g_nXCircle += nStepX;
	g_nYCircle += nStepY;
	fillcircle(g_nXCircle, g_nYCircle, 10 );
	return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
	//设置消息处理函数
	SetKeyboardProcess( enumINMSG_KEYDOWN,	OnKeyDown );

	//初始化
	if( !ShowingBoard(g_nWidth,g_nHeight, DrawProcess))
		return 1;
	//关闭图库
	CloseBoard();
	return 0;
}

有兴趣的同学可以试着运行看看效果。

四、接管所有消息处理

        当对Windows编程有了更深入了解后,需要处理除了以上消息之外的消息时,可以设置一个所有消息的处理函数。方法如下:

首先定义消息处理函数

LRESULT OnMessage( HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam )
{
	//此处输入消息处理过程

	return 0;
}

然后使用SetInputProcess进行设置

SetInputProcess( OnMessage );

此处需要注意的是使用了SetInputProcess( OnMessage );函数后,就要自己处理所有交互消息,所以SetMouseProcess和SetKeyboardProcess都将失效。

下面我们运用自定义消息处理函数对窗口关闭操作进行拦截的演示。代码如下:

// DemoMessage.cpp : 定义控制台应用程序的入口点。
//
#include "../import/include/CGBoard.h"
#include "math.h"
#ifdef _DEBUG
#pragma comment(lib,"../import/lib/SimpleCG_MDd.lib")
#else
#pragma comment(lib,"../import/lib/SimpleCG_MD.lib")
#endif


int g_nWidth = 500;		//画面宽度
int g_nHeight= 400;		//画面高度

int g_bIsDrawing = 0;
POINT g_ptLast;
int g_nLineWidth = 1;

int g_nXCircle = 100;
int g_nYCircle = 100;
void DrawProcess()
{
	setfillcolor(RGB(0xAA,0xAA,0xFF));
	fillcircle(g_nXCircle, g_nYCircle, 10 );
}


LRESULT OnMessage( HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam )
{
	if( nMessage == WM_CLOSE )
	{
		if(MessageBox(NULL,_T("是否退出"),_T("提示"),MB_YESNO) == IDYES )
			return 0;
		return 1;
	}
	return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
	//设置消息处理函数
	SetInputProcess( OnMessage );
	//初始化
	if( !ShowingBoard(g_nWidth,g_nHeight, DrawProcess))
		return 1;
	//关闭图库
	CloseBoard();
	return 0;
}

五、结语

        通过掌握以上介绍的内容,就可以编写出大部分可交互程序。不过要完全操控窗口,还需要熟练掌握更多的消息及参数。对于游戏编写,后面会给出一个简单框架。

SimpleCG库安装 

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

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

相关文章

Error response from daemon

文章目录 遇到的问题解决方法参考 遇到的问题 当输入下面的指令时 docker pull xxxxxx解决方法 打开/etc/docker/daemon.json文件 vim /etc/docker/daemon.json写入以下内容: {"registry-mirrors":["https://docker.mirrors.ustc.edu.cn"]…

OpenCV 图像像素运算操作

加法操作详解 加减乘除 #include <opencv2/opencv.hpp>using namespace cv;int main() {Mat image imread("image.jpg");if (image.empty()) {std::cout << "无法加载图像" << std::endl;return -1;}// 加法变换Mat addResult;add(ima…

mac在vscode编码过程中输入()光标在里面的时候想移出来还得动用左右键很麻烦有什么快捷方法

下载vscode插件: 想跳出大括号的时候就可以使用tab直接跳出来就行了

Buuctf web [SUCTF 2019]EasySQL

又是一道考察sql注入的题 1、起手试探 &#xff08;主要看看输入什么内容有正确的回显&#xff09; 1 0 1 1 # 发现只有在输入1的情况下有正常的回显,输入0或其他字符都没有回显&#xff0c;所以这题就要尝试堆叠注入了。 ps&#xff1a;&#xff08;如果想尝试其他注入方法…

带你打穿三层内网-红日靶场七

文章目录 前记环境配置web1信息搜集cve-2021-3129redis未授权|ssh密钥后渗透 Win7&#xff08;PC1&#xff09;永恒之蓝 web2docker逃逸 win7&#xff08;PC2&#xff09;|DC 前记 所用工具 msfcsvenomfrp蚁剑冰蝎laravel.pyfscan 注意事项 msf的永恒之蓝每次都需要两次才能…

VM-Linux基础操作命令

命令执行的本质&#xff1a; 当输入命令&#xff08;单词&#xff09;后敲击回车的那一刻。它就会立刻到以下图片&#xff0c;变量中的文件中去找对应的可执行文件 此路径又叫环境变量 1.shell命令提示符 默认&#xff1a;[rootlocalhost ~]# root&#xff1a;现已登录的账户名…

重构优化第三方查询接口返回大数据量的分页问题

# 问题描述 用户线上查询其上网流量详单数据加载慢&#xff0c;且有时候数据没有响应全~ 1、经排除是调用第三方数据量达10w条响应会超时&#xff0c;数据没正常返回 2、现有线上缓存分页也是加载慢数据不能正常展示 3、第三方接口返回类似报文jsonj&#…

基于Yolov8的光伏电池缺陷检测,引入ICCV2023 动态蛇形卷积和独家全网首发多维协作注意模块MCA,实现涨点创新十足

1.光伏电池缺陷数据集介绍 背景&#xff1a;太阳能作为一种极具吸引力的替代电力能源&#xff0c;太阳能光伏电池&#xff08;即光伏电池&#xff09;是太阳能发电系统的基础&#xff0c;一般情况下&#xff0c;电池中的各类缺陷会直接影响到光伏电池的光电转化效率和使用寿命…

Mybatis-Genertor逆向工程

1、导入mybaties插件 <build><plugins><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.2</version><dependencies><dependency>…

Android Fragment

基本概念 Fragment是Android3.0后引入的一个新的API&#xff0c;他出现的初衷是为了适应大屏幕的平板电脑&#xff0c; 普通手机开发也会加入这个Fragment&#xff0c; 可以把他看成一个小型的Activity&#xff0c;又称Activity片段&#xff01; 如果一个很大的界面&#xff…

视频直播点播平台EasyDSS创建用户详细操作来啦!

视频推拉流EasyDSS视频直播点播平台&#xff0c;集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体&#xff0c;可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。 由于旭帆科技的EasyDSS平台支持新建用户&#xff0c;但新建时用户…

Python 图片处理笔记

import numpy as np import cv2 import os import matplotlib.pyplot as plt# 去除黑边框 def remove_the_blackborder(image):image cv2.imread(image) #读取图片img cv2.medianBlur(image, 5) #中值滤波&#xff0c;去除黑色边际中可能含有的噪声干扰#medianBlur( Inp…

懒汉式之并发安全问题

在高并发场景下的懒汉式创建对象&#xff0c;造成ID重复创建&#xff0c;代码见下图&#xff1a; 并发场景下&#xff0c;iDCreator对象并未随类的创建而创建&#xff0c;而是在需要的时候进行创建&#xff0c;导致垃圾回收器可以对其进行回收&#xff0c;从而有可能同一时间戳…

帮助企业轻松搭建帮助中心-Baklib

Baklib是一个在线知识管理平台&#xff0c;帮助企业搭建在线产品手册、帮助中心、知识库等&#xff0c;Baklib是一个工具型软件&#xff0c;帮助企业高效快速搭建相关文档内容&#xff0c;轻松进行对外分享。 Baklib起源——目前企业的知识管理现状 存储难 将文档存储在本地与…

卷积网络:实现手写数字是识别50轮准确率97.3%

卷积网络&#xff1a;实现手写数字是识别50轮准确率 1 导入必备库2 torchvision内置了常用数据集和最常见的模型3 数据批量加载4 绘制样例5 创建模型7 设置是否使用GPU8 设置损失函数和优化器9 定义训练函数10 定义测试函数11 开始训练12 绘制损失曲线并保存13 绘制准确率曲线并…

Xilinx ZYNQ 7000学习笔记五(Xilinx SDK 烧写镜像文件)

概述 前面几篇讲了ZYNQ7000的启动过程&#xff0c;包括BootRom和FSBL的代码逻辑&#xff0c;其中关于FSBL代码对启动模式为JTAG被动启动没有进行分析&#xff0c;本篇将通过将JTAG的功能和通过Xilinx SDK烧写镜像文件到flash来顺道把FSBL中的JTAG代码部分给讲解下。 1.JTAG …

springboot+jxls复杂excel模板导出

JXLS 是基于 Jakarta POI API 的 Excel 报表生成工具&#xff0c;可以生成精美的 Excel 格式报表。它采用标签的方式&#xff0c;类似 JSP 标签&#xff0c;写一个 Excel 模板&#xff0c;然后生成报表&#xff0c;非常灵活&#xff0c;简单&#xff01; Java 有一些用于创建 …

为什么不推荐使用Lombok?@Data不香吗?

目录 一、前言 二、源码跟踪 三、总结 一、前言 之前写项目遇到的一个Bug&#xff0c;下面是模拟代码。 新建一个springboot的项目&#xff0c;Person一个实体类&#xff0c;定义一个方法传一个JSON数据 Data public class Person {private String name;private String a…

el-table表格动态设置最大高度 高度根据窗口可视高度大小改变自适应

由于表格内容过多&#xff0c;如果不给高度限制&#xff0c;每页100条数据的情况下&#xff0c;去操作底部的分页或者其他功能都需要划到数据最底部操作&#xff0c;用户体验性较差。解决方法是让表格一屏展示&#xff0c;超出部分滚动展示。 1.效果及思路图&#xff1a; 思路是…

【uniapp】小程序开发,初始化项目vscode

使用uniapp开发小程序可以实现一份代码打包成多个不同平台的小程序。 这里使用uniapp官方的项目模板作为示例&#xff0c;采用vue3ts开发&#xff0c;并使用vscode作为开发工具 一、通过命令行创建项目并运行 1、通过以下命令创建模板项目 参考 官方说明 npx degit dcloudi…