C语言-00如何学习C语言与图形库的使用

C语言与图形库实战:从基础到五子棋
本文详细介绍了C语言编程中从代码编辑、编译过程到图像库的使用,包括颜色处理、坐标系统、设备操作,以及实际应用如批量贴图、鼠标交互和五子棋游戏的实现。通过实例展示编程技巧和图形库的运用。

目录

一、写代码的过程

二、完整的c代码分析

三、图像库

(一)图形库基本概念

1、颜色

2、坐标

3、设备

(二)批量贴图

(三)鼠标消息

(四)小游戏—五子棋


一、写代码的过程

  • 编辑器:程序员写代码的过程(记事本、vc6.0、vim)(让程序员看懂)

  • 编译器:查看代码的语法错误,生成汇编语言。

  • 汇编器:将生成好汇编语言 生成 二进制语言(目标文件)

  • 连接器:将生成好 二进制语言+用到的库+启动代码 ==>可执行文件

二、完整的c代码分析

  • 主函数参数记得写---int main(int argc,char *argv[])

  • 再输入输出前需要有适当的描述语句,方便客户理解输入的是什么,输出的是什么

  • 浮点型变量初始化赋值(0.0f)

  • 编写程序时要按段落来写,适当的隔开不同功能的函数语句

#include<stdio.h>
// 定义一个宏 建议大写 和普通变量区分开
#define PI 3.14

int main(int argc,char *argv[])
{
    float r=0.0f; // 定义一个r变量 系统给r开辟4字节空间
    float area = 0.0f; // 定义一个面积变量

    // 获得半径 从键盘获得scanf
    printf("请输入圆的半径r:");
    scanf("%f", &r); // 带阻塞

    // 算法:计算面积area = 3.14 * r * r
    area = PI*r*r;

    // 将面积输出%.2f中的.2表示小数部分保留两位
    printf("area = %.2f\n",area);
    return 0;
}

三、图像库

(一)图形库基本概念

1、颜色

  • 预定义颜色常量

  • 16进制颜色表示

  • RGB宏合成颜色

  • 色彩模型转换的RGB颜色

2、坐标

  • 物理坐标:X轴向右为正,Y轴向下为正,单位是像素

  • 逻辑坐标:方向同物理坐标,单位是点,逻辑点=像素点

3、设备

  • 默认的图形绘画窗口

  • IMAGE对象

  • 函数功能参考EasyX_Hel软件

#define _CRT_SECURE_NO_WARNINGS // 关闭安全检查
#include<stdio.h> // 输入输出头文件
#include<stdlib.h> // system("pause")头文件
#include"graphics.h" // 图形库头文件
int main()
{
	initgraph(666, 666); // 打开一个画图窗口,长宽
	 // initgraph(666, 666, SHOWCONSOLE);画图的时候一般不用SHOWCONSOLE保留原控制台窗口,界面有两个窗口

	// 划直线 画直线前要设置图像颜色、线形
	setlinecolor(GREEN); // 设置划线颜色
	setlinestyle(0, 5); // 设置划线样式为实线,划线宽度为5像素
	// 0是实线 1是虚线,具体线形看图形库
	line(100, 100, 300, 300); // 两个端点坐标
	
	 画填充矩形
	setlinecolor(GREEN); // 设置划线颜色
	setlinestyle(0, 3); // 设置划线样式为实线,划线宽度为3像素
	setfillcolor(BLUE); // 设置填充颜色
	setfillstyle(2, 1); // 设置填充图案
	fillrectangle(400, 400, 600, 600); // 画填充矩形,左上角、右下角端点坐标
	fillcircle(400, 100, 50); // 画填充圆,圆心坐标与半径
	system("pause");
	closegraph(); // 关闭画图窗口
	return 0;
}

