I'm currently trying to draw something outside OnPaint function. I know there are many duplicate questions on the internet, however, I failed to get any of them to work. This is entirely because of my lack of understanding of MFC.
What works inside OnPaint:
CDC* pDC = GetDC();
HDC hDC = pDC->GetSafeHdc();
CRect lDisplayRect;
GetDlgItem(IDC_DISPLAYPOS)->GetClientRect(&lDisplayRect);
GetDlgItem(IDC_DISPLAYPOS)->ClientToScreen(&lDisplayRect);
ScreenToClient(&lDisplayRect);
pDC->FillSolidRect(&lDisplayRect, GetSysColor(COLOR_3DDKSHADOW));
pDC->TextOutW(300, 300, TEXT("test"));
It fills the area of the button control I have with a defined colour. And it prints out the "test" string without any issue.
But it won't work outside OnPaint.
I've seen numerous suggestions such as using CmemDC,CPaintDC, etc But none of them worked outside OnPaint.
For example,
CClientDC dc(this);
dc.rectangle( ....);
does not work.
Please note that this is a temporary test code and what I am eventually trying to do is draw incoming frames from a frame grabber within my display thread (a separate thread from the main UI thread) on the DisplayPos area and my dlg object(the dialog) owns an instance of the DisplayThread class. And I'm passing HWND and displayrect upon creating the member mDisplayThread so I can draw stuff within the display thread and that's the reason why I need to be able to draw to DC outside OnPaint (DisplayThread class does not have OnPaint or inherit any class that has it).
I'm in dire need of help...Please help!
Added: I have overridden PreTranslateMessage(MSG* pMsg) and made it return without calling the default function just in case WM_ERASE msg is erasing everything, but this approach didn't work either.
CodePudding user response:
Two important suggestions:
Do not draw outside of
OnPaint
. The content may be erased or painted over at the direction of OS.Do not draw on the dialog surface. First, it is not designed for that. It may be affected by other controls or by theming, skinning, etc. Just create a window with your own window procedure, so you are in control.
I would store the information needed for drawing in you frame grabber
, and cause an immediate window painting by calling RedrawWindow
CodePudding user response:
For example:
void CMFCApplicationDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
HDC hdc = ::GetDC(m_hWnd);
Ellipse(hdc, point.x - 10, point.y - 10, point.x 10, point.y 10);
::ReleaseDC(m_hWnd, hdc);
CDialogEx::OnLButtonDown(nFlags, point);
}