有时在绘图期间设备上下文大小会减小

Posted

技术标签:

【中文标题】有时在绘图期间设备上下文大小会减小【英文标题】:Device context size is getting reduced during drawing sometimes 【发布时间】:2020-05-29 07:33:31 【问题描述】:

我们在 MFC 中有一个应用程序。

我们遇到了设备上下文问题。 情况就像 - 我们有一个信息显示窗口,它的大小和位置是可变的。 在某些大小和位置变化的场景中,只绘制了窗口的一部分,就像窗口的一部分被切割了一样。

我们怀疑设备上下文中的矩形与从 GetWindowRect 函数返回的矩形之间存在差异。 所以我们已经记录并检查了从设备上下文中绘制的窗口矩形的大小,并且 内存 DC 的窗口矩形,用于在问题场景中绘制。

但两者都返回了小窗口矩形大小。 也就是当时的设备上下文只有rect的部分信息。

我们没有调用 UpdateWindow() 或 Invalidate()。 当我们使用 WinSpy 聚焦窗口时,整个窗口都存在,但只绘制了一小部分。 我们在此窗口上方放置并移除了另一个窗口,以检查是否会发生任何重新绘制。但问题仍然存在。

谁能帮忙解决这个问题?

嗨,我们的代码是这样的。 BOOL InfoDisplayWindow::OnEraseBkgnd(CDC* pDC)

CBitmap m_bitmap; // Offscreen bitmap
CBitmap* m_oldBitmap; // bitmap originally found
CRect m_rect; // Rectangle of drawing area.

HDC hDC = CreateCompatibleDC(pDC->m_hDC);
CDC* pTmpDC = CDC::FromHandle(hDC);
pDC->GetClipBox(&m_rect);
m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_oldBitmap = pTmpDC->SelectObject(&m_bitmap);
pTmpDC->SetWindowOrg(m_rect.left, m_rect.top);

CRect rc;
GetClientRect(&rc);
pTmpDC->FillSolidRect(&rc, COLOR_KEY);

DrawFunction();// Text is displayed in this function

CPen pen(PS_SOLID, SOLID_BORDER_WIDTH, BORDER_COLOR);
CPen *old_pen = pTmpDC->SelectObject(&pen);

// Drawing the 4 boarders of the window here.
pTmpDC->MoveTo(rc.left, rc.bottom - 1);
pTmpDC->LineTo(rc.left, rc.top);
pTmpDC->LineTo(rc.right - 1, rc.top);
pTmpDC->LineTo(rc.right - 1, rc.bottom - 1);
pTmpDC->LineTo(rc.left, rc.bottom - 1);
pTmpDC->SelectObject(old_pen);

// Copy the offscreen bitmap onto the screen.
pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
  pTmpDC, m_rect.left, m_rect.top, SRCCOPY);
//Swap back the original bitmap.
pTmpDC->SelectObject(m_oldBitmap);

return TRUE;

【问题讨论】:

如何创建窗口?它是一个 CDialog,一个 CFormView....你能展示一些代码吗? 您能否edit您的问题并添加一张显示您描述的典型情况的图片? 另外,请提供minimal reproducible example。也许您在问题描述中留下了一些重要的细节,却没有意识到它很重要。 没有理由在OnEraseBkgnd中绘制,正确的方法是在OnPaint中绘制图形。因为你没有提供代码,我只能猜测你有绘图代码OnEraseBkgndOnPaint,需要注意的是,在调用BeginPaint 函数之后,Windows 可能会在BeginPaint 返回之前将WM_ERASEBKGND 消息发送到窗口。这意味着在处理完WM_ERASEBKGND 之后,windows 从BeginPaint 返回并且应用程序在其WM_PAINT 处理程序中的剩余代码被执行。 我已经用我们的代码部分更新了帖子。由于我是新来的,所以无法在这里上传图片。 【参考方案1】:

我假设您从 BeginPaint(或使用 MFC 使用 CPaintDC)或 GetDC 获取您的设备上下文 (DC)。所有这些变体都为您的窗口客户区提供了 DC,其中不包括边框和标题栏。 GetClientRect 返回对应的矩形。 与GetWindowRect对应的是GetWindowDC,它允许在整个区域中绘制。请注意,GetWindowRect 会为您提供屏幕坐标,因此您应该先通过 ScreenToClient 对其进行转换,然后再将它们应用到您的 DC。

【讨论】:

以上是关于有时在绘图期间设备上下文大小会减小的主要内容,如果未能解决你的问题,请参考以下文章

iOS UIView drawRect 调整大小动画

iOS - 图形上下文绘图

canvas 2D绘图

MFC GDI绘图

JS之使用Canvas绘图

WebGL画一个10px大小的点