0

I have a simple MFC application which draws an ellipse when user left clicks on it. I want to draw a colored ellipse instead of one with a white background. Here are my OnEraseBkgnd() and OnLButtonDown() handlers

HBRUSH NewBrush;
BOOL CMainWindow::OnEraseBkgnd(CDC *pDC){
    NewBrush = CreateSolidBrush(RGB(0, 0, 250));
    auto res = SelectObject(HDC(*pDC),NewBrush);

    if(res==NULL||ERROR(res))
    {
        MessageBox("SelectObject error");
    }

    return CFrameWnd::OnEraseBkgnd(pDC); //I have tried return 0, and return 1 as well.
}

void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point){

    CClientDC dc(this);   
    dc.Ellipse(0,0,100,50);
}

I expect a blue ellipse to be drawn, but only a white ellipse gets drawn.

enter image description here

If I do select object in OnLButtonDown() the ellipse is drawn in blue.

void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point){
   CClientDC dc(this);
   NewBrush = CreateSolidBrush(RGB(0, 0, 250));
   SelectObject(HDC(dc),NewBrush);
   dc.Ellipse(0,0,100,50);
}

enter image description here

What I don't understand is how that the effect of SelectObject() should be the same, no matter where I do it, as long as I am drawing the ellipse after doing SelectObject(). Since the brush gets attached to the device context, which is a property of my application window. Hence once set should retain its value while the application is running.

Sahil Singh
  • 3,352
  • 39
  • 62
  • 4
    Fairly misguided implementation based on several unfounded assumptions. `1` Objects selected into a DC can be used throughout the lifetime of the DC. `2` Do not make assumptions about the lifetime of DC's you did not create. `3` Do not leave objects selected into DC's when they potentially get destroyed. `4` Do not render in response to any message other than `WM_PAINT`. If you need to trigger a repaint, call `CWnd::Invalidate()` (or similar). `5` The brush used to erase the background of a window is set during window class registration. – IInspectable Feb 28 '17 at 10:13
  • "Fairly misguided implementation based on several unfounded assumptions" - agreed. I am new to MFC, and would like to get rid of these unfounded assumptions. – Sahil Singh Feb 28 '17 at 11:08
  • About the life time of DC, I printed dc.GetSafeHdc(), and pDC->GetSafeHdc() they both have same value, pointing to the fact that the device contexts are same. Also, a DC and an application window must have a 1:1 correspondence, and a DC should be same throughout the life of the window, much like a process ID is to a process. – Sahil Singh Feb 28 '17 at 11:11
  • 1
    Mandatory reading: [Programming Windows with MFC, Second Edition](https://www.amazon.com/dp/1572316950). Also see [Prerequisites for learning MFC programming(http://stackoverflow.com/q/18165076/1889329). – IInspectable Feb 28 '17 at 11:12
  • As for your point number 5 - the brush used to erase the background is set during window class registration, I would suggest you to have a look at https://msdn.microsoft.com/en-us/library/dd145204(VS.85).aspx and http://stackoverflow.com/a/3463529/7110489 – Sahil Singh Feb 28 '17 at 11:15
  • 1
    Like every other handle type, handle values do get reused. The fact that two objects have the same value at different times does not imply object identity. And even if the objects were the same, the associated state likely isn't (the DC passed to the `WM_PAINT` handler comes with properly set up clipping, for example). At any rate, just perform all your rendering in response to `WM_PAINT`, and you won't have to rely on circumstantial evidence. – IInspectable Feb 28 '17 at 11:16
  • @SahilSingh: No. There no such 1:1 relation of DCs and windows. One DC may be used to update more than one window. And no. The DC is not the same through the lifetime of a window. Only if use use the class style CS_OWNDC this is guarantied. But I never would advise someone to use CS_OWNDC. – xMRi Feb 28 '17 at 11:16
  • Both of the links you posted agree with me: The brush used to erase the background is set during class registration. Which just goes on to prove again: One cannot safely use MFC without **intimate** familiarity with the Windows API. – IInspectable Feb 28 '17 at 11:21
  • Will CS_OWNDC, or CS_CLASSDC make any difference? I read that when using these window styles the OS maintains a single DC for an application, hence any change made at any point to the DC should be persistent. I tried for a POC but failed. I was hoping that setting the window style to either of the two will change ellipse's color when brush is set in OnEraseBkgnd(). Alas, I got the same result. – Sahil Singh Mar 15 '17 at 12:09
  • Can you explain why you're trying to set up the drawing state in OnEraseBkgnd and actually draw in OnLButtonDown? Is there something you're trying to accomplish that cannot be done by drawing in OnPaint? – Adrian McCarthy Mar 24 '17 at 21:32
  • @AdrianMcCarthy As you can see my knowledge of GDI, and MFC is limited. The problem is compounded by lack of/ambiguous documentation on MSDN. I am trying to understand these concepts. My earlier understanding was that like a program ID, a Device context associated with a window lives through its life, and is constant. To test this hypothesis I wrote the above code. Had it been the case, I would have seen same color in both the ellipses. – Sahil Singh Mar 30 '17 at 12:42

0 Answers0