博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows控制台下绘制简单图形
阅读量:5098 次
发布时间:2019-06-13

本文共 2229 字,大约阅读时间需要 7 分钟。

  最近接触到一个很有意思的问题,如何在Windows控制台下画图,翻遍了C的头文件也没找到画图的函数,好吧,那就用Windows提供的API函数吧,看来想移植是没戏了。先画一个简单的图,类似心电图那种吧,假设得到的数据是纵坐标的值,横坐标默认从0开始,每隔512uS(微秒的那个符号不会打)得到一个纵坐标值,要求将所有纵坐标值连起来,就以这个简单的程序为例吧。

  既然有了需求,实现起来就简单了,首先我们应该有一个控制台窗口的上下文(device context)句柄,然后使用和函数连线就行了。代码如下:

  

 
#include
<
windows.h
>
#include
<
stdio.h
>
#include
<
conio.h
>
#include
"
data.h
"  //声明了名为point的二维数组,以及记录数组元素个数的NUMBER常量
//
//
下列X-Y坐标平面的值取决于控制台的尺寸,需要根据实际情况进行调整
//
//
起始X坐标
#define
X_START 10
//
结束X坐标
#define
X_END 650
//
每个值的X坐标增量,相当于512uS
#define
X_INC 10
//
Y坐标
#define
Y 250
int
main()
{
HWND hwnd;
HDC hdc;
int
i;
//
获取console的设备上下文句柄
hwnd
=
GetConsoleWindow();
hdc
=
GetDC(hwnd);
//
调整一下console背景颜色,否则看不清线条
system(
"
color 3D
"
);
//
起始位置,Windows中窗口的坐标系相当于直角坐标系第一象限翻转到第四象限
MoveToEx(hdc,X_START,Y,NULL);
//
画基准坐标线
LineTo(hdc,X_END,Y);
//
开始绘图
MoveToEx(hdc,X_START,Y,NULL);
for
(i
=
0
; i
<
NUMBER; i
++
)
{
LineTo(hdc,point[i].x,point[i].y);
}
_getch();
return
0
;
}

  但是这个程序存在一个问题,就是如果控制台被其它窗口遮住后,已经绘制的线条不会重绘,也就意味着那部分线条看不见了,只能重新运行程序,这个问题怎么解决呢?我也不知道,不过可以将整个函数包含一个while循环里,如果自己是顶层窗口就重新绘制,只是这样似乎代价太大了,呵呵。

  来看一下这个程序绘制的图形吧。

  line

  既然能绘制出线条自然就可以会绘制出柱形图之类的图形,稍微修改一下就可以了,代码就不贴了,效果如下图。

  photo

  上面这些都比较好画,那么如果画圆呢?

  我想到两种方法,第一种方法是计算,首先分别计算出最大和最小的X、Y值(xmin,xmax,ymin,ymax),然后根据X^2+Y^2=R^2,在for (x = xmin; x <= xmax; x++)内部计算Y值,最后画点就是了;这个应该是比较简单的。

  第二种方法是扫描,左上角(xmin,ymin)、右上角(xmax,ymin)、左下角(xmin,ymax)和右下角(xmax,ymax)这四个点确定一个正方形,对正方形内部对每个点进行运算,也是根据X^2+Y^2=R2,只是现在根据X和Y算出R0,然后跟R对比而已,而且比第一种方法多了一个判断——是否到达行末,若到达行末则跳到下一行,若已经到了最后一行的最后一列,那就跳出循环。不过这个方法显然比较奢侈,如果半径增大n倍的话,计算量增大了n^2倍。就贴这种方法的代码吧。

  

 
void
circle(POINT
*
center,
int
radius)
{
HWND hwnd;
HDC hdc;
int
xmin
=
center
->
x
-
radius;
int
xmax
=
center
->
x
+
radius;
int
ymin
=
center
->
y
-
radius;
int
ymax
=
center
->
y
+
radius;
POINT point;
hwnd
=
GetConsoleWindow();
hdc
=
GetDC(hwnd);
point.x
=
xmin;
point.y
=
ymin;
MoveToEx(hdc,center
->
x,center
->
y
-
radius,NULL);
while
(TRUE)
{
if
(fabs(sqrt(pow2(point.x
-
center
->
x)
+
pow2(point.y
-
center
->
y))
-
radius)
<=
1
)
{
DrawPoint(hdc,
&
point);
}
//
是否到达行末
if
(point.x
==
xmax)
{
if
(point.y
==
ymax)
{
break
;
}
else
{
point.x
=
xmin;
point.y
++
;
continue
;
}
}
point.x
++
;
}
}

  绘制的圆如下图:

  circle

转载于:https://www.cnblogs.com/pianoid/archive/2011/05/27/2060001.html

你可能感兴趣的文章
Nginx+Keepalived 实现双击热备及负载均衡
查看>>
五分钟搭建WordPress博客(二)
查看>>
Vue_(组件通讯)子组件向父组件传值
查看>>
jvm参数
查看>>
Something-Summary
查看>>
Spring学习笔记
查看>>
6个有用的MySQL语句
查看>>
linux c/c++ IP字符串转换成可比较大小的数字
查看>>
我对前端MVC的理解
查看>>
sql: table,view,function, procedure created MS_Description in sql server
查看>>
[网络流24题] 最长k可重区间集问题 (费用流)
查看>>
路径依赖理论
查看>>
ActiveX多线程回调JavaScript
查看>>
剑指offer系列32-----对称二叉树的判断
查看>>
Silverlight实用窍门系列:19.Silverlight调用webservice上传多个文件【附带源码实例】...
查看>>
2016.3.31考试心得
查看>>
Python 编程快速上手 第 7章 模式匹配与正则表达式
查看>>
c#FTP应用---windows iis
查看>>
linux下调整java版本
查看>>
AutoCAD实用技巧基础篇
查看>>