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 » Autohide and ProfileBarStateLoad Collapse All
Subject Author Date
Raffaele Cappelli Mar 3, 2006 - 9:29 AM

I may have found a bug in CExtControlBar::ProfileBarStateLoad when there is an auto-hidden dynamic bar. I have modified the MDI sample to reproduce the behaviour, you can download it here: I have removed all the bars in the sample, added a single dynamic bar and two new menu items LoadState and SaveState. To reproduce the behaviour:
1) make the bar autohidden
2) save state
3) make the bar floating
4) load state

The bar looks auto-hidden, but if you right click on the caption bar, the "floating" menu item is enabled and the "Auto Hide" menu item is disabled.

Another minor problem (not related with the one above) that you can reproduce in the modified sample is the following:
1) make the bar an MDI document and de-maximize it
2) right click on the caption bar and select "Floating" to make it float again
3) look at the borders between the mini frame wnd and the inner edit control
4) resize the floating frame: you should see the borders be enlarged a bit

Technical Support Mar 4, 2006 - 4:46 AM

Your version of the MDI sample application needs to be modified. First of all, if you use resizable control bars with the auto-hide feature enabled, then the methods that update their state should be exactly like as follows (old lines of code are commented):

void CMainFrame::OnUpdateControlBarMenu(CCmdUI* pCmdUI)
{
//  CExtControlBar::DoFrameBarCheckUpdate( this, pCmdUI, true );
    CExtControlBar::DoFrameBarCheckUpdate( this, pCmdUI, false );
}
 
BOOL CMainFrame::OnBarCheck(UINT nID)
{
//  return CExtControlBar::DoFrameBarCheckCmd( this, nID, true );
    return CExtControlBar::DoFrameBarCheckCmd( this, nID, false );
}
Your methods that load/save the state are not completely correct. You load/save only the location of control bars and this is not correct in case of dynamic control bars. The state of the dynamic bar site should be loaded/saved at the same time. So, the code should include these two steps:

1) Call the CExtDynamicBarSite::StateLoad(), CExtDynamicBarSite::StateSave() or CExtDynamicBarSite::StateSerialize() method.

2) Call the CExtControlBar::ProfileBarStateLoad(), CExtControlBar::ProfileBarStateSave() or CExtControlBar::ProfileBarStateSerialize() method.

The CMainFrame::OnPersistenceLoadFromFile_Resizable() and CMainFrame::OnPersistenceSaveToFile_Resizable() methods in the MDI_DynamicBars sample application may be helpful in this regard.

We failed to reproduce the problem with border size of a floating mini frame window with a dynamic resizable control bar inside. Could you send us two screenshots demonstrating how the border changes.


Raffaele Cappelli Mar 4, 2006 - 1:52 PM

Thank you for the quick reply. I modified the sample as you suggested:


void CMainFrame::OnTestLoadstate() {
    VERIFY(CExtDynamicBarSite::StateLoad("Test","Test","Test"));
    VERIFY(CExtControlBar::ProfileBarStateLoad(this,"Test","Test","Test"));
}

void CMainFrame::OnTestSavestate() {
    VERIFY(CExtDynamicBarSite::StateSave("Test","Test","Test"));
    VERIFY(CExtControlBar::ProfileBarStateSave(this,"Test","Test","Test"));
}

1) I noted that CExtDynamicBarSite::StateLoad fails with assert in CExtCmdIcon::IconCache::Serialize() if the video color depth is <32 bit.
2) A question: if the dynamic bar is persistent, is it really necessary to serialize its icon?

3) As to calling DoFrameBarCheckUpdate( this, pCmdUI, false ) and CExtControlBar::DoFrameBarCheckCmd( this, nID, false ), may I do that only when the bar is actually in autohide mode? (I like the possibility of showing/hiding the bar as the other normal control bars from the menu...)

4) Here are the two screen shots:

Before resize


After resize

It happens when you switch from mdi doc state to floating state

Technical Support Mar 6, 2006 - 2:33 AM

The icon serialization is needed because we suppose an icon may be changed on the fly according to the state of a particular task. It is especially reasonable if your application completely restotes the UI state.

The known problems with icons are fixed in Prof-UIS 2.53. The CExtCmdIcon class is rewritten from scratch and not based on HICON handles anymore. New icons are based on bitmaps with alpha channel and provide the Windows XP/Vista icon quality on any Windows OS. You can download the updated from our ftp site (or contact us via e-mail).

