gpt4 book ai didi

c++ - Visual C++ 如何使用 CPaintDC、CDC 在 CView 中重绘图像

转载 作者:搜寻专家 更新时间:2023-10-31 02:15:04 25 4
gpt4 key购买 nike

我使用 Visual Studio 2015,使用 MFC 多文档应用程序(功能区样式)。我正在尝试将 png 图像添加到 CView 并使用 WM_TIMER 制作幻灯片。首先,我出于相同的目的制作了基于对话框的应用程序,它运行良好。这些应用程序之间的区别在于,图像是在 PictureControl (CStatic) 的对话窗口中的第一个应用程序中绘制的,由工具箱添加。在第二个应用程序中,我试图以完全相同的方式将图像添加到 CView 中的 CStatic。但是对于 CView,它不能正确重绘。只有当我改变窗口大小时(拉伸(stretch),最大化)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 被计时器正确调用。为什么仅在调整主窗口大小时显示图像?

最佳答案

void CCardioAppView::OnPaint()
{
CPaintDC view_dc(this);
...
CPaintDC dc(&m_ctrlImage); //<== wrong place
...
}

CPaintDCBeginPaint/EndPaint 的包装器,用于响应 WM_PAINT 消息。它不能用于从另一个窗口获取设备上下文。

要绘制静态控件,您必须让所有者绘制控件。但这里没有必要。您可以只使用图片控件并简单地调用 CStatic::SetBitmap

void CCardioAppView::OnTimer(UINT_PTR nIDEvent)
{
CView::OnTimer(nIDEvent);
if (ShowImageTimer == nIDEvent)
{
m_iCurrentImage++;
if (m_iCurrentImage >= theApp.FullBmpMap.size())
m_iCurrentImage = 0;

//get HBITMAP: ???
auto bmp_iter = theApp.FullBmpMap.find(m_iCurrentImage);
HBITAMP hbitmap = bmp_iter->second; //???
m_ctrlImage.SetBitmap(hbitmap);
}
}

不要使用此方法覆盖 OnPaint()OnSize()


第二个选项:CStatic 不会拉伸(stretch)位图。您可以使用 CPictureHolder 来拉伸(stretch)位图。使用下面的示例(不要创建任何 m_ctrlImage/CStatic 控件)

void OnPaint()
{
CPaintDC dc(this);

auto bmp_iter = theApp.FullBmpMap.find(m_iCurrentImage);
HBITAMP hbitmap = bmp_iter->second; //???

CPictureHolder pic;
pic.CreateFromBitmap(hbitmap);

CRect rect;
GetClientRect(&rect);
pic.Render(&dc, rect, rect);
}

void CCardioAppView::OnTimer(UINT_PTR nIDEvent)
{
CView::OnTimer(nIDEvent);
if (nIDEvent == ShowImageTimer)
{
m_iCurrentImage++;
if (m_iCurrentImage >= theApp.FullBmpMap.size())
m_iCurrentImage = 0;
Invalidate(TRUE);
}
}

第三个选项:如果要自己画,那就用window自带的DC。示例:

void CCardioAppView::OnPaint()
{
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);

auto bmp_iter = theApp.FullBmpMap.find(m_iCurrentImage);
HBITAMP hbitmap = bmp_iter->second; //???

CBitmap bmp;
bmp.Attach(hbitmap);
CDC memdc;
memdc.CreateCompatibleDC(&dc);
memdc.SelectObject(&bmp);

BITMAP b;
bmp.GetObject(sizeof(BITMAP), &b);

CRect scaleRect = rect;
if (rect.Height() <= b.bmHeight)
{
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);

bmp.Detach();
}

关于c++ - Visual C++ 如何使用 CPaintDC、CDC 在 CView 中重绘图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39119821/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com