关于MFC中绘图问题

gyjjone 2014-04-03 03:22:28
在窗口中已经有一个picture control并且也已经添加了位图,可以获得这个图的句柄和位置等信息,我现在想在另一个位置将这个图片绘制出来,应该怎么办?求指导!
...全文
612 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
向立天 2014-05-26
  • 打赏
  • 举报
回复
您好 我是本版版主 此帖已多日无人关注 请您及时结帖 如您认为问题没有解决可按无满意结帖处理 另外本版设置了疑难问题汇总帖 并已在版面置顶 相关规定其帖子中有说明 您可以根据规定提交您帖子的链接 如您目前不想结帖只需回帖说明 我们会删除此结帖通知 见此回复三日内无回应 我们将强制结帖 相关规定详见界面界面版关于版主结帖工作的具体办法
风之刃3 2014-04-25
  • 打赏
  • 举报
回复
引用 23 楼 gz_qmc 的回复:
原来是一个函数 每次都要分配内存,装载数据,画图,释放内存,效率不高 封成类后,只分配一次,转载一次,之后不释放,要的时候就画 等程序结束的时候统一释放
有点理解了,我试试,thank you
gz_qmc 2014-04-25
  • 打赏
  • 举报
回复
原来是一个函数 每次都要分配内存,装载数据,画图,释放内存,效率不高 封成类后,只分配一次,转载一次,之后不释放,要的时候就画 等程序结束的时候统一释放
鸥翔鱼游1 2014-04-25
  • 打赏
  • 举报
回复
好文章。总是要支持一下
kuankuan_qiao 2014-04-25
  • 打赏
  • 举报
回复
//图片加载
HRESULT CPicture_Disp5Dlg::LoadFromBuffer(BYTE*   pBuff,  int   nSize)
{
	bool   bResult   =   false;   
	HGLOBAL   hGlobal   =   GlobalAlloc(GMEM_MOVEABLE,   nSize);   
	void*   pData   =   GlobalLock(hGlobal);   
	memcpy(pData,   pBuff,   nSize);   
	GlobalUnlock(hGlobal);   
	IStream*   pStream   =   NULL;   
	if   (CreateStreamOnHGlobal(hGlobal,   TRUE,   &pStream)   ==   S_OK)   
	{   
		HRESULT   hr;   
		if   ((hr   =   OleLoadPicture(pStream,   nSize,   FALSE,IID_IPicture,(LPVOID   *)&m_pPicture))   ==   S_OK)   
			bResult   =   true;   
		pStream->Release();   
	}   
	return   bResult;   

}

  
//图片显示函数
BOOL CPicture_Disp5Dlg::DrawFormFile(CString fileName,CDC   *pDC) 
{
	CFile cFile; 
	CFileException e;   
	if(cFile.Open(fileName,   CFile::modeRead   |   CFile::typeBinary,   &e))   
	{   
		BYTE*   pBuff   =   new   BYTE[cFile.GetLength()];   
		if   (cFile.Read(pBuff,   cFile.GetLength())   >   0)   
		LoadFromBuffer(pBuff,   cFile.GetLength());  
		delete   []   pBuff;   
		//得到图象尺寸   
		long   hmWidth;   
		long   hmHeight;   
		m_pPicture->get_Width(&hmWidth);   
		m_pPicture->get_Height(&hmHeight);   
		int   nWidth =   MulDiv(hmWidth, pDC->GetDeviceCaps(LOGPIXELSX),   2540);   
		int   nHeight =   MulDiv(hmHeight, pDC->GetDeviceCaps(LOGPIXELSY),   2540);   
		//在内存中画   
		CDC   MemDC;   
		CBitmap   bmp;   
		bmp.CreateCompatibleBitmap(pDC,nWidth,nHeight);   
		MemDC.CreateCompatibleDC(NULL);   
		MemDC.SelectObject(&bmp);   
		m_pPicture->Render(MemDC.m_hDC,0,0,nWidth,nHeight,0,hmHeight,hmWidth,-hmHeight,NULL);   
		//到此为止已经把图象画在内存dc上了   
		//剩下就是copy到显示dc上了,可以BitbBlt直接copy,也可以用StretchBlt缩放copy   
		pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY); 
	
	}     

	return   true;   	
}  



