| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3777 人关注过本帖, 6 人收藏
标题:Windows 控制台下的绘图方法
只看楼主 加入收藏
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
结帖率:100%
收藏(6)
已结贴  问题点数:20 回复次数:30 
Windows 控制台下的绘图方法
程序代码:
#include <Windows.h>
#include <ctime>
#include <cmath>
#include <conio.h>

// 全局常数及变量
const double PI(2 * asin(1.0));                     // 圆周率
const WCHAR K_ENTER(0x000D);                        // Enter键码
const RECT Border = { 10, 10, 620, 350 };           // 图框位置及尺寸
const POINT Origin = { 20, 170 };                   // 坐标原点位置
const double Scale(80.0);                           // 缩放比例
const double Increase(0.0001);                      // 自变量微元增量dx

HDC hDC(GetDC(GetConsoleWindow()));                 // 绘图设备

// 函数原型
void DrawBorder(void);                              // 绘制图框
void DrawAxes(void);                                // 绘制坐标轴
void DrawGraph(void);                               // 绘制图像
void Wait(void);                                    // 等待按键

// 程序入口
void wmain(void)
{
    DrawBorder();
    DrawAxes();
    DrawGraph();
    Wait();
    ReleaseDC(NULL, hDC);
}

void DrawBorder(void)
{
    HPEN hPen(CreatePen(PS_SOLID, 1, RGB(0,255,0)));
    HBRUSH hBrush(CreateSolidBrush(RGB(0,0,0)));
    SelectObject(hDC, hPen);
    SelectObject(hDC, hBrush);
    Rectangle(hDC, Border.left, Border.top, Border.right, Border.bottom);
    DeleteObject(hPen);
    DeleteObject(hBrush);
}

void DrawAxes(void)
{
    HPEN hPen(CreatePen(PS_SOLID, 1, RGB(0, 255, 255)));
    SelectObject(hDC, hPen);
    MoveToEx(hDC, Origin.x, Origin.y, NULL);
    LineTo(hDC, Border.right - 10, Origin.y);
    DeleteObject(hPen);
}

void DrawGraph(void)
{
    HPEN hPen(CreatePen(PS_SOLID, 1, RGB(255, 255, 0)));
    SelectObject(hDC, hPen);
    MoveToEx(hDC, Origin.x, Origin.y, NULL);
    for (double x = 0.0; x <= 2 * PI; x += Increase)
    {
        LineTo(hDC, Origin.x + static_cast<int>(x * Scale), Origin.y - static_cast<int>(sin(x) * Scale));
    }
    DeleteObject(hPen);
}

void Wait(void)
{
    const WCHAR msg[] = L"按<Enter>键结束程序";
    RECT rect = { Border.left, Border.bottom + 20, Border.right, Border.bottom + 50 };
    SetTextColor(hDC, RGB(0,0,255));
    SetBkColor(hDC, TRANSPARENT);
    DrawTextW(hDC, msg, _countof(msg), &rect, DT_CENTER);

    HANDLE hConsole(GetStdHandle(STD_OUTPUT_HANDLE));   // 控制台句柄
    CONSOLE_CURSOR_INFO CursorInfo;
    GetConsoleCursorInfo(hConsole, &CursorInfo);
    CursorInfo.bVisible = false;
    SetConsoleCursorInfo(hConsole, &CursorInfo);
    while (_getwch() != K_ENTER)
    {
        ;
    }
    CursorInfo.bVisible = true;
    SetConsoleCursorInfo(hConsole, &CursorInfo);
}


图片附件: 游客没有浏览图片的权限,请 登录注册


[ 本帖最后由 TonyDeng 于 2012-3-27 15:19 编辑 ]
搜索更多相关主题的帖子: Windows 
2012-03-27 02:14
C_596322153
Rank: 6Rank: 6
来 自:徽州
等 级:侠之大者
帖 子:182
专家分:466
注 册:2012-1-10
收藏
得分:3 
顶顶  楼主最好能搞个不能编译器的
2012-03-27 09:53
星辰雁
Rank: 4
等 级:业余侠客
威 望:1
帖 子:93
专家分:275
注 册:2011-9-10
收藏
得分:3 
顶一个

不要认为CPU运算速度快就 把所有的问题都推给它去做,程序员应该将代码优化再优化,我们自己能做的决不要让CPU做 ,因为CPU是为用户服务的,不是为我们程序员服务的!
2012-03-27 10:26
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
下面是加上顺带求定积分的代码:

程序代码:
#include <Windows.h>
#include <cstdio>
#include <ctime>
#include <cmath>
#include <conio.h>

// 全局常数及变量
const double PI(2 * asin(1.0));                     // 圆周率
const WCHAR K_ENTER(0x000D);                        // Enter键码
const RECT Border = { 10, 10, 620, 350 };           // 图框位置及尺寸
const POINT Origin = { 20, 170 };                   // 坐标原点位置
const double Scale(80.0);                           // 缩放比例
const double Increase(0.0001);                      // 自变量微元增量dx

HDC hDC(GetDC(GetConsoleWindow()));                 // 绘图设备

