CC++绘制函数图像

CC++绘制函数图像,第1张

如果你说的是VC++的话:

你需要定义两个CPoint类型的变量m_prePoint用来存放前一个点的坐标,m_curPoint用来存放当前点的坐标。

x=-1;

m_prePoint = new CPoint(x, f(x));

然后使用pDC-> MoveTo(m_prePoint) pDC-> LineTo(m_curPoint),然后每循环一步,取得下一个点的坐标,把下一个点的坐标赋给m_curPoint,把上一步的哪个当前点坐标赋给m_prePoint,然后再使用MoveTo和LineTo画线,依次类推,就可以画出曲线了

因为实际屏幕上坐标点总是为正,而且为整数,所以在计算点位坐标的时候,你需要适当放大下,这样画出来的曲线光滑一些。

用c++的mfc绘制柱状图的方法如下:

1:取GroupBox的区域,并保存四个值  左,上,右,下

//获取屏幕坐标

((CWnd)GetDlgItem(IDC_STATIC_CHART))->GetWindowRect(rect);

//计算x轴y轴基本单位

int dx = (rectright-rectleft)/50;

int dy = (rectbottom-recttop)/80;

//转换成对话框坐标

ScreenToClient(rect);

//保存4个值

int L = rectleft,R = rectright,T = recttop,B = rectbottom;

GroupBox的区域我忘记标出来了,就在上面图中柱状图那一块

2:获取DC,这一步没什么好说的

CPaintDC dc(this);

3:画X轴,Y轴

//X

dcMoveTo(L+dx2,B-dy3);

dcLineTo(L+dx49,B-dy3);

//最后的那个箭头

dcMoveTo(L+dx49,B-dy3);

dcLineTo(L+dx48,B-dy2);

dcMoveTo(L+dx49,B-dy3);

dcLineTo(L+dx48,B-dy4);

Y轴同理,但是考虑到dx,dy的值不一样,当画Y轴的箭头时,需要交换dx和dy的位置

//纵坐标线 dcMoveTo(L+dx2,B-dy3); 

dcLineTo(L+dx2,B-dy77); 

dcMoveTo(L+dx2,B-dy77); 

//交换了dx,dy的位置

dcLineTo(L+dx2-dy,B-dy77+dx); 

dcMoveTo(L+dx2,B-dy77); 

//交换了dx,dy的位置

dcLineTo(L+dx2+dy,B-dy77+dx);

绘制完结果如图:

4:画柱状图,这里主要根据前面计算dx,dy时,划分的数量来计算每个柱的宽度,以及柱间的间隔

//第一个柱状体的左下坐标

int x = L+dx3;

int y = B-dy3;

for(int i=0;i

CRect rc;

rcleft=x+idx9;

rcright=rcleft+dx7;

rcbottom=y;

rctop=rcbottom-dyanswer[index][i+1];

//这里把柱状图的信息输出,这里输出的是一个数字,因为要转换成字符串,比较麻烦

//处理了一下,肯定有简洁的处理方式,但是我也懒得去想了,我很懒的

dcSetBkMode(TRANSPARENT);//设置透明背景,要不然输出文字之后会有一块白,难看

char num[10];

sprintf(num,"%d",answer[index][i+1]);

CString strnum(num);

dcTextOutW((rcleft+rcright)/2-dx,rcbottom-dy(answer[index][i+1]+3),strnum);

//画刷是我之前就定义好的,直接拿来用

dcFillRect(&rc,brushs+i);

}

5:添加控件消息响应函数

维护一个全局变量index来保存当前题号,创建重绘函数updateInfo

void CEnglishReportDlg::updateInfo(){

int count = choose_c[index];

int i;

//选项存在,赋值,L是宏命令与TEXT()相同功能

for(i=0;i

m_strLable[i] = choose[index][i];

}

//无此选项,置空

for(;i<5;i++)

m_strLable[i] = L"";

m_strTopic = topics[index];

//获取GroupBox区域,并转换成对话框坐标

CRect rect;

((CWnd)GetDlgItem(IDC_STATIC_CHART))->GetWindowRect(rect);

ScreenToClient(rect);

//重绘此区域

InvalidateRect(rect);

//将控件变量更新到前台

UpdateData(FALSE);

}

函数1:响应ListBox的SelChange事件

void CEnglishReportDlg::OnLbnSelchangeListTopic()

{

// TODO: 在此添加控件通知处理程序代码

index = m_listtopicGetCurSel();

updateInfo();

}

函数2:上一页按钮的Click事件

void CEnglishReportDlg::OnBnClickedButtonPre()

