Professional UI Solutions
Site Map   /  Register
 
 

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.

Forums » Prof-UIS Tech Support » WM_PRINTCLIENT not received in CExtLabel-derived class Collapse All
Subject Author Date
Suhai Gyorgy Dec 22, 2006 - 8:13 AM

Dear Support,

As I already mentioned in the past, I’m making a kind of FormEditor, heavily based on your FormEditor sample. You’ve already helped me a great deal with proper painting of the controls, and now with your classes and their handling of WM_PRINTCLIENT message my application works really nice.

I have a control of my own, a kind of Picture control which can present not just ico and bmp files, but also jpg and gif files. In my class I have handled the WM_PRINTCLIENT message to have the control properly drawn on the form, the handler works much the same as the handler for WM_PAINT message. In earlier versions of your PrintClient solution, this worked nicely, I received the message and handled it just fine. But now as I’ve tested my application overall, I realised that my control is not getting the message anymore. Do you suppress this message somewhere in your CExtLabel code or have I changed something in the meanwhile that could prevent the message to reach my control? I’ll try to insert this class in your FormEditor sample to see if the problem is on my side, I was just hoping in the meanwhile you could come up with something obvious I’m missing.

Thank you,
Chris.

Technical Support Dec 22, 2006 - 11:54 AM

We guess the problem is caused by how the WM_PRINT/WM_PRINTCLIENT messages are handled in the CExtLabel class. It simply does not print out its child windows. We fixed this. Please update the following method:

LRESULT CExtLabel::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
#if (defined WM_UPDATEUISTATE)    
    ASSERT( WM_UPDATEUISTATE == 0x0128 );
#endif
    if( message == 0x0128 )
        return 0;
    if(    message == WM_ENABLE )
    {
        LRESULT lResult = CStatic::WindowProc(message, wParam, lParam);
        Invalidate();
        UpdateWindow();
        return lResult;
    }
    if( message == WM_PRINT || message == WM_PRINTCLIENT )
    {
        CDC * pDC = CDC::FromHandle( (HDC)wParam );
        CRect rcClient;
        GetClientRect( &rcClient );
        DoPaint( pDC, rcClient );
        HWND hWndChild = ::GetWindow( m_hWnd, GW_CHILD );
        for( ; hWndChild != NULL; hWndChild = ::GetWindow( hWndChild, GW_HWNDNEXT ) )
        {
            DWORD dwChildStyle = ::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);
    }    
    if(     message == WM_SETTEXT 
        ||  message == WM_GETTEXT 
        ||  message == WM_GETTEXTLENGTH 
        )
    {
        DWORD dwWndStyle = GetStyle();
        DWORD dwWndType = (dwWndStyle&SS_TYPEMASK);
        if(     dwWndType == SS_BLACKRECT 
            ||  dwWndType == SS_GRAYRECT 
            ||  dwWndType == SS_WHITERECT 
            ||  dwWndType == SS_BLACKFRAME 
            ||  dwWndType == SS_GRAYFRAME 
            ||  dwWndType == SS_WHITEFRAME 
            ||  dwWndType == SS_USERITEM 
            ||  dwWndType == SS_OWNERDRAW 
            ||  dwWndType == SS_BITMAP 
            ||  dwWndType == SS_ICON
            ||  dwWndType == SS_ENHMETAFILE 
            ||  dwWndType == SS_ETCHEDHORZ 
            ||  dwWndType == SS_ETCHEDVERT 
            ||  dwWndType == SS_ETCHEDFRAME 
            )
            return CStatic::WindowProc( message, wParam, lParam );
 
        LRESULT lResult = FALSE;
        if(     (!m_bInitText)
            &&  (message == WM_GETTEXT || message == WM_GETTEXTLENGTH)
            )
        {
            lResult = CStatic::WindowProc( message, wParam, lParam );
            INT nMaxLength = 0;
            if( message != WM_GETTEXTLENGTH )
            {
                WPARAM wParamLocal = 0L;
                LPARAM lParamLocal = 0L; 
                nMaxLength = (INT)
                    CStatic::WindowProc( 
                        WM_GETTEXTLENGTH, 
                        wParamLocal, 
                        lParamLocal 
                        );
            }
            else
                nMaxLength = (INT)lResult;
            CString sTextInit;
            CStatic::WindowProc( 
                WM_GETTEXT, 
                nMaxLength + 1, 
                (LPARAM)sTextInit.GetBuffer( nMaxLength + 1 ) 
                );
            sTextInit.ReleaseBuffer();
            m_sText = sTextInit;
            m_bInitText = true;
            return lResult;
        }
        if( message == WM_SETTEXT )
        {
            LPCTSTR lpszText = (LPCTSTR)lParam;
            m_sText = lpszText;
            m_bInitText = true;
            RedrawWindow(
                NULL, NULL,
                RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ERASENOW
                );
            lResult = TRUE;
        }
        else if( message == WM_GETTEXT )
        {
            TCHAR * lpszText = (TCHAR *)lParam;
            ::memset( lpszText, 0, wParam );
            __EXT_MFC_STRNCPY(
                lpszText,
                wParam,
                m_sText,
                wParam - 1
                );
            lpszText[ wParam - 1 ] = _T(’\0’);
            lResult = TRUE;
        }
        else if( message == WM_GETTEXTLENGTH )
        {
            lResult = m_sText.GetLength();
        }
        return lResult;
    }
    return CStatic::WindowProc(message, wParam, lParam);
}



Suhai Gyorgy Jan 2, 2007 - 6:58 AM

I wasn’t clear in my first post: My Picture control is a class derived from CExtLabel, not a child of a CExtLabel object. So your fix didn’t solve my problem.

I solved the problem by overriding WindowProc, catching WM_PRINT and WM_PRINTCLIENT messages and doing all rendering there.

But I’m still interested why my original idea didn’t work. I made a function afx_msg LRESULT OnPrintClient(WPARAM wParam, LPARAM lParam); and had the lines ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient) and ON_MESSAGE(WM_PRINT, OnPrintClient) in the message map. But OnPrintClient function never got called. What could be the reason for that? Do I have to call some other macro in the message map instead of ON_MESSAGE? I also have ON_WM_PAINT in the same message map and that works just fine.

By the way: Happy New Year! :)

Technical Support Jan 5, 2007 - 9:03 AM

The OnPrintClient() method does not work because WindowProc() method is invoked earlier and MFC has no chances to process the message map entries. So when some message is handled in the WindowProc(), the corresponding entry in the message map is not processed. You can insert the following lines into your overridden WindowProc() method so the ON_MESSAGE macro can work:

LRESULT CYourLabel::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
   ...
    if( message == WM_PRINT || message == WM_PRINTCLIENT )
        return CStatic::WindowProc(message, wParam, lParam);
    ...
}
We wish you a Happy New Year too, Chris. Thank you for all your help.