【发布时间】:2016-12-31 09:11:35
【问题描述】:
我使用 Visual Studio 2015,使用 MFC 多文档应用程序(功能区样式)。 我正在尝试将 png 图像添加到 CView 并使用 WM_TIMER 制作幻灯片。 首先,我制作了具有相同目的的基于对话框的应用程序,它运行良好。这些应用程序之间的区别在于,图像是在 PictureControl (CStatic) 对话框窗口中的第一个应用程序中绘制的,由工具箱添加。在第二个应用程序中,我试图以完全相同的方式将图像添加到 CView 中的 CStatic。但是使用 CView 它不能正确重绘。只有当我改变窗口大小(拉伸,最大化)时,png图像才会改变,但是当我停止调整窗口大小时,图像会再次冻结。
创建 CStatic 控件。
void CCardioAppView::OnInitialUpdate()
{
CView::OnInitialUpdate();
CRect rect;
GetClientRect(rect);
BOOL b = m_ctrlImage.Create(_T(""), WS_CHILD | WS_VISIBLE, rect,this,2);
m_ctrlImage.ModifyStyle(0, SS_BITMAP, SWP_NOSIZE);
}
通过定时器和 OnSize() 重绘
void CCardioAppView::OnTimer(UINT_PTR nIDEvent)
{
if (ShowImageTimer == nIDEvent)
{
auto bmp_iter = theApp.FullBmpMap.begin();
int sz = theApp.FullBmpMap.size();
CRect ImageRect;
GetClientRect(&ImageRect);
if (m_iCurrentImage < sz)
{
m_iCurrentImage++;
InvalidateRect(ImageRect, false);
}
else
{
m_iCurrentImage = 1;
}
}
CView::OnTimer(nIDEvent);
}
void CCardioAppView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
CRect rect;
if (m_ctrlImage.GetSafeHwnd())
{
GetClientRect(rect);
m_ctrlImage.DestroyWindow();
BOOL b = m_ctrlImage.Create(_T(""), WS_CHILD | WS_VISIBLE, rect, this, 2);
m_ctrlImage.ModifyStyle(0, SS_BITMAP);
}
}
重绘 OnPaint()
void CCardioAppView::OnPaint()
{
CPaintDC view_dc(this); // device context for painting
CBitmap bmp;
CRect rect, scaleRect;
BITMAP b;
auto bmp_iter = theApp.FullBmpMap.find(m_iCurrentImage);
GetClientRect(&rect);
if (bmp_iter == theApp.FullBmpMap.end()) return;
bmp.Attach((*bmp_iter).second);
bmp.GetObject(sizeof(BITMAP), &b);
CPaintDC dc(&m_ctrlImage);
CDC memdc;
memdc.CreateCompatibleDC(&dc);
memdc.SelectObject(&bmp);
if (rect.Height() <= b.bmHeight) //scaling image
{
scaleRect = rect;
scaleRect.right = rect.left + ((b.bmWidth*rect.Height())/ b.bmHeight);
}
dc.FillSolidRect(rect, RGB(255, 255, 255));
dc.StretchBlt(0, 0, scaleRect.Width(), scaleRect.Height(), &memdc,
0, 0, b.bmWidth, b.bmHeight, SRCCOPY);
//dc.MoveTo(0, 0);
(*bmp_iter).second.Detach();
(*bmp_iter).second.Attach(bmp);
bmp.Detach();
}
OnPaint 被计时器正确调用。为什么只有在调整主窗口大小时才显示图像?
【问题讨论】:
-
我建议您使用
ON_WM_ERASEBKGND()及其处理程序OnEraseBkgnd(CDC* pDC)尝试一些事情。可能是返回与其默认父类实现相反的值。 -
顺便说一句,为什么每次调整大小时都要销毁并重新创建
m_ctrlImage?为什么不简单地调整它的大小 (CWnd::SetWindowPos)?