// 函数原型
void DrawBorder(void);                              // 绘制图框
void DrawAxes(void);                                // 绘制坐标轴
void DrawGraph(void);                               // 绘制图像
void Wait(void);                                    // 等待按键

// 程序入口
void wmain(void)
{
    DrawBorder();
    DrawAxes();
    DrawGraph();
    Wait();
    ReleaseDC(NULL, hDC);
}

void DrawBorder(void)
{
    HPEN hPen(CreatePen(PS_SOLID, 1, RGB(0,255,0)));
    HBRUSH hBrush(CreateSolidBrush(RGB(0,0,0)));
    SelectObject(hDC, hPen);
    SelectObject(hDC, hBrush);
    Rectangle(hDC, Border.left, Border.top, Border.right, Border.bottom);
    DeleteObject(hPen);
    DeleteObject(hBrush);
}

void DrawAxes(void)
{
    HPEN hPen(CreatePen(PS_SOLID, 1, RGB(0, 255, 255)));
    SelectObject(hDC, hPen);
    MoveToEx(hDC, Origin.x, Origin.y, NULL);
    LineTo(hDC, Border.right - 10, Origin.y);
    DeleteObject(hPen);
}

void DrawGraph(void)
{
    HPEN hPen(CreatePen(PS_SOLID, 1, RGB(255, 255, 0)));
    SelectObject(hDC, hPen);
    MoveToEx(hDC, Origin.x, Origin.y, NULL);
    double integral(0.0);
    for (double x = 0.0; x <= 2 * PI; x += Increase)
    {
        double fun_value(sin(x));
        LineTo(hDC, Origin.x + static_cast<int>(x * Scale), Origin.y - static_cast<int>(fun_value * Scale));
        if (x <= PI)
        {
            integral += fun_value * Increase;      // 求定积分
        }
    }
    DeleteObject(hPen);

    SetTextColor(hDC, RGB(255,0,255));
    SetBkColor(hDC, TRANSPARENT);
    WCHAR buffer[1024];
    swprintf_s(buffer, 20, L"半周期的面积=%.4f", integral);
    TextOutW(hDC, Border.left + 10, Border.bottom - 30, buffer, wcslen(buffer));
}

void Wait(void)
{
    const WCHAR msg[] = L"按<Enter>键结束程序";
    RECT rect = { Border.left, Border.bottom + 20, Border.right, Border.bottom + 50 };
    SetTextColor(hDC, RGB(255,255,255));
    SetBkColor(hDC, TRANSPARENT);
    DrawTextW(hDC, msg, _countof(msg), &rect, DT_CENTER);

    HANDLE hConsole(GetStdHandle(STD_OUTPUT_HANDLE));   // 控制台句柄
    CONSOLE_CURSOR_INFO CursorInfo;
    GetConsoleCursorInfo(hConsole, &CursorInfo);
    CursorInfo.bVisible = false;
    SetConsoleCursorInfo(hConsole, &CursorInfo);
    while (_getwch() != K_ENTER)
    {
        ;
    }
    CursorInfo.bVisible = true;
    SetConsoleCursorInfo(hConsole, &CursorInfo);
}


图片附件: 游客没有浏览图片的权限,请 登录注册


[ 本帖最后由 TonyDeng 于 2012-3-28 02:05 编辑 ]

授人以渔,不授人以鱼。
2012-03-27 15:58
小鱼儿c
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:852
专家分:1317
注 册:2011-4-1
收藏
得分:3 
Tony 大哥可以话 可以把控制台的知识好好解析一下 方便我们学习

用心做一件事情就这么简单
2012-03-27 16:24
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
回复 5楼 小鱼儿c
你们平时学的就是控制台编程呀

授人以渔,不授人以鱼。
2012-03-27 17:02
moonnight
Rank: 5Rank: 5
等 级:职业侠客
帖 子:158
专家分:380
注 册:2012-3-17
收藏
得分:3 
发现现在还看不懂。。。。
2012-03-27 18:52
C_596322153
Rank: 6Rank: 6
来 自:徽州
等 级:侠之大者
帖 子:182
专家分:466
注 册:2012-1-10
收藏
得分:0 
版主 句柄有啥用啊 前几天看api一点不懂  关于windows下图像编程   什么 句柄 消息 一类的 有什么好书推荐啊
2012-03-27 21:06
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
以下是引用C_596322153在2012-3-27 21:06:48的发言:

版主 句柄有啥用啊 前几天看api一点不懂  关于windows下图像编程   什么 句柄 消息 一类的 有什么好书推荐啊

句柄简单来说就是一个ID数字,用来识别不同“对象”的。面向对象的编程,定义了很多“类”,类相当于蓝图,而根据类制造出来的实体就叫“对象”,每份蓝图出不同的实体对象,同一个类可以制造多个对象,为了识别同一个类下对应的不同对象、以及不同类不同的对象,就需要给每个对象都分配一个ID,作为这个实体的唯一标识。好比我们的身份证号码,同一行政区划的号码都会反映在身份证号码中,但身份证号码有附加有各种各样的唯一识别码,用以区分。句柄现在定为整数,但编程时最好不要假想它是整数,就如不要把指针值当作整数一样,因为在概念上它们毕竟不是整数,而是独特的逻辑概念(正如不应该把逻辑真假视为整数0/1一样)。

