程序功能:对某些参数进行计算,并生成一列JPG图,如1.jpg,2.jpg,3.jpg。然后利用GDI+,将1.jpg读入进来并显示在视图上,点击下一张按钮,依次读入后面的JPG图。
出现的问题:第一次计算时,能够正确生成所要的JPG图,并能将1.jpg读入进来。如果第二次对同样的参数进行计算,理论上程序会生成同样的三张JPG图,并且覆盖原来已有的JPG图。但实际上程序计算完毕,在保存第一张JPG图时出错退出。
问题的原因:因为GDI+读入第一次生成的1.jpg时,该文件被独占,导致第二次保存1.jpg文件时无法替换原有的文件。现在,我的问题是:如何在每一次计算前,清空视图,也就是取消程序对JPG文件的独占访问?
出现的问题:第一次计算时,能够正确生成所要的JPG图,并能将1.jpg读入进来。如果第二次对同样的参数进行计算,理论上程序会生成同样的三张JPG图,并且覆盖原来已有的JPG图。但实际上程序计算完毕,在保存第一张JPG图时出错退出。
问题的原因:因为GDI+读入第一次生成的1.jpg时,该文件被独占,导致第二次保存1.jpg文件时无法替换原有的文件。现在,我的问题是:如何在每一次计算前,清空视图,也就是取消程序对JPG文件的独占访问?
解决方案 »
- MFC中主窗体更改生成窗体中的数据
- 一个关于VC++调用C程序的链接问题
- 除了SQLAPI++,有其他类似这个东西的三方库吗
- 请教各位,CPropertySheet做的属性表怎么去掉底部的确定,取消,帮助等按钮,进来顶也有分,请帮一下忙!!!!
- 8** 在线等待: 第一次写模板函数, 为什么提示:"fatal error C1001: INTERNAL COMPILER ERROR":
- 如何获得控件的句柄
- mynamelj(风之羽翼)你的源码已收到,我还没测试可不可以用,接分先
- 又是这种问题,碰到就恼火~!
- 编译出错,请帮我看一看
- CComboBox 重绘 设置下拉列表的高度
- 通过API Hook修改IAT中函数地址为何截获不了Ws2_32.dll的recv() ?
- 取得窗体里的ToolBarWindow32句柄后如何读取某按扭状态
void CMy2008BAC35B02View::OnInitialUpdate()
{
// CScrollView::OnInitialUpdate(); // 内存画布的初始化设置
m_memDC.CreateCompatibleDC(NULL); // 准备一个内存DC
CDC * pDC = GetDC();
m_memBitmap.CreateCompatibleBitmap(pDC, 5000, 4000); // 准备一个5000*4000的位图画布
ReleaseDC(pDC); // 滚动条初始化设置
SetScrollSizes();
}
然后自定义一个消息函数,用来接收菜单传入的图片的地址
// 自定义消息函数,当文档类向本视图发送WM_NOTIFY_DRAW消息时,执行该函数,接收来自对话框的
// 图件完整路径信息,并绘图
LRESULT CMy2008BAC35B02View::OnNotifyDraw(WPARAM wParam, LPARAM lParam)
{
CString *p_strGetPicPathName;
// 将lParam参数转换为指向CString的指针,这个指针指向的CString对象携带了图件完整路径信息
p_strGetPicPathName = (CString*)lParam;
m_strPicPathName = *p_strGetPicPathName; // 完整路径赋值给View的成员变量 CMy2008BAC35B02Doc *pDoc = GetDocument();
pDoc->UpdateAllViews(NULL); // 更新视图,调用视图类的OnUpdate函数
SetScrollSizes(); // 设置滚动条
return 1;
}
其中定义了成员变量
CString p_strGetPicPathName;
然后再定义几个成员变量
Image *image;
IStream *pStream;
HGLOBAL hMem;
并在视图类的构造函数中初始化为NULL。
在OnUpdate中执行具体的绘图
void CMy2008BAC35B02View::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
CFile file;
if (!file.Open(m_strPicPathName, CFile::modeRead))
{
MessageBox("无法打开结果图件。", "错误", MB_OK|MB_ICONSTOP);
return;
} DWORD m_nFileLen;
m_nFileLen = file.GetLength(); // 每执行一次OnUpdate,都先清空内存
if (!hMem)
{
::GlobalFree(hMem);
hMem = NULL;
}
// 动态分配内存
// 分配的是固定内存,不是可移动的(GMEM_MOVEABLE),故不必锁定内存
hMem = ::GlobalAlloc(GMEM_FIXED, m_nFileLen);
if (hMem==NULL)
{
MessageBox("内存分配失败。", "错误", MB_OK|MB_ICONSTOP);
return;
}
if (file.Read(hMem, m_nFileLen)!=m_nFileLen)
{
MessageBox("读结果图件失败", "错误", MB_OK|MB_ICONSTOP);
::GlobalFree(hMem);
return;
}
file.Close();
pStream = NULL;
if (CreateStreamOnHGlobal(hMem, FALSE, &pStream)!=S_OK)
{
MessageBox("创建IStream对象失败。", "错误", MB_OK|MB_ICONSTOP);
::GlobalFree(hMem);
return;
} if (!image)
{
delete image;
image = NULL;
}
image = Image::FromStream(pStream);
pStream->Release(); // 得到图像的宽和高
m_nPicWidth = image->GetWidth();
m_nPicHeight = image->GetHeight(); // 得到当前视图的宽和高
CRect rcClient;
GetClientRect(&rcClient);
m_nClientWidth = rcClient.Width();
m_nClientHeight = rcClient.Height(); // 得到图像缩放后的宽和高
m_nPicZoomedWidth = (int)(m_nPicWidth*m_nScale);
m_nPicZoomedHeight = (int)(m_nPicHeight*m_nScale); // 求视图中显示图片的原点
m_nClientOriginX = (m_nClientWidth-m_nPicZoomedWidth)/2;
m_nClientOriginY = (m_nClientHeight-m_nPicZoomedHeight)/2;
if (m_nClientOriginX<0)
m_nClientOriginX = 0;
if (m_nClientOriginY<0)
m_nClientOriginY = 0; // 在内存画布上显示图形
// 将准备的位图画布选入内存DC中成为内存画布
m_pOldBitmap = m_memDC.SelectObject(&m_memBitmap);
m_memDC.FillSolidRect(0, 0, 5000, 4000, RGB(255,255,255)); // 用白色填充整个内存画布
Graphics graphics(m_memDC.GetSafeHdc()); // 内存DC和GDI+的Graphics对象关联
// 设置插值模式改善图像缩放质量
graphics.SetInterpolationMode(InterpolationModeNearestNeighbor);
Rect destinationRc(0, 0, m_nPicZoomedWidth, m_nPicZoomedHeight);
// 在内存画布上显示图像
graphics.DrawImage(image, destinationRc, 0, 0, m_nPicWidth, m_nPicHeight, UnitPixel);
m_memDC.SelectObject(m_pOldBitmap);
Invalidate(); // 提示OnDraw重绘
}最后在OnDraw中显示图像
void CMy2008BAC35B02View::OnDraw(CDC* pDC)
{
CMy2008BAC35B02Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
// 直接绘制内存画布上的位图(双缓冲)
pDC->BitBlt(m_nClientOriginX, m_nClientOriginY, m_nPicZoomedWidth, m_nPicZoomedHeight,
&m_memDC, 0, 0, SRCCOPY);
}
如果按照上面的代码,分配的内存应该都是及时清空了的,因为每一次显示JPG时,都会先清空上一次分配的内存。但实际情况是随着JPG的不断显示,程序耗费的内存越来越多。不过,如果程序最小化了,貌似内存又被瞬间清空了,不知是怎么回事?