MFC GDI画图 跪求大神 CBitmap *pOldBit=dcMem.SelectObject(&bmp); bmp.DeleteObject();不能这么做吧,要再次调用 dcMem.SelectObject(pOldBit);后才删除。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 适应所有,请勿使用0、500等常量既然获得了rect, 那就根据他的长、高 加上自定义比例来,就可以适应所有 你已经实现了基本功能了,现在要做两件事:1、用GetClientRect等函数动态计算坐标,根据你的需求来绘图2、在窗口的WM_SIZE事件里重绘你的的图 谢谢您的回答 不太懂 这样吧 我把我画的坐标 以及出现问题贴出来 麻烦大家帮忙看下代码:CDC dcMem; GetClientRect(&rect); CBitmap bmp; //内存中承载临时图象的位图 bmp.LoadBitmap(IDB_CURVE);dcMem.CreateCompatibleDC(pDC);dcMem.SetBkMode(TRANSPARENT); //透明模式,CBitmap *pOldBit=dcMem.SelectObject(&bmp); CPen whitedotpen(PS_DOT,1,COLOR_WHITE); //白色点画笔CPen blacksolidpen(PS_SOLID,1,COLOR_BLACK); //黑色实画笔CPen Redpen(PS_SOLID,1,COLOR_RED); //红色笔CPen* poldpen = dcMem.SelectObject(&whitedotpen); int xx=rect.right-rect.left;int yy=rect.bottom-rect.top;SetRect(&m_rect,xx/8,yy/6,10*xx/11,6*yy/7);xlen = (float)(m_rect.right - m_rect.left)/50;ylen = (float)(m_rect.bottom - m_rect.top)/10;CString str=_T("");int i,j;//画白色点状网格for (i=0;i<=50;i++) //画白色点状网格(纵线){dcMem.MoveTo(m_rect.left+xlen*i,m_rect.top); dcMem.LineTo(m_rect.left+xlen*i,m_rect.bottom); }for (j=0;j<=10;j++) //画白色点状网格(横线){dcMem.MoveTo(m_rect.left,m_rect.bottom-ylen*j);dcMem.LineTo(m_rect.right,m_rect.bottom-ylen*j);} pDC->StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&dcMem,0,0,1270,640,SRCCOPY);dcMem.SelectObject(pOldBit);dcMem.SelectObject(poldpen);bmp.DeleteObject();dcMem.DeleteDC(); //删除DC全屏时 正常 拉伸至半屏将StretchBlt换成BitBlt 即pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY); 表格正常缩放了,但是图片不缩放请教大家 如何一起缩放 没人帮忙吗?最后的75分了 帮帮小弟:SDI OnDraw里 贴背景图+自绘图形 能够满足缩放功能解决的楼 75分全送了 那是你方法不对,反正不管怎么样,线的最右边的点都是rect.Width(),最下边是rect.Height()for(int y=0;y<rect.Height();y+=10){dcMem.MoveTo(0,y);dcMem.LineTo(rect.Width(),y);}画一排行,上面的代码我没试过。你看一下行吗?如果可以的话,也只是粗略的计算一下,效果肯定不怎么好。反正就是这么个思路 StretchBlt 可以缩放自绘图形吗? 不一起缩小 绘制的图形 就会出现在背景图的 不同位置我现在就是想一起缩小目前,通过另外一种方法解决就是在OnEraseBackgroud 里贴背景图 StretchBlt在OnDraw里 绘制图形 BitBlt可以同时缩放但 由于我这个是监测界面,所以每次刷新的时候 刷了一次背景 所以出现抖动 我给你一个代码吧,我跟你一样正在做这种趋势图~~别看这么两句代码啊~搞了我半个月~~具体思路,先写缩放功能,初始化中遍历窗口所有控件,并把控件坐标存起来,然后在onsize消息中触发缩放计算功能,具体代码如下:typedef CMap<CString, LPCSTR, CRect, CRect&> CMapCStringToCRect;typedef CList<CRect, CRect> CListRect;typedef struct _SCREEN{ int nScreenX; int nScreenY;}SCREEN;BOOL CRealTimeCurvesClientDlg::OnInitDialog(){CRect rectWnd; pWnd->GetWindowRect(&rectWnd); listRect.AddTail(&rectWnd); CWnd *pWndChild = pWnd->GetWindow(GW_CHILD); while(pWndChild) { pWndChild->GetWindowRect(&rectWnd); listRect.AddTail(&rectWnd); pWndChild = pWndChild->GetNextWindow(); }}void CRealTimeCurvesClientDlg::OnSize(UINT nType, int cx, int cy){int nCount=listRect.GetCount(); if(listRect.GetCount()>0) { CRect rectDlgNow; m_pWnd->GetWindowRect(&rectDlgNow); POSITION mP = listRect.GetHeadPosition(); CRect rectDlgSaved; rectDlgSaved = listRect.GetNext(mP); m_pWnd->ScreenToClient(rectDlgSaved); m_pWnd->ScreenToClient(rectDlgNow); float fRateScaleX = (float)(rectDlgNow.right-rectDlgNow.left)/(rectDlgSaved.right-rectDlgSaved.left); float fRateScaleY = (float)(rectDlgNow.bottom-rectDlgNow.top)/(rectDlgSaved.bottom-rectDlgSaved.top); m_pWnd->ClientToScreen(rectDlgSaved); m_pWnd->ClientToScreen(rectDlgNow); LOGFONT stFont; ::GetObject((HFONT)GetStockObject(DEFAULT_GUI_FONT), sizeof(stFont), &stFont); strcpy(stFont.lfFaceName,"Times New Roman"); stFont.lfHeight = (long)(fRateScaleY*14); stFont.lfWidth = (long)(fRateScaleX*7); CFont m_pCFont; m_pCFont.DeleteObject(); m_pCFont.CreateFontIndirect(&stFont); CRect rectChildSaved; CWnd *pWndChild = m_pWnd->GetWindow(GW_CHILD); while(pWndChild) { rectChildSaved = listRect.GetNext(mP); rectChildSaved.left = rectDlgNow.left+(int)((rectChildSaved.left-rectDlgSaved.left)* fRateScaleX); rectChildSaved.top = rectDlgNow.top+(int)((rectChildSaved.top-rectDlgSaved.top)*fRateScaleY); rectChildSaved.right = rectDlgNow.right+(int)((rectChildSaved.right-rectDlgSaved.right)* fRateScaleX); rectChildSaved.bottom = rectDlgNow.bottom+(int)((rectChildSaved.bottom-rectDlgSaved.bottom)* fRateScaleY); m_pWnd->ScreenToClient(rectChildSaved); pWndChild->MoveWindow(rectChildSaved); pWndChild->SetFont(&m_pCFont); pWndChild = pWndChild->GetNextWindow(); } // _CrtDumpMemoryLeaks(); }Invalidate();}具体的背景以及曲线的绘制用双缓冲就不闪了,缩放以后重新计算绘制图形和背景。动态获取你那个背景的rect,缩放之后根据比例计算~比如要在背景画10条线,一定要写成double xjg=(double)rect.right/(double)10,yjg=(double)rect.bottom/(double)10;对了,计算的时候一定要用double类型,在转换坐标的时候才自动转换成int型,不然你会发现你画的线不是均匀平分的。再贴一个画曲线的函数void S::DrawCurve(CDC* pDC, CRect rect, int Max_X_TimeLength_Value){ CDC Mem_DC; CBitmap MemBitmap; Mem_DC.CreateCompatibleDC(pDC); MemBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom); Mem_DC.SelectObject(&MemBitmap); CPen pen; pen.CreatePen(PS_SOLID,1,RGB(255,0,0));Mem_DC.SelectObject(pen); Mem_DC.MoveTo());//不要写数值,要根据传进来的rect计算 Mem_DC.LineTo());pen.DeleteObject(); pDC->BitBlt(0,0,rect.right-1,rect.bottom-1,&Mem_DC,0,0,SRCCOPY); MemBitmap.DeleteObject(); Mem_DC.DeleteDC();这段代码最主要的部分就是dc的获取,我是直接把图形都画在了一个picture控件上,那么我获取的时候直接CRect rect; GetDlgItem(IDC_picture)->GetClientRect(rect); CDC *pDC=GetDlgItem(IDC_picture)->GetDC();……GetDlgItem(IDC_STATIC_BACK)->ReleaseDC(pDC);欢迎交流~~~ 谢谢你的热心解答不过有个小问题,单文档MFC,我在某view中响应了OnMouseMove消息,那么我在此view中想再响应onsize消息 什么代码也没有添加呢,就报错 报以前正常的代码错误 ,什么重定义啊之类的 仔细检查一下代码吧,我这里在view里添加这两个消息没有问题~ onsize消息映射尽量不要添加到View的子类里头,尺寸变化应该由框架窗体来管理,你把这个消息映射添加到FrameWnd 直接发代码给我,我帮你调试一下看看[email protected] 添加SIZE消息冲突的问题已解决,原来程序把我手动添加的消息“afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);”覆盖了,诡异。。谢谢ATMCash4423分享的代码,我明天看看也谢谢yao050421103的建议近期结贴,谢谢各位的关注 求好书推介、、、、 为什么当屏保运行时不能发送鼠标事件 怎样解决invalid win 32 application? 菜鸟问个问题,希望不要见笑 请教:指针作为影射表的关键字时怎么用 vc知识库-www.vckbase.com-上面提到的Form++控件,哪里有免费的啊?(100分) 大家帮我看看这段代码有问题吗? 各位大侠好,有个问题.... 谁能告诉我visualc++有什么好书买啊! 如何修改一个MFC ActiveX插件的项目名称 IDispatch接口问题 内核可使用的和 SetupDiGetClassDevs 功能类似的函数是什么?
1、用GetClientRect等函数动态计算坐标,根据你的需求来绘图
2、在窗口的WM_SIZE事件里重绘你的的图
谢谢您的回答 不太懂 这样吧
我把我画的坐标 以及出现问题贴出来 麻烦大家帮忙看下
代码:
CDC dcMem;
GetClientRect(&rect);
CBitmap bmp; //内存中承载临时图象的位图
bmp.LoadBitmap(IDB_CURVE);
dcMem.CreateCompatibleDC(pDC);
dcMem.SetBkMode(TRANSPARENT); //透明模式,
CBitmap *pOldBit=dcMem.SelectObject(&bmp);
CPen whitedotpen(PS_DOT,1,COLOR_WHITE); //白色点画笔
CPen blacksolidpen(PS_SOLID,1,COLOR_BLACK); //黑色实画笔
CPen Redpen(PS_SOLID,1,COLOR_RED); //红色笔CPen* poldpen = dcMem.SelectObject(&whitedotpen);
int xx=rect.right-rect.left;
int yy=rect.bottom-rect.top;
SetRect(&m_rect,xx/8,yy/6,10*xx/11,6*yy/7);xlen = (float)(m_rect.right - m_rect.left)/50;
ylen = (float)(m_rect.bottom - m_rect.top)/10;
CString str=_T("");
int i,j;
//画白色点状网格for (i=0;i<=50;i++) //画白色点状网格(纵线)
{
dcMem.MoveTo(m_rect.left+xlen*i,m_rect.top);
dcMem.LineTo(m_rect.left+xlen*i,m_rect.bottom);
}
for (j=0;j<=10;j++) //画白色点状网格(横线)
{
dcMem.MoveTo(m_rect.left,m_rect.bottom-ylen*j);
dcMem.LineTo(m_rect.right,m_rect.bottom-ylen*j);
}
pDC->StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&dcMem,0,0,1270,640,SRCCOPY);
dcMem.SelectObject(pOldBit);
dcMem.SelectObject(poldpen);
bmp.DeleteObject();
dcMem.DeleteDC(); //删除DC全屏时 正常
拉伸至半屏将StretchBlt换成BitBlt 即pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY); 表格正常缩放了,但是图片不缩放
请教大家 如何一起缩放
SDI OnDraw里 贴背景图+自绘图形 能够满足缩放功能解决的楼 75分全送了
for(int y=0;y<rect.Height();y+=10)
{
dcMem.MoveTo(0,y);
dcMem.LineTo(rect.Width(),y);
}
画一排行,上面的代码我没试过。
你看一下行吗?
如果可以的话,也只是粗略的计算一下,效果肯定不怎么好。
反正就是这么个思路
目前,通过另外一种方法解决就是在OnEraseBackgroud 里贴背景图 StretchBlt
在OnDraw里 绘制图形 BitBlt
可以同时缩放
但 由于我这个是监测界面,所以每次刷新的时候 刷了一次背景 所以出现抖动
具体思路,先写缩放功能,初始化中遍历窗口所有控件,并把控件坐标存起来,然后在onsize消息中触发缩放计算功能,具体代码如下:typedef CMap<CString, LPCSTR, CRect, CRect&> CMapCStringToCRect;
typedef CList<CRect, CRect> CListRect;
typedef struct _SCREEN
{
int nScreenX;
int nScreenY;
}SCREEN;BOOL CRealTimeCurvesClientDlg::OnInitDialog()
{
CRect rectWnd;
pWnd->GetWindowRect(&rectWnd);
listRect.AddTail(&rectWnd);
CWnd *pWndChild = pWnd->GetWindow(GW_CHILD);
while(pWndChild)
{
pWndChild->GetWindowRect(&rectWnd);
listRect.AddTail(&rectWnd);
pWndChild = pWndChild->GetNextWindow();
}
}void CRealTimeCurvesClientDlg::OnSize(UINT nType, int cx, int cy)
{
int nCount=listRect.GetCount();
if(listRect.GetCount()>0)
{
CRect rectDlgNow;
m_pWnd->GetWindowRect(&rectDlgNow);
POSITION mP = listRect.GetHeadPosition();
CRect rectDlgSaved;
rectDlgSaved = listRect.GetNext(mP);
m_pWnd->ScreenToClient(rectDlgSaved);
m_pWnd->ScreenToClient(rectDlgNow);
float fRateScaleX = (float)(rectDlgNow.right-rectDlgNow.left)/(rectDlgSaved.right-rectDlgSaved.left);
float fRateScaleY = (float)(rectDlgNow.bottom-rectDlgNow.top)/(rectDlgSaved.bottom-rectDlgSaved.top);
m_pWnd->ClientToScreen(rectDlgSaved);
m_pWnd->ClientToScreen(rectDlgNow);
LOGFONT stFont;
::GetObject((HFONT)GetStockObject(DEFAULT_GUI_FONT), sizeof(stFont), &stFont);
strcpy(stFont.lfFaceName,"Times New Roman");
stFont.lfHeight = (long)(fRateScaleY*14);
stFont.lfWidth = (long)(fRateScaleX*7);
CFont m_pCFont;
m_pCFont.DeleteObject();
m_pCFont.CreateFontIndirect(&stFont);
CRect rectChildSaved;
CWnd *pWndChild = m_pWnd->GetWindow(GW_CHILD);
while(pWndChild)
{
rectChildSaved = listRect.GetNext(mP);
rectChildSaved.left = rectDlgNow.left+(int)((rectChildSaved.left-rectDlgSaved.left)* fRateScaleX);
rectChildSaved.top = rectDlgNow.top+(int)((rectChildSaved.top-rectDlgSaved.top)*fRateScaleY);
rectChildSaved.right = rectDlgNow.right+(int)((rectChildSaved.right-rectDlgSaved.right)* fRateScaleX);
rectChildSaved.bottom = rectDlgNow.bottom+(int)((rectChildSaved.bottom-rectDlgSaved.bottom)* fRateScaleY);
m_pWnd->ScreenToClient(rectChildSaved);
pWndChild->MoveWindow(rectChildSaved); pWndChild->SetFont(&m_pCFont); pWndChild = pWndChild->GetNextWindow();
}
// _CrtDumpMemoryLeaks();
}
Invalidate();
}具体的背景以及曲线的绘制用双缓冲就不闪了,缩放以后重新计算绘制图形和背景。
动态获取你那个背景的rect,缩放之后根据比例计算~比如要在背景画10条线,一定要写成double xjg=(double)rect.right/(double)10,yjg=(double)rect.bottom/(double)10;
对了,计算的时候一定要用double类型,在转换坐标的时候才自动转换成int型,不然你会发现你画的线不是均匀平分的。
再贴一个画曲线的函数void S::DrawCurve(CDC* pDC, CRect rect, int Max_X_TimeLength_Value)
{
CDC Mem_DC;
CBitmap MemBitmap;
Mem_DC.CreateCompatibleDC(pDC);
MemBitmap.CreateCompatibleBitmap(pDC,rect.right,rect.bottom); Mem_DC.SelectObject(&MemBitmap);
CPen pen;
pen.CreatePen(PS_SOLID,1,RGB(255,0,0));
Mem_DC.SelectObject(pen);
Mem_DC.MoveTo());//不要写数值,要根据传进来的rect计算
Mem_DC.LineTo());
pen.DeleteObject();
pDC->BitBlt(0,0,rect.right-1,rect.bottom-1,&Mem_DC,0,0,SRCCOPY);
MemBitmap.DeleteObject();
Mem_DC.DeleteDC();这段代码最主要的部分就是dc的获取,我是直接把图形都画在了一个picture控件上,那么我获取的时候直接CRect rect;
GetDlgItem(IDC_picture)->GetClientRect(rect);
CDC *pDC=GetDlgItem(IDC_picture)->GetDC();
……
GetDlgItem(IDC_STATIC_BACK)->ReleaseDC(pDC);欢迎交流~~~
谢谢你的热心解答
不过有个小问题,单文档MFC,我在某view中响应了OnMouseMove消息,那么我在此view中想再响应onsize消息 什么代码也没有添加呢,就报错 报以前正常的代码错误 ,什么重定义啊之类的
onsize消息映射尽量不要添加到View的子类里头,尺寸变化应该由框架窗体来管理,你把这个消息映射添加到FrameWnd
[email protected]