
如果你说的是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重绘界面
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)