{
	CPaintDC dc(this); // device context for painting
	if (IsIconic())
	{
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{	
		CString filename;
		filename = "ye.bmp";//绝对路径,图像在工程目录下
		DrawFormFile(filename,&dc);
		CDialog::OnPaint();
	}	
}

kuankuan_qiao 2014-04-25
  • 打赏
  • 举报
回复
引用 5 楼 gz_qmc 的回复:
方法二: 1、自定义窗口CXXXXWnd类画图函数,直接画文件名 void CXXXXWnd::ShowPic(CDC *pDC,CString lpstrFile,int sx,int sy,int nScrWidth, int nScrHeight); 2、在窗口的OnPaint中,将图画到指定位置 ShowPic(&dc,"C:\\A.JPG",0,0,500,400"); ShowPic(&dc,"D:\\B.BMP",500,0,1000,400); 注意:如果先ShowPic到内存DC,然后通过AlphaBlend等可实现半透明及缩放等 赋予ShowPic源代码
void CGoHomeDlg::ShowPic(CDC *pDC,CString lpstrFile,int sx,int sy,int nScrWidth, int nScrHeight)
{
	IPicture  *pPic;  
	IStream   *pStm;  

	HANDLE    hFile=NULL;  
	DWORD     dwFileSize,dwByteRead;  

	//打开硬盘中的图形文件  	hFile=CreateFile(lpstrFile,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);  
	if (hFile!=INVALID_HANDLE_VALUE)  
	{  
		dwFileSize=GetFileSize(hFile,NULL);//获取文件字节数  
		if(dwFileSize==0xFFFFFFFF)  
		{
			CloseHandle(hFile);
			return;  
		}
	}  
	else	return;  
	
	//分配全局存储空间  
	HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE,dwFileSize);  
	if(hGlobal==NULL) 	return;  

	LPVOID  pvData =GlobalLock(hGlobal);  

	if(pvData==NULL)//锁定分配内存块  
	{
		GlobalFree(hGlobal);
		return;  
    }
	ReadFile(hFile,pvData,dwFileSize,&dwByteRead,NULL);//把文件读入内存缓冲区  
	CloseHandle(hFile);//关闭打开的文件  

	GlobalUnlock(hGlobal);  

	CreateStreamOnHGlobal(hGlobal,TRUE,&pStm);  

	//装入图形文件  
	OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic);  
	pStm->Release();
	pStm=NULL;
	GlobalFree(hGlobal);

	if(NULL==m_Pic)   return;

	long   hmWidth;//图片的真实宽度  
	long   hmHeight;//图片的真实高度  
	pPic->get_Width(&hmWidth);  
	pPic->get_Height(&hmHeight);  

	//将图形输出到屏幕上(有点像BitBlt)  
	bResult=pPic->Render(pDC->m_hDC,sx,sy,nScrWidth,nScrHeight,0,hmHeight,hmWidth,-hmHeight,NULL);  

	pPic->Release();  
}
这段代码在一本书上看过
风之刃3 2014-04-24
  • 打赏
  • 举报
回复
引用 21 楼 gz_qmc 的回复:
你说的问题我没遇到过 但我在10楼有提过方法三 不知道你看到没有
额,初学者.............看了,没看懂.........你这是直接改造CPicture类吗???
gz_qmc 2014-04-24
  • 打赏
  • 举报
回复
你说的问题我没遇到过 但我在10楼有提过方法三 不知道你看到没有
gz_qmc 2014-04-24
  • 打赏
  • 举报
回复
你说的问题我们遇到过 但我在10楼有提过方法三 不知道你看到没有
风之刃3 2014-04-24
  • 打赏
  • 举报
回复
引用 5 楼 gz_qmc 的回复:
方法二: 1、自定义窗口CXXXXWnd类画图函数,直接画文件名 void CXXXXWnd::ShowPic(CDC *pDC,CString lpstrFile,int sx,int sy,int nScrWidth, int nScrHeight); 2、在窗口的OnPaint中,将图画到指定位置 ShowPic(&dc,"C:\\A.JPG",0,0,500,400"); ShowPic(&dc,"D:\\B.BMP",500,0,1000,400); 注意:如果先ShowPic到内存DC,然后通过AlphaBlend等可实现半透明及缩放等 赋予ShowPic源代码
void CGoHomeDlg::ShowPic(CDC *pDC,CString lpstrFile,int sx,int sy,int nScrWidth, int nScrHeight)
{
	IPicture  *pPic;  
	IStream   *pStm;  

	HANDLE    hFile=NULL;  
	DWORD     dwFileSize,dwByteRead;  

	//打开硬盘中的图形文件  	hFile=CreateFile(lpstrFile,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);  
	if (hFile!=INVALID_HANDLE_VALUE)  
	{  
		dwFileSize=GetFileSize(hFile,NULL);//获取文件字节数  
		if(dwFileSize==0xFFFFFFFF)  
		{
			CloseHandle(hFile);
			return;  
		}
	}  
	else	return;  
	
	//分配全局存储空间  
	HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE,dwFileSize);  
	if(hGlobal==NULL) 	return;  

	LPVOID  pvData =GlobalLock(hGlobal);  

	if(pvData==NULL)//锁定分配内存块  
	{
		GlobalFree(hGlobal);
		return;  
    }
	ReadFile(hFile,pvData,dwFileSize,&dwByteRead,NULL);//把文件读入内存缓冲区  
	CloseHandle(hFile);//关闭打开的文件  

	GlobalUnlock(hGlobal);  

	CreateStreamOnHGlobal(hGlobal,TRUE,&pStm);  

	//装入图形文件  
	OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic);  
	pStm->Release();
	pStm=NULL;
	GlobalFree(hGlobal);

	if(NULL==m_Pic)   return;

	long   hmWidth;//图片的真实宽度  
	long   hmHeight;//图片的真实高度  
	pPic->get_Width(&hmWidth);  
	pPic->get_Height(&hmHeight);  

	//将图形输出到屏幕上(有点像BitBlt)  
	bResult=pPic->Render(pDC->m_hDC,sx,sy,nScrWidth,nScrHeight,0,hmHeight,hmWidth,-hmHeight,NULL);  

	pPic->Release();  
}
直接释放资源的话,你们试试把对话框拉出屏幕,程序会报错的吧,因为刷新对话框出了问题,有大神能解决不???
gz_qmc 2014-04-21
  • 打赏
  • 举报