(二)批量贴图

  • 图片存放在.c文件的文档里

  • 图片文件名报错,项目-属性-配置属性-常规-字符集-使用多字节字符集

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include"graphics.h" // 图形库头文件
int main()
{
	initgraph(666, 666); // 打开一个画图窗口,长宽666X666
	// 贴图
	IMAGE img; // 图片对象img:用于保存图片
	loadimage(&img, "1.jpg", 200, 300);  // 加载图片:给定图片对象、图片路径和图片大小
	putimage(50, 50, &img); // 在给定位置绘制图片
	// 输出文本
	settextcolor(RED); // 设置字体颜色
	settextstyle(16, 0, ("宋体")); // 设置当前字体为高16像素的“宋体”,宽度为 0,则比例自适应
	outtextxy(500, 300, "宝宝"); // 头字母坐标值500,300
	system("pause");
	closegraph(); // 关闭画图窗口
	return 0;
}

(三)鼠标消息

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include"graphics.h" // 图形库头文件
int main()
{
	initgraph(666, 666); // 打开画图窗口
	IMAGE img; // 定义图片对象
	loadimage(&img, "1.jpg", 200, 300); // 加载图片
	// 鼠标消息
	MOUSEMSG msg; // 定义鼠标消息变量
	while (1) // 用while语句重复获取鼠标消息,重复贴图
	{
		msg = GetMouseMsg(); // 使用鼠标消息变量获取鼠标消息
		if (msg.uMsg == WM_LBUTTONUP) // 鼠标左键弹起就贴图
		{
			cleardevice(); // 用当前背景颜色清空绘图窗口
			putimage(msg.x, msg.y, &img); // 根据鼠标坐标绘制图片
		}
	}
	system("pause");
	closegraph(); // 关闭画图窗口
	return 0;
}
  • 当前鼠标消息:鼠标消息变量名.uMsg;

  • 当前鼠标消息可以用于条件判断 

鼠标消息变量名.uMsg==WM_LBUTTONDOWN // 如果鼠标左键按下  
鼠标消息变量名.uMsg==WM_RBUTTONDOWN // 如果鼠标右键按下

(四)小游戏—五子棋

 #define _CRT_SECURE_NO_WARNINGS
 #include <stdio.h>
 #include <stdlib.h>
 #include "graphics.h"
 void game() // 五子棋
 {
     initgraph(600, 600); // 打开图形库窗口
     // 画棋盘
     fillrectangle(20, 20, 580, 580); // 画填充矩形
     setlinecolor(BLACK); // 设置画线样式为黑色
     setlinestyle(0, 2); // 设置画线宽度为2像素,画线样式为实线
     for (int i = 50; i <= 550; i += 50) // 画棋盘的线
     {
         line(50, i, 550, i); // 画横线
         line(i, 50, i, 550); // 画竖线
     }
     // 鼠标消息
     MOUSEMSG msg; // 定义鼠标消息变量
     int i = 0;
     while (1) // 使用while循环重复获取鼠标消息,重复贴图
     {
         // 实现黑白棋子
         if (i % 2 == 0) 
         {
             setfillcolor(BLACK); // 设置填充颜色为黑色
         }
         else
         {
             setfillcolor(WHITE); // 设置填充颜色为白色
         }
         // 放置棋子
         msg = GetMouseMsg(); // 使用鼠标消息变量获取鼠标消息
         if (msg.uMsg == WM_LBUTTONUP) // 如果鼠标左键弹起就贴图
         {
             // 四舍五入加强版:49舍50进
             int x = (msg.x + 25) / 50 * 50; // 整50的个数
             int y = (msg.y + 25) / 50 * 50; 
             fillcircle(x, y, 25); // 画圆
             i++; // 黑白棋子交替 
         }
     }
     system("pause");
     closegraph(); // 关闭图形库窗口
 }
 // 主函数
 int main()
 {
     game();
     system("pause");
     return 0;
 }

