I needed a button that has an image on its left side and provides a dropdown button with a list of options the users can choose from, like the Explorer’s Back button. The next requirement was that the picture and menu are optional and the button should generate a BN_CLICKED message if the button itself or a menu item was clicked.
I read several articles here but I didn’t find a solution that suits me. So, I wrote it on my own. It’s a CButton-derived class that uses the OwnerDraw style.
Using the Control
To use my control in your project, just add the following files to it:
Then, either add a button to your dialog resource and add a control variable of the type CChoiceButton or subclass it. Or, create it—dynamically, of course. The button shows up as a normal button unless an image is set and/or menu items are added. The first added menu item will be selected.
Then, as with a normal button, add a Message handler for BN_CLICKED and in it you can determine the chosen state by calling the GetChoice() member function. With Memberfunction SetImage(…), you can set an image for the button to display on its left side (must be a bitmap resource). With Memberfunction AddMenuItem(…), you can add items to the dropdown menu. The menu button won’t be displayed unless the menu contains at least one item. The button can act as default button. You don’t have to set it as Ownerdraw in the Dialog editor.
The control provides you with these functions to control it:
- BOOL SetImage(UINT nResID, COLORREF crTrans, bool bResize = true): Sets the image that will appear on the left side of the main button.
- UINT nResID: The resource identifier of the buttons bitmap.
- COLORREF crTrans: The color in the bitmap that will be mapped to the button’s face color.
- bool bResize: Says whether the controls height should be resized to fit the images height, preserving BorderSpacing.
- Return Value: TRUE if the image could be loaded
- int AddMenuItem(LPCTSTR lpszNewItem): Adds an item to the dropdown menu. The first item added will become the button’s text and will be checked by default; you can specify another menu item with SetChoice(…).
- LPCTSTR lpszNewItem: The label of the menu item
- Return Value: The choice number of this item, the position of the new item in the dropdown menu; can be compared to the value of GetChoice()
- BOOL DeleteMenuItem(UINT nItem): Deletes a menu item
- UINT nItem: the choice number of the menu item
- Return Value: true, if menu item could be deleted
- void AddMenuSeparator(): Adds a separator to the menu
- bool EnableMenuItem(UINT nItem, bool bEnable): Enables or disables (grays) a menu item
- UINT nItem: The item that should be enabled/disabled (return value of AddMenuItem())
- bool bEnable: True: menu item should be enabled; false: menu item should be disabled
- Return Value: Previous state of that menu item
- void SetChoice(UINT nMenuItem): Sets the actual chosen menu item
- UINT nMenuItem: The menu item that is to be chosen (return value from AddMenuItem)
- UINT GetChoice(): Gets the actual choice.
- Return Value: The ID of the actual chosen item; can be compared to return value of AddMenuItem()
- bool SetPush(bool bPushed): :ets the button appear to be pushed
- bool bPushed: Rrue: button appears as pushed
- Return Value: Previous push state of button
- void SetDropWidth(UINT nDropWidth) sets the amount of pixels by which the buttons text,image and arrow will move (right&down) if pushed
- UINT nDropWidth: See above; default: 1
- void SetMenuButtonWidth(UINT nWidth): Sets the width of the menu button (if displayed) in pixels.
- UINT nWidth: See above; default: 20
- void SetBorderSpacing(UINT nSpacing): Sets the minimal spacing (in pixels) from the borders of the buttons text, image, and arrow.
- UINT nSpacing: See above; default: 4
- void SetPicTextSpacing(UINT nSpacing) Sets the spacing between the image and the button’s text
- UINT nSpacing: See above; default: 4
- void SizeToContents(UINT uSpacing): Resizes the buttons Width to fit all contents, including picture, the buttons text (in case that menu items where added, the largest menu item label is considered), spacings, the menu button
- UINT uSpacing: an individual spacing, that is added to the calculated width. default: 10
by Christian Skovdal Andersen