在Windows的架构中,每种类都是一个实现库中有基本运行模版的,所有基于同一个类生成的对象,其行为代码全部从这个实现库中抽取,因此,尽管我们对同一个类定义了很多不同的对象实体(比如开了若干个窗口),但这些对象的基本行为其实是用同一份代码实现的,不同的动作,其实是我们设定了不同的参数,用参数来驱动代码,不同的参数表现出不同的行为,但究其实,真实的执行代码就只有一份!因此,你开不同的窗体,传入每个窗体的Title字符串,类代码就会把这些具体的字符串呈现在窗体的标题栏,看起来就是不同的对象在工作,但其实只有一份代码在工作,这份代码要应付你开设的所有的窗体的动作。这就是面向对象的编程,你写的代码,要能适应不同的动作需求,但代码就只有一份,被数据驱动。Windows使用句柄,是要把每个对象实体的数据用查表法归属到代码中,相同句柄下的数据,执行起来就是对同一个对象操作的。

“消息”,就是那些用来驱动执行代码的参数。Windows系统下应用程序的执行,其实是Windows根据消息调用程序代码,是Windows在执行程序,不是程序自己在执行,程序能做的,是发出消息通知Windows想做什么,然后Windows在同意的情况视具体情形在适当时候满足你的需求。消息的基本原理,其实就是在一个死循环中不断查询是否有某种约定的消息数据出现了,如果有,就执行对应的功能,如果没有,就查询下一个,就这样不断死循环,把所有消息都处理完。比如在我这里的程序中,其实那个main()主程序就有一个叫Wait()的死循环,它在开始执行完“初始化”把图像呈现出来后,就处于等待状态,除非接收到消息(按下Enter键),否则它什么也不做(如果这里只有一个消息,还不能让你明白,那么看看这里https://bbs.bccn.net/thread-364017-1-1.html 6楼的main()函数代码,就由四个消息驱动,计时、发出变换图像的信号、是否有按键及按了什么键)。Windows程序的主程序,其实就是这么一个死循环,在循环内部不断地搜寻有什么消息出现,你可以在这个程序中添加各种各样不同的消息(不要死守着Windows的消息,Windows是根据这样的理念制造的程序产品,不是它的专利,消息是程序员自创的,不是只有Windows定义的那些东西才叫消息)。

事实上,“消息”的机制并不新鲜,也不是从C++才开始有的,早在C时代就有了。printf()和scanf()函数的编制,其实就是典型的消息驱动机制,通过约定的格式字符串,指示函数内部处理数据的动作,这就是这两个函数之所以必须要附带格式字符串而且要严格的原因,不过这两个函数约定的消息是死的,它能处理内置数据类型,但无法用同样的机制处理自定义数据类型,所以后来才用C++的多态性来实现这种需求,从而废弃了这两个函数。不过,思想真的并不新鲜,C++是在C基础上发展起来的,当然有很多共同基础,很多人没意识到这一点,才总说C和C++如何这般的不同,以至于走到极端要纯粹的C或C++,那是偏狭了。

现在,你可以看看我这个程序的写法。我把各种可能变动的参数都集中写在全局变量那里,如果你需要修改,就在那里集中修改,而基本上不用动后面的代码,这样,你写程序时,集中精力写好一份代码就可以了,以后的变动,交给数据去做,只要你代码写好了,就不用反复地写类似的代码。编程所要学的,其实就是养成这么一种理念,不要总喜欢做同类的事情,写链表,就一辈子在弄各种各样的链表,学会写链表算法,不表示懂编程了。

算法再精妙,终究也只需写一次,以后不会再用到了(所以我们应该把精力放在那些将来会经常遇到的算法上,比如基本的排序、筛选、查寻、比较、读写文件等等,而不要总弄那些没多少机会遇到的算法,常用的算法,算法书上都有伪代码,用什么语言都能实现,需要时花个几天时间把伪代码实现了就可以,不用在大学花数年时间来练指法,那些是将来可以现学的,但思想和思维是必须花大力气巩固培养的),这就是C++专家建议我们采用STL标准库的目的,他们集全世界的精英力量构建好了那些算法库和数据结构,你自己写的代码无论如何都不及他们的优秀,何必花那些力气去弄精通它们,了解基本精神和大致的原理即可,无需自己去实现那些代码,除非你要向那些精英挑战、兴趣所在,那当然是你的自由和权力了。

[ 本帖最后由 TonyDeng 于 2012-3-27 22:40 编辑 ]

授人以渔,不授人以鱼。
2012-03-27 21:34
k_tide
Rank: 2
等 级:论坛游民
帖 子:22
专家分:15
注 册:2012-1-2
收藏
得分:3 
新人  长见识来了

2012-03-27 23:12
快速回复:Windows 控制台下的绘图方法
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.030476 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved