I thought that the “working” animation, like seen on smart phones and other similar devices, was neat showing up in the middle of my auto email program window but it didn’t look so good when the window is huge and when the window is full of status text.

I decided to move it to the status bar.

Don’t use a CWnd object created in the main GUI thread in any other thread. This works fine quite often but one simple change can cause assertion failures to start showing up. They are hard to track down. The eventual cause of the problems are that the CWnd object has stuff in it that is thread-local, or some such thing.

I changed my code to do create a status bar with two panes instead of one. Below is that code with unrelated code removed:

static UINT indicators[] = 
{ 
    ID_SEPARATOR, 
    ID_SEPARATOR 
}; 

if (!m_wndStatusBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM)) 
{ 
    TRACE0("Failed to create status bar\n"); 
    return -1;      // fail to create 
} 
CStatusBarCtrl &Temp = m_wndStatusBar.GetStatusBarCtrl(); 
Temp.SetMinHeight( 28 ); 
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)); 
m_wndStatusBar.SetPaneInfo( 0, ID_SEPARATOR, SBPS_NOBORDERS, 28 ); 
m_wndStatusBar.SetPaneInfo( 1, ID_SEPARATOR, SBPS_NOBORDERS | SBPS_STRETCH, 0 );

Once I had the status bar showing up with two panes, I had to call SetPaneText() instead of SetWindowText(). That is when I started to see assertion failures. There is some odd COM code in the MFC library code that doesn’t cause a problem for SetWindowText() but does cause a problem for SetPaneText().

After a complete rewrite of my status management system to send messages to the main window and update the child windows from there, things worked fine.

I added this code to the main window initialization code just after the code shown above and now my animation shows up in the status bar:

CRect Rect( 0, 0, 0, 0 ); 
m_StatusAnimationControl.Create( WS_CHILD | ACS_TRANSPARENT | ACS_CENTER,
                                 Rect, &m_wndStatusBar, 121212 ); 
m_StatusAnimationControl.ShowWindow( SW_HIDE ); 
m_StatusAnimationControl.Open( IDR_AVI2 );

I also had to add an OnSize() handler for the main window so that I could get the rectangle for the first pane of the status window and then set the position of the animation control appropriately. The rectangle is not correct at the time of initialization but it is correct later once the window gets a WM_SIZE message.

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
    CFrameWnd::OnSize(nType, cx, cy);

    CRect Rect;
    m_wndStatusBar.GetItemRect( 0, &Rect );
    m_StatusAnimationControl.SetWindowPos( 0, Rect.left, Rect.top, 
                                           Rect.Width(), Rect.Height() - 3, SWP_NOZORDER ); 
}

emailer-working

This is a little less cool in some ways but a little better in many others. Plus, working on this code made me fix the problem with multiple threads touching GUI components like the CMainFrame object.