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 » Combo box height Collapse All
Subject Author Date
Robert Webb Nov 24, 2008 - 6:03 PM

Hi,


I have a combo box on my ribbon bar (created using flags __ECTN_TBB_TEXT_FIELD|__ECTN_TBB_COMBO).  It only has a few items in it, but is far too tall when opened, leaving lots of space at the end.  There is a call DropDownHeightMaxSet() but it seems to set the actual height rather than the maximum height.  The way MFC combo boxes typically work is that you set the maximum height, but it will be shorter if there aren’t enough items to fill that height.  But Prof-UIS combo boxes seem to always use the full height.


I can fix this of course by passing a smaller height to DropDownHeightMaxSet(), but then I need to pass a different height to each combo box, based on trial and error to get it just right, or based on font heights etc which is messy, and would need to change if I ever added another value to the list.  Is there no way to automatically make the drop-down height match the number of items within it (up to the maximum height set), as happens automatically with native MFC?


Thanks,


Rob.

Technical Support Nov 26, 2008 - 1:37 PM

The entire size of the popup list box is measured in the CExtCustomizeSite::OnPopupListBoxMeasureTrackSize() virtual method. Default implementation of this method does nothing. We can code this method and make its body measuring entire size of the popup list box in the same way like the CMainFrame::OnPopupListBoxMeasureTrackSize() method does for the ID_SE_STYLE_LIST combo field displaying list of styles in the StyleEditor sample application. The entire size of the popup list box can be computed through measuring sizes of each list box item. This algorithm is not effective if list box contains thousands of items. That is why we did not coded the body of the CExtCustomizeSite::OnPopupListBoxMeasureTrackSize() virtual method yet. It’s possible to optimize the popup list box size calculation partially. The CExtCustomizeSite::OnPopupListBoxMeasureTrackSize() virtual method knows toolbar button pointer which needs to display the popup list box. It’s possible to get toolbar window pointer and toolbar button position on the screen. This allows to optimize calculation of list box height. If we know toolbar button position on the screen, then the list box height should be smaller than the monitor height where toolbar button is located. We cannot optimize the calculation of the list box width. The width is typically less than any smallest monitor. This means the CExtCustomizeSite::OnPopupListBoxMeasureTrackSize() virtual method will always walk through all the list box items and measure their sizes for computing correct list box widths displaying entirely all the items. The same problem also present in all the popup list boxes displayed by grid cell classes. It would be interesting to know your point of view whether you still expect us to code the generically working popup list box size calculation as part of Prof-UIS?

Robert Webb Nov 26, 2008 - 6:33 PM

The StyleEditor example is useful, but not quite useful enough.  The code is specific to that drop-down, making use of a member variable containing the list of styles.  I would like a generic solution.  OnPopupListBoxMeasureTrackSize() is one of the few OnPopupListBox* callbacks which doesn’t get passed a reference to the CListBox.  Why is that?  How can I get the CListBox within that function?  Then I can enumerate over its items, or since my drop-downs will probably all contain items of the same height, all I really need to know is how many items it contains.  Hmm, maybe it’s a chicken and egg problem as the size is probably requested before the list box is created, but we still need a way to iterate over the items.


And yes, I think you should provide a built-in solution for this.  I’d suggest additional flags to choose whether the drop-down should be auto-height (up to the maximum set) and/or auto-width.  If it is auto-height but not auto-width, then you can optimise quite well, only iterating over items till the max height (or screen height) is reached, so thousands of items would not be a problem.  Maybe even provide a flag to say that all items are the same height, as a hint to speed up calculation (no iterating, just a multiply).


Rob.

Technical Support Dec 1, 2008 - 10:13 AM

