一个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

浙公网安备 33010602011771号