Forum
Please
Log In
to post a new message or reply to an existing one. If you are not registered, please
register.
NOTE: Some forums may be read-only if you are not currently subscribed to
our technical support services.
Subject |
Author |
Date |
|
Bart Kampers
|
Jan 23, 2009 - 2:41 AM
|
Hello, I derived a custom control from CWnd. I override OnEraseBkgnd and OnPaint to do my own drawings. When I use this control in an ordinary MFC application it has a transparent background. But when I use it in a Prof-UIS application the background is white. How can I have a transparent background in Prof-UIS also? Kind regards, Bart.
|
|
Carsten Pedersen
|
Feb 20, 2012 - 6:50 AM
|
Hi - I have implemented this functionality into my custom control, and it works great. Since my dialog application is non-resizable I don’t have a problem with the custom control not being derived from CExtResizableDialog. However, if I choose to make a resizable dialog, then I reckon I must derive all controls from the CExtResizableDialog ? And then we have the ::OnPaint problem again, with the CPaintDC I assume?
Best regards,
Carsten Pedersen
|
|
Technical Support
|
Feb 21, 2012 - 2:23 AM
|
The resizable dialog behavior is not a problem. The CExtPaintManager::PaintDockerBkgnd() method provides a themed background to any control at any nested level. The background content is drawn using the dialog coordinate system. The dialog size is not important.
|
|
Carsten Pedersen
|
Feb 22, 2012 - 2:12 AM
|
Hi, I think you misunderstood; If I derive a control from CExtResizableDialog, then the ::OnPaint method will not work with the CPaintDC, and thus flickering will occur. If I derive from CWnd, then it will work as described below. But then it won’t be resizable using ProfUIS methods, will it?
|
|
Technical Support
|
Feb 23, 2012 - 2:16 AM
|
The CExtResizableDialoig class handles the WM_PAINT message in the WindowProc() virtual method. Please override the WindowProc() method in your dialog class and implement painting code here.
#if (!defined __EXT_MEMORY_DC_H)
#include <../Src/ExtMemoryDC.h>
#endif
. . .
virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
if( message == WM_PAINT )
{
CPaintDC dcPaint( this );
CRect rcClient;
GetClientRect( &rcClient );
CExtMemoryDC dc( &dcPaint, &rcClient );
COLORREF clrBackground = GetBkColor();
bool bTransparent = false;
if( PmBridge_GetPM()->GetCb2DbTransparentMode(this) && ( clrBackground == COLORREF(-1L) ) )
{
CExtPaintManager::stat_ExcludeChildAreas( dc, GetSafeHwnd(), CExtPaintManager::stat_DefExcludeChildAreaCallback );
if( PmBridge_GetPM()->PaintDockerBkgnd( true, dc, this ) )
bTransparent = true;
if( ( ! bTransparent) && clrBackground != COLORREF(-1L) )
dc.FillSolidRect( &rcClient, clrBackground );
}
//
//
// draw custom things into dc here (not into dcPaint)
//
//
PmBridge_GetPM()->OnPaintSessionComplete( this );
return __super::WindowProc( message, wParam, lParam );
}
|
|
Technical Support
|
Jan 26, 2009 - 11:40 AM
|
The code snippet in your message looks incorrectly formatted or as a result of incorrect copy or paste. We can’t understand which of lines in it are those relevant last 3 lines.
|
|
Technical Support
|
Jan 23, 2009 - 12:44 PM
|
All the Prof-UIS controls are written with care to flicker free painting. All the container windows in Prof-UIS are created with the WS_CLIPSIBLINGS | WS_CLIPCHILDREN window styles and we strongly recommend to set these styles in all your dialog template resources. So, your window should simply return TRUE from the WM_ERASEBKGND message handler. The WM_PAINT message handler should look like this:
#if (!defined __EXT_MEMORY_DC_H)
#include <../Src/ExtMemoryDC.h>
#endif
void CYourWnd::OnPaint()
{
ASSERT_VALID( this );
CPaintDC dcPaint( this );
CRect rcClient;
GetClientRect( &rcClient );
if( rcClient.IsRectEmpty() )
return;
CExtMemoryDC dc( &dcPaint, &rcClient );
DrawEntireYourWnd( dcPaint, rcClient );
}
Where the DrawEntireYourWnd() method looks like: void CYourWnd::DrawEntireYourWnd( CDC & dc, CRect rcClient )
{
ASSERT_VALID( this );
DrawBackgroundOfYourWnd( dcPaint, rcClient );
DrawContentOfYourWnd( dcPaint, rcClient );
}
Where the DrawBackgroundOfYourWnd() and DrawContentOfYourWnd() methods look like: void CYourWnd::DrawBackgroundOfYourWnd( CDC & dc, CRect rcClient )
{
ASSERT_VALID( this );
bool bThemedBackgroundPainted = false;
if( g_PaintManager->GetCb2DbTransparentMode(this)
&& g_PaintManager->PaintDockerBkgnd( true, dc, this )
)
bThemedBackgroundPainted = true;
if( ! bThemedBackgroundPainted )
dc.FillSolidRect( &rcClient, g_PaintManager->GetColor( CExtPaintManager::CLR_3DFACE_OUT, this ) );
}
void CYourWnd::DrawContentOfYourWnd( CDC & dc, CRect rcClient )
{
ASSERT_VALID( this );
//
// TO-DO: draw content of your window here
//
}
But the good implementation of custom control should also handle surface printing. LRESULT CYourWnd::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
if( message == WM_PRINT || message == WM_PRINTCLIENT )
{
CDC * pDC = CDC::FromHandle( (HDC)wParam );
CRect rcClient;
GetClientRect( &rcClient );
DrawEntireYourWnd( pDC, rcClient );
HWND hWndChild = ::GetWindow( m_hWnd, GW_CHILD );
for( ; hWndChild != NULL; hWndChild = ::GetWindow( hWndChild, GW_HWNDNEXT ) )
{
__EXT_MFC_LONG_PTR dwChildStyle = ::__EXT_MFC_GetWindowLong( hWndChild, GWL_STYLE );
if( ( dwChildStyle & WS_VISIBLE ) == 0 )
continue;
CRect rcChildWnd, rcChildClient, rcStartClient;
::GetClientRect( m_hWnd, &rcStartClient );
::ClientToScreen( hWndChild, ((LPPOINT)(&rcStartClient)) );
::ClientToScreen( hWndChild, ((LPPOINT)(&rcStartClient))+1 );
::GetWindowRect( hWndChild, &rcChildWnd );
::GetClientRect( hWndChild, &rcChildClient );
::ClientToScreen( hWndChild, ((LPPOINT)(&rcChildClient)) );
::ClientToScreen( hWndChild, ((LPPOINT)(&rcChildClient))+1 );
CPoint ptChildRenderOffset( 0, 0 );
if( ( lParam & PRF_NONCLIENT ) != 0 )
{
ptChildRenderOffset.x = rcStartClient.left - rcChildWnd.left;
ptChildRenderOffset.y = rcStartClient.top - rcChildWnd.top;
}
else
{
ptChildRenderOffset.x = rcStartClient.left - rcChildClient.left;
ptChildRenderOffset.y = rcStartClient.top - rcChildClient.top;
}
if( ptChildRenderOffset.x != 0 || ptChildRenderOffset.y != 0 )
::OffsetViewportOrgEx( pDC->m_hDC, -ptChildRenderOffset.x, -ptChildRenderOffset.y, NULL );
::SendMessage( hWndChild, message, (WPARAM)pDC->m_hDC, lParam );
if( ptChildRenderOffset.x != 0 || ptChildRenderOffset.y != 0 )
::OffsetViewportOrgEx( pDC->m_hDC, ptChildRenderOffset.x, ptChildRenderOffset.y, NULL );
}
return (!0);
}
return C_BASE_OF_YourWnd::WindowProc( message, wParam, lParam );
}
You may also need to re-paint your window when the WM_ACTIVATE , WM_NCACTIVATE , WM_ACTIVATEAPP , WM_ENABLE and/or WM_SETTEXT messages received.
|
|
Bart Kampers
|
Jan 26, 2009 - 1:49 AM
|
Thanks for reply. I implemented my control almos as you described except for the DrawBackgroundOfYourWnd part. So I added this piece and my OnPaint now looks like the code below. I noticed that when I leave the last three statements out the background is transparents. When I then add the "CExtMemoryDC memDC(&paintDC);" statement again the background turns white.
void
CClock::OnPaint()this);this); // device context for painting
CRect rcClient;
GetClientRect(&rcClient);
{
{
bThemedBackgroundPainted =
}
{
paintDC.FillSolidRect(&rcClient, g_PaintManager->GetColor(CExtPaintManager::CLR_3DFACE_OUT,
}
CExtMemoryDC memDC(&paintDC);
Graphics graphics(memDC);
Paint(graphics);
}
} if (! rcClient.IsRectEmpty()) bool bThemedBackgroundPainted = false; if (g_PaintManager->GetCb2DbTransparentMode(this) && g_PaintManager->PaintDockerBkgnd(true, paintDC, this))true; if(! bThemedBackgroundPainted)this)); { ASSERT_VALID( CPaintDC paintDC(
|
|
Bart Kampers
|
Jan 27, 2009 - 1:37 AM
|
I’m sorry for the unreadable snippet. Here it is again: void CClock::OnPaint()
{
ASSERT_VALID(this);
CPaintDC paintDC(this); // device context for painting
CRect rcClient;
GetClientRect(&rcClient);
if (! rcClient.IsRectEmpty())
{
bool bThemedBackgroundPainted = false;
if (g_PaintManager->GetCb2DbTransparentMode(this) && g_PaintManager->PaintDockerBkgnd(true, paintDC, this))
{
bThemedBackgroundPainted = true;
}
if(! bThemedBackgroundPainted)
{
paintDC.FillSolidRect(&rcClient, g_PaintManager->GetColor(CExtPaintManager::CLR_3DFACE_OUT, this));
} CExtMemoryDC memDC(&paintDC);
Graphics graphics(memDC);
Paint(graphics);
}
}
|
|
Technical Support
|
Jan 27, 2009 - 11:36 AM
|
The CExtMemoryDC object should be initialized immediately after the CPaintDC object because the themed background should be painted into CExtMemoryDC . We recommend you invoke the GdiFlush() API before initializing the Graphics object.
|
|