一个c++ OCX,用于在应用程序的任何窗口上绘图
介绍 这个OCX让你可以缩放任何你喜欢的图片 窗口(至少)您的应用程序。有三个主要部分, 即加载所需的图片,Windows事件处理程序的重定向 然后画图。 Windows NT, Windows 2000和Windows XP只允许一个应用程序 重写自己窗口的Windows事件处理程序。这个例子 或多或少是自我解释。使用OleLoadPicture()加载图片。 图片将使用Windows标准图形API绘制 strechblt()函数。 要取代Windows事件处理程序,使用SetWindowLong()。 细节 绘图程序 主绘图是在ondraw方法中完成的。万一 OCX应该在其他窗口上绘制,而不是自己,它会直接调用ondraw。 因为OCX是使用MFC生成的,所以方法头是标准的 自动生成: 隐藏,复制Code
void CPictureZoomCtrl::OnDraw( CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
PictureZoom使用一个标志来识别图片是否具有 已加载或未加载: 隐藏,复制Code
if (m_bNoPicture) return;
第一步是创建一个兼容的DC需要容纳的图片: 隐藏,复制Code
CDC mdc; // memory DC mdc.CreateCompatibleDC(pdc); CBitmap* pOld = mdc.SelectObject(&m_Picture);
为防止在绘制拉伸或缩小的图片时出现干扰色彩, 正确设置颜色模式: 隐藏,复制Code
pdc->SetStretchBltMode(COLORONCOLOR); mdc.SetStretchBltMode(COLORONCOLOR);
为了处理图片,我们需要它的尺寸: 隐藏,复制Code
m_Picture.UnrealizeObject(); BITMAP BM; m_Picture.GetBitmap(&BM);
接下来的部分有点棘手,因为我们需要区分三种方法 展示图片的方法。第一种是在不保留外观的情况下绘制 原图比例: 隐藏,复制Code
if (!m_bAspectRatio) pdc->StretchBlt(0, 0, rcBounds.Width(), rcBounds.Height(),&mdc, 0, 0, BM.bmWidth, BM.bmHeight, SRCCOPY);
下一组不同于其他两种情况: 隐藏,复制Code
else { double Strech = double(rcBounds.Width()) / double(BM.bmWidth); int iHeight = Strech * BM.bmHeight; int iWidth = Strech * BM.bmWidth; int yMove = ((iHeight - rcBounds.Height()) / 2) / Strech;
另外两种情况中的第一种是图片需要被剪切 在顶部和底部以缩放的方式绘制它在整个给定的窗口。 第一步是计算左上角 在源(未缩放!)位图: 隐藏,复制Code
if (yMove >= 0) { // Strech for width int xp = -m_xAdd; int yp = yMove - m_yAdd; if (xp < 0) xp = 0; if (yp < 0) yp = 0; if (xp > iWidth - rcBounds.Width()) xp = iWidth - rcBounds.Width(); if (yp > (iHeight - rcBounds.Height()) / Strech) yp = (iHeight - rcBounds.Height()) / Strech;
因为我对图片的中心显示有点不满意, 我决定也允许一些对齐设置: 隐藏,复制Code
if (m_Align == TOP) yp = 0; else if (m_Align == BOTTOM) yp = (iHeight - rcBounds.Height()) / Strech; m_xAdd = -xp; m_yAdd = yMove - yp;
第1种情况的最后一步是简单地对源矩形进行blit 在目标窗口上使用strechblt(): 隐藏,复制Code
// Blit only on the rectangle that is invalid CRect SourceRect((rcInvalid.left * BM.bmWidth) / rcBounds.Width() + xp, (rcInvalid.top * (rcBounds.Height() / Strech)) / rcBounds.Height() + yp, (rcInvalid.right * BM.bmWidth) / rcBounds.Width() + xp, (rcInvalid.bottom * (rcBounds.Height() / Strech)) / rcBounds.Height() + yp); pdc->StretchBlt(rcInvalid.left, rcInvalid.top, rcInvalid.Width(), rcInvalid.Height(),&mdc, SourceRect.left, SourceRect.top, SourceRect.right - SourceRect.left, SourceRect.bottom - SourceRect.top, SRCCOPY); }
第二种情况或多或少等于前一步。 唯一的区别是,图片现在会被截断 在左手和右手边。这发生时,当窗口 在此基础上绘制的比例小于1(见宽对高)。 隐藏,复制Code
else { Strech = double(rcBounds.Height()) / double(BM.bmHeight); int iHeight = Strech * BM.bmHeight; int iWidth = Strech * BM.bmWidth; int xMove = ((iWidth - rcBounds.Width()) / 2) / Strech; int xp = xMove - m_xAdd; int yp = -m_yAdd; if (xp < 0) xp = 0; if (yp < 0) yp = 0; if (xp > (iWidth - rcBounds.Width()) / Strech) xp = (iWidth - rcBounds.Width()) / Strech; if (yp > iHeight - rcBounds.Height()) yp = iHeight - rcBounds.Height();
再次,我决定允许一些对齐(对窗口的左或右边界): 隐藏,复制Code
if (m_Align == LEFT) xp = 0; else if (m_Align == RIGHT) xp = (iWidth - rcBounds.Width()) / Strech; m_xAdd = xMove - xp; m_yAdd = -yp; // Blit only on the rectangle that is invalid CRect SourceRect((rcInvalid.left * rcBounds.Width()/Strech) / rcBounds.Width() + xp, (rcInvalid.top * BM.bmHeight) / rcBounds.Height() + yp, (rcInvalid.right * rcBounds.Width()/Strech) / rcBounds.Width() + xp, (rcInvalid.bottom * BM.bmHeight) / rcBounds.Height() + yp); pdc->StretchBlt(rcInvalid.left, rcInvalid.top, rcInvalid.Width(), rcInvalid.Height(),&mdc, SourceRect.left, SourceRect.top, SourceRect.right - SourceRect.left, SourceRect.bottom - SourceRect.top, SRCCOPY); } }
绘制的最后一步是释放所有使用的资源: 隐藏,复制Code
mdc.SelectObject(pOld); mdc.DeleteDC(); }
这篇文章将在接下来的几天中尽快继续 工作和学习之间有更多的时间。 本文转载于:http://www.diyabc.com/frontweb/news10645.html