0

We have an application in MFC.

We have come across an issue with device context. The situation is like - we have an info display window, which is variable in size and posiion. During some size and position changing scenarios, only part of the window is drawn, like a portion of the window is cut.

We doubted there is difference between the rect in device context and the rect returned from GetWindowRect function. So we have logged and checked the size of the window rect which is being drawn from the device context and also the window rect of memory DC which is used for drawing during the issue scenario.

But both returned the small window rect size. That is device context has only the partial information of the rect at that time.

  • We didn't called UpdateWindow() or Invalidate().
  • When we focused the window using WinSpy, the whole window is present, but only that small portion is drawn.
  • We placed and then removed another window above this window to check whether any repainting would happen. But still the issue persists.

Can anyone please help rectify this problem?

hi, our code is like this.
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;

}

Dinu
  • 11
  • 2
  • How you create your window ? is it a CDialog, a CFormView.... can you show some parts of code ? – Landstalker Feb 13 '20 at 15:02
  • Could you [edit] your question and add a picture that shows the typical situation you describe? – Jabberwocky Feb 13 '20 at 15:30
  • Also, please do provide a [mcve]. Maybe there is some significant detail you left from your problem description without realizing that it is significant. – IInspectable Feb 13 '20 at 15:57
  • Just a guess - do you have a child window that is supposed to be resized to its parent but is not getting resized? (basing it on a fact that `GetWindowRect` is smaller than you expected) – Vlad Feinstein Feb 13 '20 at 20:01
  • @Landstalker The window is derived from CDialog. I couldnt upload images. – Dinu Feb 14 '20 at 04:49
  • One thing is that OnPaint() is not overrided in this scenario and drawing is done in OnEraseBkgnd(). When we overrided and moved the drawing logic to OnPaint() the isssue seems to be solved. But without the valid reason we couldnt change the code in the production line. – Dinu Feb 14 '20 at 05:01
  • 1
    There is no reason to draw in `OnEraseBkgnd`, the correct method is to draw the graphics in `OnPaint`.Because you did not provide the code, I can only guess that you have drawing codes in both `OnEraseBkgnd` and `OnPaint`, and what needs to be noted is after the `BeginPaint` function has been called that Windows may send the `WM_ERASEBKGND` message to the window before `BeginPaint` returns. This means that after `WM_ERASEBKGND` has been handled that windows returns from `BeginPaint` and the application's remaining code in its `WM_PAINT` handler is executed. – Strive Sun Feb 14 '20 at 06:54
  • 1
    I have updated the post with our code portion. Since I am a new comer here i am not able to upload images here. – Dinu Feb 17 '20 at 06:33
  • You said that both returned the small window rect size, which means the client area?After my test, the values of `m_rect` and `rc` are the same. And when use FillRect api ,it can draw the whole client area. Here is a [gif](https://i.stack.imgur.com/GmzL3.gif) for your reference. – Strive Sun Feb 18 '20 at 03:47

1 Answers1

0

I assume you get your device context (DC) either from BeginPaint (or using MFC using a CPaintDC) or from GetDC. All these variants give you the DC for your window's client area, which doesn't include the border and title bar. The corresponding rect is returned by GetClientRect. Corresponding to GetWindowRect is GetWindowDC, which allows to draw in the full area. Be aware that GetWindowRect gives you screen coordinates, so you should transform them by ScreenToClient before applying them to your DC.

Nick
  • 472
  • 3
  • 18