{

// TODO: 在此添加控件通知处理程序代码

if(index>0)

index--;

updateInfo();

m_listtopicSetCurSel(index);

}

函数3:下一页按钮的Clicl事件

void CEnglishReportDlg::OnBnClickedButtonNext()

{

// TODO: 在此添加控件通知处理程序代码

if(index<19)

index++;

updateInfo();

m_listtopicSetCurSel(index);

}

至此基本的功能都已经实现了,还差最后一步:

6:初始化对话框

for(int i=0;i<20;i++){

m_listtopicAddString(topics[i]);

}

//index初始化为0,直接刷新

updateInfo();

m_listtopicSetCurSel(index);

运行结果如下:

我画了半个正弦函数,其余的你可以照着画,欢迎讨论,

#include "stdioh"

#include "conioh"

#include "mathh"

#include "graphicsh"

void main()

{

int driver,mode,i;

driver=DETECT;

mode=0;

initgraph(&driver,&mode,"");

setcolor(15);

for(i=0;i<360;i++)

line(i,200sin(i314/360),i+1,200sin((i+1)314/360));

getch();

restorecrtmode();

}

单点绘制,在OnDraw(OnPaint)中,使用pDC->SetPixel函数设置坐标点颜色即可。缺点:当像素点过多,会比较缓慢

内存DC绘制(绘制方法同上),再将保存的内存DC内容BitBlt到设备dc(参考“双缓冲”相关信息)。缺点:第一次绘制较慢,但之后刷新很快

通过算法,自己对位图内存指针进行COLORREF指针赋值 *** 作,当绘制好内存指针后,将位图通过BitBlt等函数显示到DC。缺点:速度最快但 *** 作和算法最复杂。

void CMFCApplication2Dlg::OnPaint()

{

if (IsIconic())

{

//

else

{

CPaintDC dc(this); // device context for painting

CPoint Pt[7];

Pt[0] = CPoint(20+m_incr, 50);

Pt[1] = CPoint(180+m_incr, 50);

Pt[2] = CPoint(180+m_incr, 20);

Pt[3] = CPoint(230+m_incr, 70);

Pt[4] = CPoint(180+m_incr, 120);

Pt[5] = CPoint(180+m_incr, 90);

Pt[6] = CPoint(20+m_incr, 90);

dcPolygon( Pt, 7);

CDialogEx::OnPaint();

}

}void CMFCApplication2Dlg::OnBnClickedButton1()//Move Arrow button

{

if ( m_nTimer )

{

KillTimer( m_nTimer );

m_nTimer = NULL;

}

else

m_nTimer = SetTimer(1, 20, 0);

}

void CMFCApplication2Dlg::OnTimer(UINT_PTR nIDEvent)

{

m_incr += 3;

Invalidate();

CDialogEx::OnTimer(nIDEvent);

}

在MFC中并没有现成的类或函数实现这一功能。不过有类似的函数,比如:

CDC::PolylineTo

BOOL PolylineTo( const POINT lpPoints, int nCount );

CDC::Polyline

BOOL Polyline( LPPOINT lpPoints, int nCount );

你可以利用这两个函数,自己编写一个类或函数,实现你想要的画平滑曲线的功能。示例:

折线的作用示例——绘制一条正弦曲线

#include <mathh>

#define PI 31415926

#define SEGMENT 500

void CMainWindow::OnPaint()

{

CPaintDC dc(this);

CRect rect;

GetClientRect(&rect);

int nWidth = rectWidth();

int nHeight = rectHeight();

CPoint aPoint[SEGMENT];

for (int i=0; i<SEGMENT; i++)

{

aPoint[i]x = (i nWidth) / SEGMENT;

aPoint[i]y = (int) ((nHeight / 2) (1 - (sin((2PIi)/SEGMENT))));

}

dcPolyline(aPoint,SEGMENT);

}

你的思路是对的,要在CDiagView中调用 COpenglView的绘图函数才行在CDiagView中通过COpenglView的指针调用Invalidata()就OK了m_pCOpenglView->Invalidata() 补充回答:我所说的 m_pCOpenglView 是你自己声明一个CDiagView的成员变量m_pCOpenglView。要让这个指针指向你的COpenglView对象。拿到这个指针的方式比较多,取决于你的程序是基于SDI、MDI还是自己写的框架。如果不知道怎末拿这个指针,给我留言,告诉我这两个视图的父窗体类是什么。我给你附上解决方案这个问题的核心思想是:在CDiagView中输入参数后,要通知到COpenglView重绘界面

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/12459916.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-23
下一篇2023-05-23

发表评论

登录后才能评论

评论列表(0条)

    保存