You can code your own OnBarCheck() and OnUpdateControlBarMenu() methods in the main frame window. These methods should analyze whether the control bar identifier corresponds to a particular control bar and whether it is in the auto hide mode. If the latter is true, the check-mark command style should not be used.Otherwise, it can be used for making control bar commands both showing and hiding the bar.

The border effect is really interesting. We will try to figure out what’s wrong and notify you additionally.

Raffaele Cappelli Mar 6, 2006 - 4:15 AM

Thank you for your answers.

I understand the icon serialization is needed in general (of course you have a better idea about how your library is used by the various customers ;-) ). If possible, I suggest to add a flag do disable icon and title bar text serialization for those cases (like in my application) where the serialization is used only to save the layout, and the icon/text are always set by the application.

Acually I was already using a 2.53, but it was an older one. I downloaded the latest and I confirm the problem is now fixed. Furthermore, with the new icon classes, my application seems to use less GDI handles (probably due to the menu icons no longer being HICON) and this is very good, expecially for win98/me systems.

Technical Support Mar 6, 2006 - 8:00 AM

Yes, we can modify the CExtDynamicBarSite::StateSerialize() method so it will serialize icon/text using a new standalone method. This would allow you to override it.

Raffaele Cappelli Mar 6, 2006 - 1:59 PM

Hello, here are two minor problems I incurred with the new icon classes in v2.53:

- icons with an odd size (e.g. 16x15) : ExtBitmap::AssignFromHICON( HICON hIcon ) does not work. I suggest to get the icon size always from the _iconInfo.hbmMask and not from the Hotspot.

- when a dynamic bar is in MDI child state and the MDI child is maximized, the icon displayed in the menu bar (the system menu of the child) has a black background (it seems the mask is not copied correctly); the same happens in the MDI tab icon. You can reproduce this problem by modifying the 16x16 icon associated to the dynamic bars in the MDI_DynamicBars sample so that it has some background pixels, then set a dynamic bar to MDI document state and maximize it.

Technical Support Mar 7, 2006 - 10:25 AM

First of all, plese let us whether where these problems can reproduced with Prof-UIS samples. Besides, we improved bitmap and icon classes, including the capatibilty of assigning a bitmap from an icon handle. Now it is possible to assign a Windows XP icon based on a 32-bit bitmap (with alpha channel). Please, download an updated Prof-UIS 2.53 from our ftp.

Raffaele Cappelli Mar 7, 2006 - 2:05 PM

The first problem (but it is not a very important issue) does not need to be reproduced, just look at the implementation of bool CExtBitmap::AssignFromHICON( HICON hIcon ):

CSize _sizeIcon((INT)( (BYTE)(_iconInfo.xHotspot * 2 ) ),
     (INT)( (BYTE)(_iconInfo.yHotspot * 2 ) ));

it will be never able to correctly get an odd size (e.g. if the icon height is 15, it will set _sizeIcon.cy=14, since the hotspot y will be 7).


The second problem can be reproduced by modifying the 16x16 icon (IDR_MAINFRAME) associated to the dynamic bars in your MDI_DynamicBars sample: for instance make half of the pixels in the the icon background pixels, then set a dynamic bar to MDI document state, maximize it and look at the icon in the menubar on the left of the File menu.

Technical Support Mar 9, 2006 - 9:27 AM