We have implemented automatically measured popup list boxes in toolbars, menus, ribbons and grid cells. The following methods still can be used for measuring popup list box size but they are invoked before creation of popup menu and list box windows:
- CExtCustomizeSite::OnPopupListBoxMeasureTrackSize() - used in customizable toolbars and menus
- CExtBarTextFieldButton::OnPopupListBoxMeasureTrackSize() - used in non customizable toolbars and menus
- CExtRibbonPage::OnPopupListBoxMeasureTrackSize() - used in ribbon bar and ribbon page
- CExtGridCell::OnPopupListBoxMeasureTrackSize() - used in all the grid cells
We have implemented new list box measurement methods which are invoked when both popup menu and list box windows are already created but not displayed on the screen:
- CExtCustomizeSite::OnPopupListBoxAdjustSize() - used in customizable toolbars and menus
- CExtBarTextFieldButton::OnPopupListBoxAdjustSize() - used in non customizable toolbars and menus
- CExtRibbonPage::OnPopupListBoxAdjustSize() - used in ribbon bar and ribbon page
- CExtGridCell::OnPopupListBoxAdjustSize() - used in all the grid cells
The new methods are measuring list box sizes via sending the standard WM_MEASUREITEM() message for list box items. All the popup list boxes in Prof-UIS are owner draw and by default are painted using classic look of list box items.
In case of customizable toolbars/menus and ribbon controls the maximal size of popup list box can be specified in constructor parameters of the CExtCustomizeCmdTreeNode or CExtRibbonNode classes:

 CExtCustomizeCmdTreeNode(
            UINT nCmdIdBasic = 0L,
            UINT nCmdIdEffective = 0L,
            CExtCustomizeCmdTreeNode * pParentNode = NULL,
            DWORD dwFlags = 0L,
            __EXT_MFC_SAFE_LPCTSTR strTextInToolbar = NULL,
            __EXT_MFC_SAFE_LPCTSTR strTextInMenu = NULL,
            __EXT_MFC_SAFE_LPCTSTR strTextUser = NULL,
            LPARAM lParam = 0L,
            CExtCmdIcon * pIconCustomized = NULL
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
            ,
            INT nTextFieldWidth = 100,
            INT nDropDownWidth = -2, // (-1) - auto calc, (-2) - same as button area
            INT nDropDownHeightMax = 250
#endif
            );

      CExtRibbonNode(
            UINT nCmdIdBasic = 0L,
            UINT nCmdIdEffective = 0L,
            CExtRibbonNode * pParentNode = NULL,
            DWORD dwFlags = 0L,
            __EXT_MFC_SAFE_LPCTSTR strTextInToolbar = NULL,
            __EXT_MFC_SAFE_LPCTSTR strTextInMenu = NULL,
            __EXT_MFC_SAFE_LPCTSTR strTextUser = NULL,
            LPARAM lParam = 0L,
            CExtCmdIcon * pIconCustomized = NULL
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
            ,
            INT nTextFieldWidth = 100,
            INT nDropDownWidth = -2, // (-1) - auto calc, (-2) - same as button area
            INT nDropDownHeightMax = 250
#endif
            );

The nDropDownWidth parameter is by default set to -1 what makes popup list box using width of combo box button in toolbar. You can set it to -1 for using automatically measured list box width. The nDropDownHeightMax parameter is used for specifying maximal height of popup list box. The maximal width and height of all the popup list boxes are also limited by width and height of the monitor’s work area where popup list box menu is displayed. These parameters can be also set using the CExtCustomizeCmdTreeNode::DropDownWidthSet() and CExtCustomizeCmdTreeNode::DropDownHeightMaxSet() methods.

The grid cell classes does not have list box size options. They are always using popup list box size calculation and make list box width always greater or equal to grid cell width. The list box height is limited by monitor’s work area sizes and the new CExtGridCell::OnPopupListBoxQueryMaxSize() virtual method. The CExtGridCell::TrackCellStateInfo_t data structure which is used for containing properties of grid cell during tracking of its popup menu is now have new properties:
- m_bAdjustListBoxWidth - indicates whether the width of the popup list box menu should be computed from widths of list box items; by default is set to true
- m_bAdjustListBoxHeight - indicates whether the height of the popup list box menu should be computed from heights of list box items; by default is set to true
- m_bAlingListBoxWidthToCellWidthMin - indicates whether the width of the popup list box menu should be greater or equal to grid cell width; by default is set to true
- m_bAlingListBoxWidthToCellWidthMax - indicates whether the width of the popup list box menu should be less or equal to grid cell width; by default is set to false
If two last properties are set to true, then widths of the popup list box menu displayed from grid cell’s drop down button with be the equal to grid cell widths. These properties of the CExtGridCell::TrackCellStateInfo_t data structure can be set in the overridden CExtGridCell::OnPopupListBoxMeasureTrackSize virtual method before invoking parent class method like in the CExtGridCellHeaderFilter class does in Prof-UIS 2.84:
CSize CExtGridCellHeaderFilter::OnPopupListBoxMeasureTrackSize(
      CExtGridCell::TrackCellStateInfo_t & _tcsi,
      CExtPopupListBoxMenuWnd * pPopup
      )
{
      ASSERT_VALID( this );
      _tcsi.m_bAlingListBoxWidthToCellWidthMin = _tcsi.m_bAlingListBoxWidthToCellWidthMax = false;
      return CExtGridCellHeader::OnPopupListBoxMeasureTrackSize( _tcsi, pPopup );
}

In conclusion: now all the popup list box menus in Prof-UIS are using automatically computed sizes by default and this is true even if you have implemented custom measured/painted list box items like the style toolbar button in the StyleEditor sample application. If the list box contains only a few items, then you will not see blank space below the last displayed item. In case of simple list boxes with/without icons, custom item intents and/or check boxes you need only to insert list box items. In case of custom painted/measured list boxes you should implement painting and measuring virtual methods. In both cases you no longer need to compute entire size of popup list box.
You can drop us an e-mail and we will provide you with the source code update.