<think>我们使用EasyX库中的GetMouseMsg()函数来等待并获取鼠标消息。peekmessage不同,GetMouseMsg()会阻塞直到有鼠标消息到来。但为了在循环中同时检测其他事件(如键盘退出),我们通常使用MouseHit()来检查是否有鼠标消息,然后使用GetMouseMsg()获取。 步骤: 1. 初始化图形窗口(使用窗口模式,以便控制台可见) 2. 使用一个循环,在循环中检查是否有鼠标消息(使用MouseHit()) 3. 如果有鼠标消息,则使用GetMouseMsg()获取消息 4. 判断消息类型,如果是左键按下(WM_LBUTTONDOWN),则在控制台输出坐标 5. 同时,我们也要检测键盘事件以便退出循环(例如按ESC键) 注意:GetMouseMsg()获取的是MOUSEMSG结构(注意:在EasyX中,ExMessage是扩展消息结构,而MOUSEMSG是旧的鼠标消息结构,但为了兼容性,我们这里使用MOUSEMSG,因为GetMouseMsg()返回的是MOUSEMSG类型)。不过,在EasyX的新版本中,推荐使用ExMessage和peekmessage,但既然用户要求使用GetMouseMsg(),我们就按此方法。 但是,请注意:EasyX文档中提到,GetMouseMsg()用于获取鼠标消息,并且会等待一个鼠标消息。而MouseHit()用于检查当前是否有鼠标消息。因此,我们可以这样写: 代码示例: ```cpp #include <graphics.h> // 注意:easyx.h已经包含在graphics.h中,或者直接包含easyx.h #include <conio.h> #include <iostream> int main() { initgraph(640, 480, 0); // 创建窗口,模式0(窗口模式)确保控制台可见 std::cout << "程序启动,点击窗口内任意位置,将在控制台输出坐标(按ESC键退出)" << std::endl; // 消息循环 while (true) { // 检查键盘事件(按ESC退出) if (_kbhit()) { int key = _getch(); if (key == 27) // ESC break; } // 检查鼠标事件 if (MouseHit()) // 如果有鼠标消息 { MOUSEMSG msg = GetMouseMsg(); // 获取鼠标消息 switch (msg.uMsg) { case WM_LBUTTONDOWN: // 在控制台输出坐标 std::cout << "左键点击坐标: (" << msg.x << ", " << msg.y << ")" << std::endl; break; } } // 避免CPU占用过高 Sleep(10); } closegraph(); // 关闭图形窗口 return 0; } ``` 注意: 1. 我们使用MouseHit()来检查是否有鼠标消息,如果有,则调用GetMouseMsg()获取。 2. 在获取鼠标消息后,我们判断uMsg成员(注意:在MOUSEMSG结构中,消息类型存储在uMsg中)是否为WM_LBUTTONDOWN(左键按下)。 3. 同时,我们使用_kbhit()和_getch()来检测ESC键按下,以便退出循环。 但是,请注意:在EasyX的文档中,MOUSEMSG结构定义如下: struct MOUSEMSG { UINT uMsg; // 消息值,如WM_MOUSEMOVE, WM_LBUTTONDOWN等 bool mkCtrl; // Ctrl键是否按下 bool mkShift; // Shift键是否按下 bool mkLButton; // 左键是否按下 bool mkMButton; // 中键是否按下 bool mkRButton; // 右键是否按下 int x; // x坐标 int y; // y坐标 int wheel; // 鼠标滚轮滚动值(仅当消息为WM_MOUSEWHEEL时有效) }; 因此,我们使用msg.uMsg来判断消息类型。 另外,如果希望同时处理其他鼠标事件(如右键、移动等),可以在switch语句中添加相应的case。 关于控制台可见性:使用initgraph(640,480,0)创建窗口模式,这样控制台窗口会保留。如果控制台没有出现,请确保在项目设置中链接器子系统设置为控制台(/SUBSYSTEM:CONSOLE)。 如果使用的是Visual Studio,可以在项目属性中设置: 链接器 -> 系统 -> 子系统 -> 控制台 这样,程序启动时会同时出现控制台窗口和图形窗口。 最后,我们添加了Sleep(10)来降低CPU占用率,如果没有这个延迟,循环会运行得非常快,占用大量CPU资源。 如果用户希望在没有鼠标事件时进行其他图形绘制,可以在循环中添加绘制代码。 现在,我们根据用户要求,使用GetMouseMsg()函数实现了鼠标左键点击在控制台输出坐标的功能。</think>### 使用 EasyX 的 GetMouseMsg() 实现鼠标左键点击输出 以下是使用 `GetMouseMsg()` 函数检测鼠标左键点击并在控制台输出信息的完整实现方法: #### 核心代码实现 ```cpp #include <graphics.h> // 包含 EasyX 头文件 #include <conio.h> // 键盘输入支持 #include <iostream> // 控制台输出支持 int main() { // 初始化图形窗口(必须使用窗口模式保留控制台) initgraph(640, 480, 0); // 参数3=0: 窗口模式 // 设置控制台输出提示 std::cout << "点击窗口查看坐标(按ESC退出)" << std::endl; while (true) { // 1. 检测键盘退出(ESC键) if (_kbhit() && _getch() == 27) break; // 2. 检测鼠标事件 if (MouseHit()) { // 检查是否有鼠标事件 MOUSEMSG msg = GetMouseMsg(); // 获取鼠标消息 // 3. 处理左键点击 if (msg.uMsg == WM_LBUTTONDOWN) { // 在控制台输出坐标 std::cout << "左键点击坐标: (" << msg.x << ", " << msg.y << ")" << std::endl; // 可选:在图形窗口绘制标记 setfillcolor(RED); solidcircle(msg.x, msg.y, 5); } } // 降低CPU占用率 Sleep(10); } closegraph(); // 关闭图形窗口 return 0; } ``` #### 关键点解析 1. **消息获取流程**: ```cpp if (MouseHit()) { // 检查是否有鼠标事件 MOUSEMSG msg = GetMouseMsg(); // 获取消息 if (msg.uMsg == WM_LBUTTONDOWN) { // 判断左键点击 // 处理代码 } } ``` [^1] 2. **MOUSEMSG 结构体**: - `uMsg`:消息类型(`WM_LBUTTONDOWN=0x0201`) - `x/y`:点击坐标 - `mkCtrl/mkShift`:控制/Shift键状态 3. **控制台保留技巧**: ```cpp initgraph(640, 480, 0); // 关键参数:0=窗口模式 ``` 使用全屏模式(参数3=1)会隐藏控制台[^2] #### 常见问题解决 1. **控制台不显示**: - 项目属性 → 链接器 → 系统 → 子系统改为`控制台(/SUBSYSTEM:CONSOLE)` - 确保使用`initgraph(,,0)`窗口模式 2. **点击无响应**: ```cpp // 添加调试输出 std::cout << "收到鼠标消息: 0x" << std::hex << msg.uMsg << std::endl; ``` 验证是否收到`0x201`(WM_LBUTTONDOWN) 3. **EasyX安装问题**: - 下载对应编译器版本(VC++6.0/VS2019等)[^2] - 安装程序自动配置头文件和库路径[^3] #### 增强功能示例 同时处理键盘和鼠标事件: ```cpp if (msg.uMsg == WM_MOUSEMOVE) { // 鼠标移动处理 std::cout << "鼠标移动: (" << msg.x << "," << msg.y << ")" << std::endl; } else if (msg.uMsg == WM_RBUTTONDOWN) { // 右键点击处理 std::cout << "右键点击!" << std::endl; } ``` > **最佳实践**:在VS中调试时,使用`OutputDebugString`函数将信息输出到"输出"窗口(View → Output),避免切换窗口[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盾山狂热粉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值