We think we use the correct way of getting the icon size even with one pixel precision. Besides, this formula is not our idea. In fact, most of the icons have even sizes and this calculation does not bring a problem. The original toolbar common control is bitmap based. The HICON-related calculation will not affect. Here is the latest version of the CExtBitmap::AssignFromHICON() method which should not cause any problems:

 
bool CExtBitmap::AssignFromHICON( HICON hIcon )
{
    Empty();
    if( hIcon == NULL )
        return true;
ICONINFO _iconInfo;
    ::memset( &_iconInfo, 0, sizeof(ICONINFO) );
    if( ! ::GetIconInfo( hIcon, &_iconInfo ) )
        return false;
    ASSERT( _iconInfo.hbmColor != NULL || _iconInfo.hbmMask != NULL );
CSize _sizeIcon(
        (INT)( (BYTE)(_iconInfo.xHotspot * 2 ) ),
        (INT)( (BYTE)(_iconInfo.yHotspot * 2 ) )
        );
BITMAP _bmpInfo;
    ::memset( &_bmpInfo, 0, sizeof(BITMAP) );
    ::GetObject(
        (_iconInfo.hbmColor != NULL) ? _iconInfo.hbmColor : _iconInfo.hbmMask,
        sizeof(BITMAP),
        &_bmpInfo
        );
    ASSERT( _bmpInfo.bmWidth > 0 && _bmpInfo.bmHeight > 0 );
    if( _sizeIcon.cx == 0 || _sizeIcon.cy == 0 )
    {
        _sizeIcon.cx = (INT)_bmpInfo.bmWidth;
        _sizeIcon.cy = (INT)_bmpInfo.bmHeight;
    }
    ASSERT( _sizeIcon.cx > 0 );
    ASSERT( _sizeIcon.cy > 0 );
    if(       _bmpInfo.bmBitsPixel == 32
        &&    g_PaintManager.m_bIsWinXPorLater
        &&    CExtPaintManager::stat_GetBPP() >= 32
        )
    { // XP alpha icons under Windows XP or later + 32 bit desktop
        CExtImageList _il;
        if(    _il.Create(
                _sizeIcon.cx,
                _sizeIcon.cy,
                ILC_COLOR32,
                1,
                1
                )
            )
        {
            if( _il.Add( hIcon ) >= 0 )
            {
                IMAGEINFO _ii = { 0 };
                _il.GetImageInfo( 0, &_ii );
                ASSERT( _ii.hbmImage != NULL );
                ASSERT( _ii.hbmMask == NULL );
                if( ! FromBitmap(
                        _ii.hbmImage,
                        &_ii.rcImage,
                        false,
                        true
                        )
                    )
                    Empty();
                else
                {
                    bool bAssignedEmpty = true;
                    for( INT nY = 0; nY < _sizeIcon.cy; nY++ )
                    {
                        for( INT nX = 0; nX < _sizeIcon.cx; nX++ )
                        {
                            RGBQUAD _pixel;
                            VERIFY( GetPixel( nX, nY, _pixel ) );
                            if( _pixel.rgbReserved != 0 )
                            {
                                bAssignedEmpty = false;
                                break;
                            }
                        }
                        if( ! bAssignedEmpty )
                            break;
                    }
                    if( bAssignedEmpty )
                        Empty();
                }
                ::DeleteObject( _ii.hbmImage );
            }
        }
    } // XP alpha icons under Windows XP or later + 32 bit desktop
    if( IsEmpty() )
    { // old style icon
        if( _iconInfo.hbmColor == NULL && _iconInfo.hbmMask != NULL )
        {
            CRect rc( 0, 0, _sizeIcon.cx, _sizeIcon.cy );
            if( FromBitmap( _iconInfo.hbmMask, &rc, false, false ) )
            {
            }
            else
                Empty();
        }
        else if( _iconInfo.hbmColor != NULL )
        {
            if( FromBitmap( _iconInfo.hbmColor, false ) )
            {
                if( Make32( false ) )
                {
                    if( _iconInfo.hbmMask != NULL )
                    {
                        CExtBitmap bmpMask;
                        if(       bmpMask.FromBitmap( _iconInfo.hbmMask )
                            &&    bmpMask.Make32( false )
                            )
                        {
                            INT nX, nY;
                            for( nY = 0; nY < _sizeIcon.cy; nY ++ )
                            {
                                for( nX = 0; nX < _sizeIcon.cx; nX ++ )
                                {
                                    RGBQUAD _pixel;
                                    VERIFY( GetPixel( nX, nY, _pixel ) );
                                    COLORREF clrMaskPixel = bmpMask.GetPixel( nX, nY );
                                    if( clrMaskPixel == RGB(0,0,0) )
                                        _pixel.rgbReserved = 0xFF;
                                    else
                                        _pixel.rgbReserved = 0x0;
                                    VERIFY( SetPixel( nX, nY, _pixel ) );
                                }
                            }
                        }
                        else
                            Empty();
                    }
                }
                else
                    Empty();
            }
        }
    }
    if( _iconInfo.hbmColor != NULL )
        ::DeleteObject( _iconInfo.hbmColor );
    if( _iconInfo.hbmMask != NULL )
        ::DeleteObject( _iconInfo.hbmMask );
    OnContentChanged();
bool bIsEmpty = IsEmpty();
    return ( ! bIsEmpty );
}

Raffaele Cappelli Mar 9, 2006 - 1:23 PM

Yes. I agree that icons should have even sizes, so it is not a problem, thank you.

What about the second problem? Are you able to reproduce it as I described?

Technical Support Mar 11, 2006 - 9:39 AM

Yes, the second problem was successfully reproduced and fixed. The updated source code is available via ftp.