回复
另外,该函数可以显示BMP和GIF,所以要能兼容BMP资源和GIF资源就更好了
路人乙2019 2014-04-21
  • 打赏
  • 举报
回复
选到dc里面,直接用bitblt画就是了。
longzhishen 2014-04-21
  • 打赏
  • 举报
回复
可以将图表保存 bmp 文件
longzhishen 2014-04-21
  • 打赏
  • 举报
回复
http://blog.csdn.net/longzhishen/article/details/24254183 看看这个
凌乱哥 2014-04-11
  • 打赏
  • 举报
回复
引用 10 楼 gz_qmc 的回复:
如果你有闲工夫;再改造一下 装载到IPicture 的方法更进一步,直接装载到DDC位图和内存DC,就更成熟了
我改成了从资源加载jpg图片的方式

void  ShowPic(CDC *pDC,UINT nID,int sx,int sy,int nScrWidth, int nScrHeight)
{
	HINSTANCE hInst = AfxGetResourceHandle();
	HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),_T("JPG")); // type
	if (!hRsrc)
		return;

	// load resource into memory
	DWORD len = SizeofResource(hInst, hRsrc);
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
	if (!lpRsrc)
		return;

	IPicture  *pPic = NULL;
	IStream   *pStm = NULL;
	//分配全局存储空间  
	HGLOBAL hGlobal=GlobalAlloc(GMEM_FIXED,len);  
	if(hGlobal==NULL)
		return;  

	BYTE*  pvData = (BYTE*)GlobalLock(hGlobal);  
	if(pvData==NULL)//锁定分配内存块  
	{
		GlobalFree(hGlobal);
		return;  
	}

	memcpy(pvData,lpRsrc,len);
	GlobalUnlock(hGlobal);
	CreateStreamOnHGlobal(hGlobal,TRUE,&pStm);  

	//装入图形文件  
	OleLoadPicture(pStm,len,TRUE,IID_IPicture,(LPVOID*)&pPic);  
	pStm->Release();
	pStm = NULL;
	GlobalFree(hGlobal);

	if(NULL == pPic)return;

	long   hmWidth;//图片的真实宽度  
	long   hmHeight;//图片的真实高度  
	pPic->get_Width(&hmWidth);  
	pPic->get_Height(&hmHeight);  

	//将图形输出到屏幕上(有点像BitBlt)  
	pPic->Render(pDC->m_hDC,sx,sy,nScrWidth,nScrHeight,0,hmHeight,hmWidth,-hmHeight,NULL);  
	pPic->Release();  
}
调用的时候

CPaintDC dc(this);
ShowPic(&dc,IDR_JPG1,0,0,300,300);
gz_qmc 2014-04-11
  • 打赏
  • 举报
回复
不错,举一反三,这才是程序员应该有的态度和习惯
feibeyond 2014-04-06
  • 打赏
  • 举报
回复
引用 9 楼 gz_qmc 的回复:
[quote=引用 7 楼 feibeyond 的回复:] 兄台这么厉害,我忍不住想请教个问题:我想修改static控件的背景色,一开始为默认的,数据读入后为蓝色,1秒后自动恢复为默认色,我用HBRUSH CRandomDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)只能实现数据读入后变成蓝色,但是无法实现1秒后变为透明这个功能,请兄台赐教!
如果我是你,绝对不用STATIC控件 更不用去追究他的细节 你确实没看懂我的奉献[/quote] 我现在是现学现卖,对于你说的哪类的程序员用什么控件怎么用控件,我看过,但是我现在做的还没到那个深度,最近也是在看基础知识。。。
凌乱哥 2014-04-05
  • 打赏
  • 举报
回复
引用 10 楼 gz_qmc 的回复:
[quote=引用 6 楼 dingxz105090 的回复:] 方法2简单又吊飞天啊哥
就我观察你的水平,不应该只限于这样的认识 直接从文件画,装载总是需要时间的,大量图片的时候,效率肯定有问题 如果你能改造方法二到方法三,才和你的水平相当 方法三: 先装载好图象,不用OnPaint的时候在装载,直接显示就更好了
class CPicture
{
public:
	CPicture();
	virtual ~CPicture();
public:
	void Show(CDC *pDC, int xSrc, int ySrc, int wSrc, int hSrc);
	BOOL LoadPicture(LPCTSTR lpFileName);
	void Release();
private:
	IPicture * m_Pic;//如果这里用链表,还可以保存多张图片,实现GIF等效果就方便了
};
至于显示,直接多加几种显示方式,比如带半透明等基本不废吹灰之力 如果你有闲工夫;再改造一下 装载到IPicture 的方法更进一步,直接装载到DDC位图和内存DC,就更成熟了

class CPicture
{
public:
	CPicture();
	virtual ~CPicture();
public:
	void Show(CDC *pDC, int xSrc, int ySrc, int wSrc, int hSrc);
	BOOL LoadPicture(LPCTSTR lpFileName);
        void    InitDC(CDC *pDC,int  w, int  h);
	void Release();
private:
        CDC *xDC;
        CBitmap *xBMP;
};
 void    CPicture::InitDC(CDC *pDC,int  w, int  h)
{
      xDC=创建兼容DC(pDC);
      xBMP=创建兼容位图(pDC,w,h);
      xDC->选择对象(xBMP);
}
那么,显示方法可以用Bltbit等直接实现,半透明,缩放等就更好控制了 在窗口初始话的地方InitDC(GetDC(),w,h),并LoadPicture 剩下显示就可以了[/quote] 哥你高估我了,我喜欢收集好的实现,然后需要的时候直接用,较少像你这样去研究 多多休息啊,熬夜这么晚还在搞技术?
gz_qmc 2014-04-05
  • 打赏
  • 举报
回复
引用 6 楼 dingxz105090 的回复:
方法2简单又吊飞天啊哥


就我观察你的水平,不应该只限于这样的认识
直接从文件画,装载总是需要时间的,大量图片的时候,效率肯定有问题

如果你能改造方法二到方法三,才和你的水平相当

方法三:
先装载好图象,不用OnPaint的时候在装载,直接显示就更好了

class CPicture
{
public:
CPicture();
virtual ~CPicture();
public:
void Show(CDC *pDC, int xSrc, int ySrc, int wSrc, int hSrc);
BOOL LoadPicture(LPCTSTR lpFileName);
void Release();
private:
IPicture * m_Pic;//如果这里用链表,还可以保存多张图片,实现GIF等效果就方便了
};

至于显示,直接多加几种显示方式,比如带半透明等基本不废吹灰之力

如果你有闲工夫;再改造一下
装载到IPicture 的方法更进一步,直接装载到DDC位图和内存DC,就更成熟了

class CPicture
{
public:
CPicture();
virtual ~CPicture();
public:
void Show(CDC *pDC, int xSrc, int ySrc, int wSrc, int hSrc);
BOOL LoadPicture(LPCTSTR lpFileName);
void InitDC(CDC *pDC,int w, int h);
void Release();
private:
CDC *xDC;
CBitmap *xBMP;
};
void CPicture::InitDC(CDC *pDC,int w, int h)
{
xDC=创建兼容DC(pDC);
xBMP=创建兼容位图(pDC,w,h);
xDC->选择对象(xBMP);
}
那么,显示方法可以用Bltbit等直接实现,半透明,缩放等就更好控制了

在窗口初始话的地方InitDC(GetDC(),w,h),并LoadPicture
剩下显示就可以了
gz_qmc 2014-04-05
  • 打赏
  • 举报
回复
引用 7 楼 feibeyond 的回复:
兄台这么厉害,我忍不住想请教个问题:我想修改static控件的背景色,一开始为默认的,数据读入后为蓝色,1秒后自动恢复为默认色,我用HBRUSH CRandomDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)只能实现数据读入后变成蓝色,但是无法实现1秒后变为透明这个功能,请兄台赐教!
如果我是你,绝对不用STATIC控件 更不用去追究他的细节 你确实没看懂我的奉献
加载更多回复(8)

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