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 General Discussion » Toolbar not being drawn in "child" CFrameWnd Collapse All
Subject Author Date
Jacquie Howard Aug 14, 2005 - 2:29 PM

Sorry if this comes up twice - the first time it just disappeared!


I am trying to open a new CFrameWnd to display an item from a list exactly as Outlook does when you double-click on an email item in the list.


All works well but it will not draw the toolbar icons.  The buttons on the toolbar are there and react appropriately - it’s just the icons are not drawn.


 


I reproduced the problem by adapting the MDI_InnerOuterBars sample and have included the changes so you can try it.  I also tried a non-Profuis version and the toolbar was fine there.


MDI_InnerOuterBars.cpp:


Replace OnFileNew method with:


void CMDIApp::OnFileNew()


{


/*CMainFrame * pFrame =


STATIC_DOWNCAST(


CMainFrame,


m_pMainWnd


);


// create a new MDI child window


pFrame->CreateNewChild(


RUNTIME_CLASS(CChildFrame),


IDR_MDITYPE,


m_hMDIMenu,


m_hMDIAccel


);*/


CMainFrame* pFrame = STATIC_DOWNCAST(CMainFrame, m_pMainWnd);


ASSERT(RUNTIME_CLASS(CChildFrame) != NULL);


CFrameWnd* pChildFrame = (CFrameWnd*) RUNTIME_CLASS(CChildFrame)->CreateObject();


ASSERT_KINDOF(CFrameWnd, pFrame);


// load the frame


CCreateContext context;


context.m_pCurrentFrame = pFrame;


// pTextFrame->SetHandles(m_hDrawMenu, m_hDrawAccel);


if (!pChildFrame->LoadFrame(IDR_MDITYPE,


WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, &context))


{


TRACE(traceAppMsg, 0, "Couldn’t load frame window.\n");


delete pChildFrame;


}


CString strFullString, strTitle;


if (strFullString.LoadString(IDR_MDITYPE))


AfxExtractSubString(strTitle, strFullString, CDocTemplate::docName);


// redraw the frame and parent


pChildFrame->SetTitle(strTitle);


pChildFrame->InitialUpdateFrame(NULL, TRUE);


}


ChildFrm.h:


Replace "CMDIChildWnd" with "CFrameWnd"


...


// afx_msg void OnWindowPosChanged(WINDOWPOS FAR* lpwndpos);


// afx_msg void OnNcPaint();


...


ChildFrm.cpp:


Replace "CMDIChildWnd" with "CFrameWnd"  throughout


Comment out OnWindowPosChanged and OnNcPaint() methods


Had to comment out the following as it made it crash - any ideas?


/* CExtControlBar::ProfileBarStateLoad(


this,


pApp->m_pszRegistryKey,


pApp->m_pszProfileName,


LPCTSTR( m_sProfileName )


);*/


and


/* VERIFY(


CExtControlBar::ProfileBarStateSave(


this,


pApp->m_pszRegistryKey,


pApp->m_pszProfileName,


LPCTSTR( m_sProfileName )


)


);


g_CmdManager->ProfileWndRemove( GetSafeHwnd() );*/


MainFrm.h:


Replace "CMDIChildWnd" with "CFrameWnd"  throughout


MainFrm.cpp:


Replace "CMDIFrameWnd" with "CFrameWnd"  throughout


 


Your help would be very much appreciated!

Technical Support Aug 15, 2005 - 10:29 AM

The toolbar icons are not visible because the toolbar window is unable to find the command descriptions (including command icons) in the command manager. Typically the main frame window performs the command profile initialization in the OnCreate() method, in which the g_CmdManager->ProfileSetup() or g_CmdManager->ProfileWndAdd() methods are called. The command profile is deinitialized in the DestroyWindow() virtual method of the main frame window, in which where the g_CmdManager->ProfileWndRemove() is called. If the main frame window becomes attached to some named command profile in the command manager, then all the child windows (including toolbars) are able to find command descriptions and draw the command icons. We guess your second frame window that acts like a message view in Outlook does not perform initialization of the command profile. This is the most common source of the problem with invisible toolbar images.

If your application opens more then one "outlook message view" frame, then you may need to create a separate command profile for each running copy of the frame. This command profile should have a unique name to avoid profile allocation/destruction conflicts when open/closing new frames. But all outlook message view frames should save and load the same settings of the command manager. So, you will need to rename the command profile before the GUI state is loaded/saved and assign some statically pre-defined name to it. After the state is loaded/saved. you need to rename the command profile back and assign the unique name to it. Ok, we will guide you step by step how to do this.

static LPCTSTR g_strMessageViewCmdProfile = _T("MessageVew");
 
CMessageViewFrame::CMessageViewFrame()
{
    m_strUniqueCmdProfile.Format( _T("MessageViewFrame-%p"), this );
}
 
int CMessageViewFrame::OnCreate( . . . )
{
    . . .
    VERIFY(
        g_CmdManager->ProfileSetup(
            m_strUniqueCmdProfile,
            m_hWnd
            )
        );
    // update the profile from resources
    // create all the bars, etc
    . . .
    g_CmdManager->SerializeState( 
        m_strUniqueCmdProfile,
        g_strMessageViewCmdProfile
        );
    g_CmdManager->SerializeState(
        pApp->m_pszProfileName,
        pApp->m_pszRegistryKey,
        g_strMessageViewCmdProfile,
        false
        );
    g_CmdManager->SerializeState( 
        g_strMessageViewCmdProfile,
        m_strUniqueCmdProfile
        );
    . . .
}
 
BOOL CMessageViewFrame::DestroyWindow()
{
    . . .
    g_CmdManager->SerializeState( 
        m_strUniqueCmdProfile,
        g_strMessageViewCmdProfile
        );
    VERIFY(
        g_CmdManager->SerializeState(
            pApp->m_pszProfileName,
            pApp->m_pszRegistryKey,
            g_strMessageViewCmdProfile,
            true
            )
        );
    g_CmdManager->SerializeState( 
        g_strMessageViewCmdProfile,
        m_strUniqueCmdProfile
        );
    g_CmdManager->ProfileWndRemove( m_hWnd, true ); 
    . . .
}


As you can see, each of the outlook message view frames opened from the main frame window uses the command profile with a unique name during run time. Many copies of this frame work stably, without conflicts. But the command profile is renamed using the g_strMessageViewCmdProfile string when it is to be loaded or saved. So, all the frames use the same settings in the registry.

Jacquie Howard Aug 15, 2005 - 2:24 PM

Hi,


 


Thanks, that is exactly what I needed.


 


However, these lines do not compile either in "OnCreate" or "DestroyWindow"


    g_CmdManager->SerializeState(
        m_strUniqueCmdProfile,
        g_strMessageViewCmdProfile
        );


...
      g_CmdManager->SerializeState(
        g_strMessageViewCmdProfile,
        m_strUniqueCmdProfile
        );


Please tell me how I can make this work how you intended.


Thanks again.

Technical Support Aug 16, 2005 - 5:39 AM

First of all, we need to clarify the following: we meant that the m_strUniqueCmdProfile variable is a member of your outlook message viewer frame class derived from the CFrameWnd(or CMDIFrameWnd) class. This is a property of the CString type which is initialized with a unique command profile’s name string in the frame’s constructor. Please make sure that it is so. Of course, you can send us your source code and we will help you fix the problem.

Jacquie Howard Aug 16, 2005 - 11:52 AM

 


Yes, thanks, I understood that part.


 


The calls to SerializeState that I said would not compile were having a problem because there weren’t enough parameters.  I think maybe the calls should be to something like "ProfileRename" which has two strings as parameters.

Technical Support Aug 16, 2005 - 12:29 PM

The invocation of the SerializeState() method is correct and has a valid number of parameters. Please let us know what is displayed in the Visual Studio’s Output window. Of course, you can also send us your project so that we can fix the problem.

Jacquie Howard Aug 16, 2005 - 3:02 PM

This is what I get when I try to compile:


d:\Development\Common\FOSS Software\PROF-UIS\Samples\MDI_InnerOuterBars\ChildFrm.cpp(303) : error C2664: ’bool CExtCmdManager::SerializeState(__EXT_MFC_SAFE_LPCTSTR,CArchive &)’ : cannot convert parameter 2 from ’LPCTSTR’ to ’CArchive &’


A reference that is not to ’const’ cannot be bound to a non-lvalue


d:\Development\Common\FOSS Software\PROF-UIS\Samples\MDI_InnerOuterBars\ChildFrm.cpp(313) : error C2664: ’bool CExtCmdManager::SerializeState(__EXT_MFC_SAFE_LPCTSTR,CArchive &)’ : cannot convert parameter 2 from ’CString’ to ’CArchive &’


A reference that is not to ’const’ cannot be bound to a non-lvalue


d:\Development\Common\FOSS Software\PROF-UIS\Samples\MDI_InnerOuterBars\ChildFrm.cpp(368) : error C2664: ’bool CExtCmdManager::SerializeState(__EXT_MFC_SAFE_LPCTSTR,CArchive &)’ : cannot convert parameter 2 from ’LPCTSTR’ to ’CArchive &’


A reference that is not to ’const’ cannot be bound to a non-lvalue


d:\Development\Common\FOSS Software\PROF-UIS\Samples\MDI_InnerOuterBars\ChildFrm.cpp(380) : error C2664: ’bool CExtCmdManager::SerializeState(__EXT_MFC_SAFE_LPCTSTR,CArchive &)’ : cannot convert parameter 2 from ’CString’ to ’CArchive &’


A reference that is not to ’const’ cannot be bound to a non-lvalue


 


The code I am using is MDI_InnerOuterBars with the changes I made as explained before, plus the changes you gave me.


 


Thank you for your continued support!

Technical Support Aug 17, 2005 - 5:48 AM

There are two overloaded SerializeState() methods in the CExtCmdManager class:

    bool SerializeState(
        __EXT_MFC_SAFE_LPCTSTR sProfileName,
        __EXT_MFC_SAFE_LPCTSTR sSectionNameCompany,
        __EXT_MFC_SAFE_LPCTSTR sSectionNameProduct,
        bool bSave
        );
    bool SerializeState(
        __EXT_MFC_SAFE_LPCTSTR sProfileName,
        CArchive & ar
        );


We just need to make C++ compiler forget about the second method and use first. Please decorate all the values with the explicit LPCTSTR() conversion:
    g_CmdManager->SerializeState(
        LPCTSTR( variable name or _T("...") value ),
        LPCTSTR( variable name or _T("...") value ),
        LPCTSTR( variable name or _T("...") value ),
        true or false
        );

Jacquie Howard Aug 17, 2005 - 11:31 AM

I think we are talking at cross purposes here.


This is the sequence of calls you gave me before:


 


  g_CmdManager->SerializeState(
        m_strUniqueCmdProfile,
        g_strMessageViewCmdProfile
        );
    g_CmdManager->SerializeState(
        pApp->m_pszProfileName,
        pApp->m_pszRegistryKey,
  g_strMessageViewCmdProfile,
        false/true
        );
    g_CmdManager->SerializeState(
        g_strMessageViewCmdProfile,
        m_strUniqueCmdProfile
        );

Technical Support Aug 17, 2005 - 11:52 AM

We are sorry for the typo. The first and last invocations are really ProfileRename() invocations:

    g_CmdManager->ProfileRename( // NOT SerializeState() !
        m_strUniqueCmdProfile,
        g_strMessageViewCmdProfile
        );
    g_CmdManager->SerializeState(
        pApp->m_pszProfileName,
        pApp->m_pszRegistryKey,
        g_strMessageViewCmdProfile,
        false/true
        );
    g_CmdManager->ProfileRename( // NOT SerializeState() !
        g_strMessageViewCmdProfile,
        m_strUniqueCmdProfile
        );

Jacquie Howard Aug 17, 2005 - 12:53 PM

Thanks again!


It’s working just how I want it now!