CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Sep 2012
    Posts
    25

    Problem with CStatusBar panes in Windows 7

    * Development System: WinXP SP3
    * Development Environment: MS VC++ 6.0 SP6
    * Program is statically linked.

    It's kind of a long-winded post but I wanted to present as much information as I could.

    Here is the basic problem. In Win7 (and probably Vista) my status bar panes are not always displaying their text. The problem may also exist in other Windows OSs but never noticed.

    I have a program that I've maintained for 10 years. Through the yearss it has been updated for capability and to make sure it runs on the all Windows platforms through Win7.

    In all this time it has had the same status bar derivecd from MFC's CStatusBar. It has always had five panes of text. Pane 0 is the normal status pane used for displaying the normal 'status' text. The other four panes are for displaying program settings that the user selects. I know it doesn't matter much, but examples of pane 3 text are "NONE", "COM1", "GPIB0", and "PL89".

    The status bar panes 1, 2, 3, and 4 have displayed their text just fine through WinXP. But Win7 (and I presume Vista) is DRIVING ME NUTS! Panes 2, 3, and 4 are sometimes cleared and display no text at all. Pane 1 appears to be OK but its text never changes. Pane 1 text is always "RAW", but the text can be normal or dimmed according to a user selectable option.

    I will describe pane 3 because it seems to give me the most problems. I'll also leave out most of the error checking in the code snippets below to simplify things.

    The status bar is created with:

    m_cStatusBar.Create (this);
    m_cStatusBar.SetIndicators (indicator info goes here);

    Pane 3 is initialized like this (the other panes are the same):

    nIndex = m_cStatusBar.CommandToIndex (ID_INDICATOR_3);
    m_cStatusBar.GetPaneInfo (nIndex, uID, uStyle, nWidth);
    m_cStatusBar.SetPaneInfo (nIndex, uID, uStyle | SBT_OWNERDRAW, nWidth);

    The status bar panes are owner-drawn, mostly so I can select the color for the pane and center the text in the pane. Here is the DrawItem() function in a nutshell:

    void CStatusBarBmp:rawItem (LPDRAWITEMSTRUCT pstDrawItemStruct)
    {
    //get pane's text
    nItemID = static_cast<INT>(pstDrawItemStruct->itemID);
    GetPaneText (nItemID, cszPaneText);

    //set pane's background and foreground colors
    cDC.Attach (pstDrawItemStruct->hDC);
    cDC.SetBkColor (::GetSysColor (COLOR_BTNFACE));
    if (m_abEnabled [nItemID])
    dwTextColor = ::GetSysColor (COLOR_BTNTEXT);
    else
    dwTextColor = ::GetSysColor (COLOR_GRAYTEXT);
    cDC.SetTextColor (dwTextColor);

    //draw centered text in the pane
    cRect (&pstDrawItemStruct->rcItem);
    cDC.DrawText (cszPaneText, cRect, DT_CENTER);
    cDC.Detach();
    }

    I use CStatusBar::SetPaneText() to initially write text to the panes. I'm not sure that the CStatusBar::SetPaneText() is needed. In my CMDIFrameWnd derived main frame I use ON_UPDATE_COMMAND_UI commamnd handlers to write the text during idle time. For example:

    ON_UPDATE_COMMAND_UI(ID_INDICATOR_3, OnUpdateIndicator3)

    void CMainFrame::OnUpdateIndicator3 (CCmdUI* pCmdUI)
    {
    pCmdUI->Enable (TRUE);
    pCmdUI->SetText (pane text goes here);
    }

    During my tests it apears that the ON_UPDATE_COMMAND_UI handlers in WinXP are NOT really need. But it also appears that they ARE needed in Win7. It also appears that in Win7 the panes display correctly in _DEBUG builds but have problems in RELEASE builds. I've also noted that in Win7 if the pane is cleared I can get the pane text to display again if I either resize the main frame or cover/uncover the pane with another program.

    Here is the worst possible situation. Sometimes, if the panes are cleared during operation I can simply restart the program and they might work.

    So here is my current code:

    1. Use CStatusBar::SetPaneText().
    2. Use CStatusBar:rawItem().
    3. Use CMainFrame::OnUpdateIndicatorX()

    I ran across this quote someplace on the 'net (CAPS emphasis is mine:

    "The SetText approach is recommended. It is possible to perform this task at a slightly lower level by calling the CStatusBar member function SetPaneText. Even so, you still need an update handler. Without such a handler for the pane, MFC AUTOMATICALLY DISABLES THE PANE, ERASING ITS CONTENT."

    What the Hell do they mean "MFC AUTOMATICALLY DISABLES THE PANE, ERASING ITS CONTENT"?

    Anybody have any idea what I can do to get the status bar panes working reliably in Win7?

    Thanks,
    Mike

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Problem with CStatusBar panes in Windows 7

    Try to call
    Code:
    	InvalidateRect(rectPane);
    	UpdateWindow();
    after updating pane text or image.
    Victor Nijegorodov

  3. #3
    Join Date
    Sep 2012
    Posts
    25

    Re: Problem with CStatusBar panes in Windows 7

    Hi VictorN,

    I tried your suggestion and ran automatic and manual tests all day long, but it didn't quite solve the problem. Sometimes when I update one pain another pane would be cleared. However, when a pane is cleared it would be redrawn again if I reseize the program window or cover/uncover the status bar pane with anther program window.

    Instead of InvalidateRect() for a pane I''l try Invalidate() for the entire status bar and then call UpdateWindow().

  4. #4
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: Problem with CStatusBar panes in Windows 7

    You shouldn't need DrawItem just to set status bar text. Try removing it.

  5. #5
    Join Date
    Sep 2012
    Posts
    25

    Re: Problem with CStatusBar panes in Windows 7

    Hi GCDEF,

    Nope! DrawItem() is used to switch pane text between 'dimmed' and 'normal' text to reflect user settings. It is also used to center the text within a pane.

  6. #6
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Problem with CStatusBar panes in Windows 7

    But it must not be called directly! It is called from the framework only. Isn't it?
    Victor Nijegorodov

  7. #7
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: Problem with CStatusBar panes in Windows 7

    Quote Originally Posted by Mike Douglas View Post
    Hi GCDEF,

    Nope! DrawItem() is used to switch pane text between 'dimmed' and 'normal' text to reflect user settings. It is also used to center the text within a pane.
    Still, I would suspect that's where the problem is. I'd comment it out for now and see if the problem goes away. At least it will give you somewhere to look.

  8. #8
    Join Date
    Sep 2012
    Posts
    25

    Re: Problem with CStatusBar panes in Windows 7

    Hi VictorN,

    I DO NOT call DrawItem() directly. It is only called from the framework. I just setup a variable for each pane that defines the color (dimmed or normal) of the text. The variable is used during DrawItem().

    As stated at the bottom of my original post "...MFC automatically disables the pane, erasing its content.". If I knew what causes MFC to disable the pane maybe I can fix the problem instead of handling the symptoms.

  9. #9
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: Problem with CStatusBar panes in Windows 7

    Works fine for me, but I don't override DrawItem, so as I said, I'd start looking there.

  10. #10
    Join Date
    Sep 2012
    Posts
    25

    Re: Problem with CStatusBar panes in Windows 7

    I want to thanl every one who offered pointers. This is the code I ended up with and things seem to be working OK but I'm still testing. If anyone can see any holes I'd appreciate some feedback. I'm especially not sure of the OnPaint() routine at the bottom of the post.


    //adds indicator ID to an array used in DrawItem()

    void CStatusBarBmp::AddIndicatorID (const UINT uIndicatorID)
    {
    INT nIndex = CommandToIndex (uIndicatorID);

    if ((nIndex > 0) && (nIndex < PANES))
    m_auIndicatorID [nIndex] = uIndicatorID;
    } //CStatusBarBmp::AddIndicatorID


    //sets whether pane text is enabled (normal) or disabled (dimmed)

    void CStatusBarBmp::EnablePaneText (const UINT uIndicatorID,
    const BOOL bEnable)
    {
    INT nIndex;

    nIndex = CommandToIndex (uIndicatorID);
    if ((nIndex > 0) && (nIndex < PANES))
    {
    if (m_abEnabled [nIndex] != bEnable)
    {
    RECT stRect;

    m_abEnabled [nIndex] = bEnable;

    GetItemRect (nIndex, &stRect);
    InvalidateRect (&stRect, FALSE);
    UpdateWindow ();
    }
    }
    } //CStatusBarBmp::EnablePaneText


    //owner-drawn routine

    void CStatusBarBmp:rawItem (LPDRAWITEMSTRUCT pstDrawItemStruct)
    {
    INT nItemID;

    nItemID = static_cast<INT>(pstDrawItemStruct->itemID);

    if (CommandToIndex (m_auIndicatorID [nItemID]) == nItemID)
    {
    DWORD dwTextColor;
    CDC cDC;
    CString cszPaneText;

    cDC.Attach (pstDrawItemStruct->hDC);

    cDC.SetBkColor (::GetSysColor (COLOR_BTNFACE));
    if (m_abEnabled [nItemID])
    dwTextColor = ::GetSysColor (COLOR_BTNTEXT);
    else
    dwTextColor = ::GetSysColor (COLOR_GRAYTEXT);
    cDC.SetTextColor (dwTextColor);

    GetPaneText (nItemID, cszPaneText);
    cDC.DrawText (cszPaneText, &pstDrawItemStruct->rcItem,
    DT_CENTER | DT_SINGLELINE);

    cDC.Detach ();
    }
    else
    CStatusBar:rawItem (pstDrawItemStruct);
    } //CStatusBarBmp:rawItem


    void CStatusBarBmp::OnPaint (void)
    {
    CStatusBar::OnPaint ();
    SendMessage (WM_IDLEUPDATECMDUI);
    } //CStatusBarBmp::OnPaint

  11. #11
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Problem with CStatusBar panes in Windows 7

    Quote Originally Posted by Mike Douglas View Post
    Code:
    void CStatusBarBmp::OnPaint (void)
    {
       CStatusBar::OnPaint ();
       SendMessage (WM_IDLEUPDATECMDUI);
    } //CStatusBarBmp::OnPaint
    Why do you send WM_IDLEUPDATECMDUI from within OnPaint?
    You should not! Never do it!
    Standard MFC status bar already receives WM_IDLEUPDATECMDUI messages from the MFC framework!
    Victor Nijegorodov

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured