Discussion:
Toolbar icons with different image sizes
(too old to reply)
Francis
2008-01-10 16:06:26 UTC
Permalink
I am creating an internet explorer toolbar that has toolbar buttons
where most buttons have an icon of 16 pixels in width and height.
However there is one button that is has 80x16 size and is used as a
drop-down menu.

Adding the large icon to the toolbar gives funny results. The large
icon is chopped up in icons of 16x16. The large button receives the
first piece, and all the icon buttons after it get a following piece
of it instead of their own icon.

I figure that the large icon is interpreted as adding 5 icons. This
despite the fact that I use TB_ADDBITMAP with wParam=1, meaning that
the image only contains one bitmap.

Can anyone help me with this problem?


Best regards,

Francis
Christian ASTOR
2008-01-10 21:31:59 UTC
Permalink
Post by Francis
I am creating an internet explorer toolbar that has toolbar buttons
where most buttons have an icon of 16 pixels in width and height.
However there is one button that is has 80x16 size and is used as a
drop-down menu.
Adding the large icon to the toolbar gives funny results. The large
icon is chopped up in icons of 16x16. The large button receives the
first piece, and all the icon buttons after it get a following piece
of it instead of their own icon.
I figure that the large icon is interpreted as adding 5 icons. This
despite the fact that I use TB_ADDBITMAP with wParam=1, meaning that
the image only contains one bitmap.
Can anyone help me with this problem?
TB_ADDBITMAP adds bitmaps to the Toolbar ImageList, which has images of
the same size.
A button width can be changed by TB_SETBUTTONINFO
For a bitmap with another width, another control must be inserted (e.g.
another Toolbar)
Francis
2008-01-11 20:23:53 UTC
Permalink
Post by Christian ASTOR
Post by Francis
I am creating an internet explorer toolbar that has toolbar buttons
where most buttons have an icon of 16 pixels in width and height.
However there is one button that is has 80x16 size and is used as a
drop-down menu.
Adding the large icon to the toolbar gives funny results. The large
icon is chopped up in icons of 16x16. The large button receives the
first piece, and all the icon buttons after it get a following piece
of it instead of their own icon.
I figure that the large icon is interpreted as adding 5 icons. This
despite the fact that I use TB_ADDBITMAP with wParam=1, meaning that
the image only contains one bitmap.
Can anyone help me with this problem?
TB_ADDBITMAP adds bitmaps to the Toolbar ImageList, which has images of
the same size.
A button width can be changed by TB_SETBUTTONINFO
For a bitmap with another width, another control must be inserted (e.g.
another Toolbar)
Thanks, this idea actually clears up a lot, and I think that I'm
finally beginning to 'get' windows programming.

Just a quick question: the second toolbar is that a child window of
the first, or a sibling?
Francis
2008-01-14 12:36:13 UTC
Permalink
Ok, it works a little. I created a second toolbar as a child control
of the first toolbar. However, the area occupied by the toolbar is
black. Button highlighting works though (shows a grey empty button).
The icons on the first toolbar are not harmed and buttons work
perfectly.

Do I need to override WM_PAINT messages or something in order to make
rendering for the second toolbar work?
b***@gmail.com
2008-01-14 14:56:05 UTC
Permalink
Post by Francis
Ok, it works a little. I created a second toolbar as a child control
of the first toolbar. However, the area occupied by the toolbar is
black. Button highlighting works though (shows a grey empty button).
The icons on the first toolbar are not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the second toolbar work?
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigning button images from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the larger button. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So the button
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.

I've read several supposed solutions to this problem, but none of them
actually work. I'm considering moving to the approach you're using,
building a second toolbar in my main toolbar, but I'm wondering first
if it actually solves the problem. How exactly are you building the
child toolbar? Maybe we can figure this out together...
Francis
2008-01-14 16:55:37 UTC
Permalink
Post by b***@gmail.com
Ok, it works a little. I created a secondtoolbaras a child control
of the firsttoolbar. However, the area occupied by thetoolbaris
black.Buttonhighlighting works though (shows a grey emptybutton).
The icons on the firsttoolbarare not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the secondtoolbarwork?
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigningbuttonimages from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the largerbutton. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So thebutton
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I've read several supposed solutions to this problem, but none of them
actually work. I'm considering moving to the approach you're using,
building a secondtoolbarin my maintoolbar, but I'm wondering first
if it actually solves the problem. How exactly are you building the
childtoolbar? Maybe we can figure this out together...
I have not yet succeeded to make it work. Due to time pressure I am
now using an image button instead that I add as a custom window to the
toolbar. I will certainly post more info when I get it to work.

The code for the second toolbar looks like this:

RECT rc;
GetClientRect(mParentHandle, &rc);
mSubToolbar = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
NULL,
0
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| TBSTYLE_FLAT
| TBSTYLE_TRANSPARENT
//| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
,
rc.left,rc.top,100,24,
mToolbarHandle, // original toolbar
(HMENU)(INT_PTR)IDC_TOOLBAR_SUBTOOLBAR,
GetModuleHandle(0),
NULL
);
SendMessage(mSubToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)
sizeof(TBBUTTON), 0);

// Create the image list.
HIMAGELIST hImageList = ImageList_Create(80, 16, ILC_COLOR32, 10, 10);
CGdiPlusBitmapResource theBmpRes // helper class, can be found on
google
(
MAKEINTRESOURCE(IDI_TOOLBAR_LOGO),
RT_RCDATA,
mModuleHandle
);

HICON theIcon;
theBmpRes.m_pBitmap->GetHICON(&theIcon);

ImageList_AddIcon(hImageList, theIcon);
DeleteObject(theIcon);

TBBUTTON theToolbarButton;
theToolbarButton.iBitmap = 1;
theToolbarButton.idCommand = IDC_TOOLBAR_SUBTOOLBAR;
theToolbarButton.fsState = TBSTATE_ENABLED;
theToolbarButton.fsStyle = BTNS_BUTTON | BTNS_DROPDOWN;
theToolbarButton.dwData = 0;
theToolbarButton.iString = (INT_PTR)TEXT("Test");

SendMessage(mSubToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
SendMessage(mSubToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)
(LPTBBUTTON) &theToolbarButton);
SendMessage(mSubToolbar, TB_AUTOSIZE, 0, 0);


Hope this helps a bit,

Francis
Francis
2008-01-14 16:56:06 UTC
Permalink
Post by b***@gmail.com
Ok, it works a little. I created a secondtoolbaras a child control
of the firsttoolbar. However, the area occupied by thetoolbaris
black.Buttonhighlighting works though (shows a grey emptybutton).
The icons on the firsttoolbarare not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the secondtoolbarwork?
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigningbuttonimages from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the largerbutton. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So thebutton
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I've read several supposed solutions to this problem, but none of them
actually work. I'm considering moving to the approach you're using,
building a secondtoolbarin my maintoolbar, but I'm wondering first
if it actually solves the problem. How exactly are you building the
childtoolbar? Maybe we can figure this out together...
I have not yet succeeded to make it work. Due to time pressure I am
now using an image button instead that I add as a custom window to the
toolbar. I will certainly post more info when I get it to work.

The code for the second toolbar looks like this:

RECT rc;
GetClientRect(mParentHandle, &rc);
mSubToolbar = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
NULL,
0
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| TBSTYLE_FLAT
| TBSTYLE_TRANSPARENT
//| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
,
rc.left,rc.top,100,24,
mToolbarHandle, // original toolbar
(HMENU)(INT_PTR)IDC_TOOLBAR_SUBTOOLBAR,
GetModuleHandle(0),
NULL
);
SendMessage(mSubToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)
sizeof(TBBUTTON), 0);

// Create the image list.
HIMAGELIST hImageList = ImageList_Create(80, 16, ILC_COLOR32, 10, 10);
CGdiPlusBitmapResource theBmpRes // helper class, can be found on
google
(
MAKEINTRESOURCE(IDI_TOOLBAR_LOGO),
RT_RCDATA,
mModuleHandle
);

HICON theIcon;
theBmpRes.m_pBitmap->GetHICON(&theIcon);

ImageList_AddIcon(hImageList, theIcon);
DeleteObject(theIcon);

TBBUTTON theToolbarButton;
theToolbarButton.iBitmap = 1;
theToolbarButton.idCommand = IDC_TOOLBAR_SUBTOOLBAR;
theToolbarButton.fsState = TBSTATE_ENABLED;
theToolbarButton.fsStyle = BTNS_BUTTON | BTNS_DROPDOWN;
theToolbarButton.dwData = 0;
theToolbarButton.iString = (INT_PTR)TEXT("Test");

SendMessage(mSubToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
SendMessage(mSubToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)
(LPTBBUTTON) &theToolbarButton);
SendMessage(mSubToolbar, TB_AUTOSIZE, 0, 0);


Hope this helps a bit,

Francis
Bennett
2008-01-14 20:10:51 UTC
Permalink
Post by Francis
Post by b***@gmail.com
Ok, it works a little. I created a secondtoolbaras a child control
of the firsttoolbar. However, the area occupied by thetoolbaris
black.Buttonhighlighting works though (shows a grey emptybutton).
The icons on the firsttoolbarare not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the secondtoolbarwork?
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigningbuttonimages from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the largerbutton. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So thebutton
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I've read several supposed solutions to this problem, but none of them
actually work. I'm considering moving to the approach you're using,
building a secondtoolbarin my maintoolbar, but I'm wondering first
if it actually solves the problem. How exactly are you building the
childtoolbar? Maybe we can figure this out together...
I have not yet succeeded to make it work. Due to time pressure I am
now using an image button instead that I add as a custom window to the
toolbar. I will certainly post more info when I get it to work.
RECT rc;
GetClientRect(mParentHandle, &rc);
mSubToolbar = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
NULL,
0
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| TBSTYLE_FLAT
| TBSTYLE_TRANSPARENT
//| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
,
rc.left,rc.top,100,24,
mToolbarHandle, // original toolbar
(HMENU)(INT_PTR)IDC_TOOLBAR_SUBTOOLBAR,
GetModuleHandle(0),
NULL
);
SendMessage(mSubToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)
sizeof(TBBUTTON), 0);
// Create the image list.
HIMAGELIST hImageList = ImageList_Create(80, 16, ILC_COLOR32, 10, 10);
CGdiPlusBitmapResource theBmpRes // helper class, can be found on
google
(
MAKEINTRESOURCE(IDI_TOOLBAR_LOGO),
RT_RCDATA,
mModuleHandle
);
HICON theIcon;
theBmpRes.m_pBitmap->GetHICON(&theIcon);
ImageList_AddIcon(hImageList, theIcon);
DeleteObject(theIcon);
TBBUTTON theToolbarButton;
theToolbarButton.iBitmap = 1;
theToolbarButton.idCommand = IDC_TOOLBAR_SUBTOOLBAR;
theToolbarButton.fsState = TBSTATE_ENABLED;
theToolbarButton.fsStyle = BTNS_BUTTON | BTNS_DROPDOWN;
theToolbarButton.dwData = 0;
theToolbarButton.iString = (INT_PTR)TEXT("Test");
SendMessage(mSubToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
SendMessage(mSubToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)
(LPTBBUTTON) &theToolbarButton);
SendMessage(mSubToolbar, TB_AUTOSIZE, 0, 0);
Hope this helps a bit,
Francis
I've tried using your code, but I can't get a subToolbar to appear. I
think I'm confused as to the difference between mParentHandle and
mToolbarHandle. Also, are you using MFC or ATL?

I've been trying to use NM_CUSTOMDRAW as well, but I can't seem to get
that to work. I can capture the NM_CUSTOMDRAW message, but then my
buttons just don't seem to get drawn, even when I try to just do the
default behavior.

Have you had any more luck?
Francis
2008-01-14 22:19:21 UTC
Permalink
Post by Bennett
I've tried using your code, but I can't get a subToolbar to appear. I
think I'm confused as to the difference between mParentHandle and
mToolbarHandle. Also, are you using MFC or ATL?
I've been trying to use NM_CUSTOMDRAW as well, but I can't seem to get
that to work. I can capture the NM_CUSTOMDRAW message, but then my
buttons just don't seem to get drawn, even when I try to just do the
default behavior.
Have you had any more luck?
I had some luck, but I can still use some more. The toolbar renders
the button now, but the refreshing of the button doesn't work like it
should. It repaints without erasing it's backgroud, so the result is
that the highlighting causes blurriness in the toolbar icon. Because
it keeps painting over itself.

Also the highlighting is different than that of the other buttons. The
other buttons show a rounded highlighting rectangle, and the
subtoolbar button has sharp cornered highlighting.

I am not using ATL or MFC, just pure Win32 API calls.

The code looks like this now:
hWndParent is the parent window of the main toolbar
mToolbarHandle is the handle to the main toolbar
mSubToolbar is the handle to the second toolbar


RECT rc;
GetClientRect(hWndParent, &rc);


mToolbarHandle = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
0,
WS_CHILDWINDOW
//| WS_CLIPSIBLINGS
//| WS_CLIPCHILDREN
| WS_TABSTOP
| TBSTYLE_FLAT
// Version 4.70. Creates a flat toolbar. In a flat toolbar, both the
toolbar and the buttons are
// transparent and hot-tracking is enabled. Button text appears under
button bitmaps. To prevent
// repainting problems, this style should be set before the toolbar
control becomes visible.
//| TBSTYLE_WRAPABLE
// Creates a toolbar that can have multiple lines of buttons. Toolbar
buttons can "wrap" to the next
// line when the toolbar becomes too narrow to include all buttons on
the same line. When the toolbar
// is wrapped, the break will occur on either the rightmost separator
or the rightmost button if there
// are no separators on the bar. This style must be set to display a
vertical toolbar control when the
// toolbar is part of a vertical rebar control. This style cannot be
combined with CCS_VERT.
| TBSTYLE_TRANSPARENT
// Version 4.71. Creates a transparent toolbar. In a transparent
toolbar, the toolbar is transparent
// but the buttons are not. Button text appears under button bitmaps.
To prevent repainting problems,
// this style should be set before the toolbar control becomes
visible.
| TBSTYLE_LIST
// Version 4.70. Creates a flat toolbar with button text to the right
of the bitmap. Otherwise, this
// style is identical to TBSTYLE_FLAT. To prevent repainting problems,
this style should be set before
// the toolbar control becomes visible.
// | TBSTYLE_CUSTOMERASE
// Version 4.70. Generates NM_CUSTOMDRAW notification messages when
the toolbar processes
// WM_ERASEBKGND messages.
| TBSTYLE_TOOLTIPS
// Creates a ToolTip control that an application can use to display
descriptive text for the buttons
// in the toolbar.
| CCS_NODIVIDER
// Prevents a two-pixel highlight from being drawn at the top of the
control.
| CCS_NOPARENTALIGN
// Prevents the control from automatically moving to the top or bottom
of the parent window. Instead,
// the control keeps its position within the parent window despite
changes to the size of the parent.
// If CCS_TOP or CCS_BOTTOM is also used, the height is adjusted to
the default, but the position and
// width remain unchanged.
| CCS_NORESIZE
// Prevents the control from using the default width and height when
setting its initial size or a
// new size. Instead, the control uses the width and height specified
in the request for creation or
// sizing.
| CCS_TOP
// Causes the control to position itself at the top of the parent
window's client area and sets the
// width to be the same as the parent window's width. Toolbars have
this style by default.
// | CCS_ADJUSTABLE
// Enables a toolbar's built-in customization features, which let the
user to drag a button to a new
// position or to remove a button by dragging it off the toolbar. In
addition, the user can
// double-click the toolbar to display the Customize Toolbar dialog
box, which enables the user to
// add, delete, and rearrange toolbar buttons.
// | CCS_BOTTOM
// Causes the control to position itself at the bottom of the parent
window's client area and sets the
// width to be the same as the parent window's width. Status windows
have this style by default.
// | CCS_LEFT
// Version 4.70. Causes the control to be displayed vertically on the
left side of the parent window.
| CCS_NODIVIDER
// Prevents a two-pixel highlight from being drawn at the top of the
control.
// | CCS_NOMOVEX
// Version 4.70. Causes the control to resize and move itself
vertically, but not horizontally, in
// response to a WM_SIZE message. If CCS_NORESIZE is used, this style
does not apply.
// | CCS_NOMOVEY
// Causes the control to resize and move itself horizontally, but not
vertically, in response to a
// WM_SIZE message. If CCS_NORESIZE is used, this style does not
apply. Header windows have this style
// by default.
| CCS_NORESIZE
// Prevents the control from using the default width and height when
setting its initial size or a new
// size. Instead, the control uses the width and height specified in
the request for creation or
// sizing.
// | CCS_RIGHT
// Version 4.70. Causes the control to be displayed vertically on the
right side of the parent window.
// | CCS_TOP
// Causes the control to position itself at the top of the parent
window's client area and sets the
// width to be the same as the parent window's width. Toolbars have
this style by default.
// | CCS_VERT
// Version 4.70. Causes the control to be displayed vertically.

,rc.left,rc.top,rc.right-rc.left,cIconHeight,
hWndParent,
(HMENU)(INT_PTR)eToolbarPane_Toolbar,
mModuleHandle,
0
);

mSubToolbar = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
NULL,
0
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| WS_VISIBLE
| TBSTYLE_FLAT
| TBSTYLE_TRANSPARENT
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
| TBSTYLE_TOOLTIPS
| TBSTYLE_LIST
| WS_TABSTOP
,
0,0,100,24, // give some extra width and height
mToolbarHandle, // original toolbar
(HMENU)(INT_PTR)inId,
mModuleHandle,
NULL
);
SendMessage(mSubToolbar , TB_BUTTONSTRUCTSIZE, (WPARAM)
sizeof(TBBUTTON), 0);

// Create the image list, himlHot.
HIMAGELIST hImageList = ImageList_Create
(
80,
16,
ILC_COLOR32,
10,
10
);
CGdiPlusBitmapResource theBmpRes
(
MAKEINTRESOURCE(inIconResourceId),
RT_RCDATA,
mModuleHandle
);

HICON theIcon;
theBmpRes.m_pBitmap->GetHICON(&theIcon);
ImageList_AddIcon(hImageList, theIcon);
DeleteObject(theIcon);

TBBUTTON theToolbarButton;
theToolbarButton.iBitmap = (int)0;
theToolbarButton.idCommand = inCommandId;
theToolbarButton.fsState = TBSTATE_ENABLED;
theToolbarButton.fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE;
theToolbarButton.dwData = 0;
theToolbarButton.iString = (INT_PTR)TEXT("");

SendMessage(mSubToolbar , TB_SETIMAGELIST, 0, (LPARAM)hImageList);
SendMessage(mSubToolbar , TB_ADDBUTTONS, (WPARAM)1, (LPARAM)
(LPTBBUTTON) &theToolbarButton);
SendMessage(mSubToolbar , TB_AUTOSIZE, 0, 0);
SendMessage((HWND)mSubToolbar , (UINT) TB_SETEXTENDEDSTYLE, (WPARAM)0,
(LPARAM) TBSTYLE_EX_DRAWDDARROWS);
//ShowWindow(mSubToolbar , SW_SHOW);

I hope this helps, don't hesitate to ask for clarification if needed.

I'll also have a look at NM_CUSTOMDRAW and I'll keep you updated if I
make any progress...
Francis
2008-01-14 22:22:44 UTC
Permalink
The main toolbar has no WS_CLIPCHILDREN and no WS_CLIPSIBLINGS, that
was the crucial change.
Francis
2008-01-15 17:44:07 UTC
Permalink
Post by Bennett
Post by Francis
Post by b***@gmail.com
Ok, it works a little. I created a secondtoolbaras a child control
of the firsttoolbar. However, the area occupied by thetoolbaris
black.Buttonhighlighting works though (shows a grey emptybutton).
The icons on the firsttoolbarare not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the secondtoolbarwork?
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigningbuttonimages from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the largerbutton. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So thebutton
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I've read several supposed solutions to this problem, but none of them
actually work. I'm considering moving to the approach you're using,
building a secondtoolbarin my maintoolbar, but I'm wondering first
if it actually solves the problem. How exactly are you building the
childtoolbar? Maybe we can figure this out together...
I have not yet succeeded to make it work. Due to time pressure I am
now using an image button instead that I add as a custom window to the
toolbar. I will certainly post more info when I get it to work.
RECT rc;
GetClientRect(mParentHandle, &rc);
mSubToolbar = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
NULL,
0
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| TBSTYLE_FLAT
| TBSTYLE_TRANSPARENT
//| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
,
rc.left,rc.top,100,24,
mToolbarHandle, // original toolbar
(HMENU)(INT_PTR)IDC_TOOLBAR_SUBTOOLBAR,
GetModuleHandle(0),
NULL
);
SendMessage(mSubToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)
sizeof(TBBUTTON), 0);
// Create the image list.
HIMAGELIST hImageList = ImageList_Create(80, 16, ILC_COLOR32, 10, 10);
CGdiPlusBitmapResource theBmpRes // helper class, can be found on
google
(
MAKEINTRESOURCE(IDI_TOOLBAR_LOGO),
RT_RCDATA,
mModuleHandle
);
HICON theIcon;
theBmpRes.m_pBitmap->GetHICON(&theIcon);
ImageList_AddIcon(hImageList, theIcon);
DeleteObject(theIcon);
TBBUTTON theToolbarButton;
theToolbarButton.iBitmap = 1;
theToolbarButton.idCommand = IDC_TOOLBAR_SUBTOOLBAR;
theToolbarButton.fsState = TBSTATE_ENABLED;
theToolbarButton.fsStyle = BTNS_BUTTON | BTNS_DROPDOWN;
theToolbarButton.dwData = 0;
theToolbarButton.iString = (INT_PTR)TEXT("Test");
SendMessage(mSubToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
SendMessage(mSubToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)
(LPTBBUTTON) &theToolbarButton);
SendMessage(mSubToolbar, TB_AUTOSIZE, 0, 0);
Hope this helps a bit,
Francis
I've tried using your code, but I can't get a subToolbar to appear. I
think I'm confused as to the difference between mParentHandle and
mToolbarHandle. Also, are you using MFC or ATL?
I've been trying to use NM_CUSTOMDRAW as well, but I can't seem to get
that to work. I can capture the NM_CUSTOMDRAW message, but then my
buttons just don't seem to get drawn, even when I try to just do the
default behavior.
Have you had any more luck?
After a lot more struggling today I am now considering to go the
NM_CUSTOMDRAW route. I think it's a more standard and better supported
solution than the other methods that I have tried up until now.
Bennett
2008-01-16 16:08:21 UTC
Permalink
Post by Francis
Post by Bennett
Post by Francis
Post by b***@gmail.com
Ok, it works a little. I created a secondtoolbaras a child control
of the firsttoolbar. However, the area occupied by thetoolbaris
black.Buttonhighlighting works though (shows a grey emptybutton).
The icons on the firsttoolbarare not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the secondtoolbarwork?
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigningbuttonimages from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the largerbutton. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So thebutton
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I've read several supposed solutions to this problem, but none of them
actually work. I'm considering moving to the approach you're using,
building a secondtoolbarin my maintoolbar, but I'm wondering first
if it actually solves the problem. How exactly are you building the
childtoolbar? Maybe we can figure this out together...
I have not yet succeeded to make it work. Due to time pressure I am
now using an image button instead that I add as a custom window to the
toolbar. I will certainly post more info when I get it to work.
RECT rc;
GetClientRect(mParentHandle, &rc);
mSubToolbar = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
NULL,
0
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| TBSTYLE_FLAT
| TBSTYLE_TRANSPARENT
//| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
,
rc.left,rc.top,100,24,
mToolbarHandle, // original toolbar
(HMENU)(INT_PTR)IDC_TOOLBAR_SUBTOOLBAR,
GetModuleHandle(0),
NULL
);
SendMessage(mSubToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)
sizeof(TBBUTTON), 0);
// Create the image list.
HIMAGELIST hImageList = ImageList_Create(80, 16, ILC_COLOR32, 10, 10);
CGdiPlusBitmapResource theBmpRes // helper class, can be found on
google
(
MAKEINTRESOURCE(IDI_TOOLBAR_LOGO),
RT_RCDATA,
mModuleHandle
);
HICON theIcon;
theBmpRes.m_pBitmap->GetHICON(&theIcon);
ImageList_AddIcon(hImageList, theIcon);
DeleteObject(theIcon);
TBBUTTON theToolbarButton;
theToolbarButton.iBitmap = 1;
theToolbarButton.idCommand = IDC_TOOLBAR_SUBTOOLBAR;
theToolbarButton.fsState = TBSTATE_ENABLED;
theToolbarButton.fsStyle = BTNS_BUTTON | BTNS_DROPDOWN;
theToolbarButton.dwData = 0;
theToolbarButton.iString = (INT_PTR)TEXT("Test");
SendMessage(mSubToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
SendMessage(mSubToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)
(LPTBBUTTON) &theToolbarButton);
SendMessage(mSubToolbar, TB_AUTOSIZE, 0, 0);
Hope this helps a bit,
Francis
I've tried using your code, but I can't get a subToolbar to appear. I
think I'm confused as to the difference between mParentHandle and
mToolbarHandle. Also, are you using MFC or ATL?
I've been trying to use NM_CUSTOMDRAW as well, but I can't seem to get
that to work. I can capture the NM_CUSTOMDRAW message, but then my
buttons just don't seem to get drawn, even when I try to just do the
default behavior.
Have you had any more luck?
After a lot more struggling today I am now considering to go the
NM_CUSTOMDRAW route. I think it's a more standard and better supported
solution than the other methods that I have tried up until now.
I've found several examples of how you're 'supposed' to use
NM_CUSTOMDRAW, but as I said, whenever I try to use them I end up with
buttons that don't get drawn properly. The icons and text are there,
but moving the mouse over the buttons does nothing, and depending on
how I have implemented NM_CUSTOMDRAW, clicking may or may not work. I
agree that this is the way to go, but most of the forum posts I've
seen on NM_CUSTOMDRAW just say 'it works, just follow the MSDN
documentation.' However, that hasn't seemed to quite cut it for
me... I'm working on a few other things in parallel, but I'll keep
trying to tinker with this periodically, and I'll let you know if I
stumble on anything useful. Please do the same...
Bennett
2008-01-17 16:56:53 UTC
Permalink
Post by Bennett
Post by Francis
Post by Bennett
Post by Francis
Post by b***@gmail.com
Ok, it works a little. I created a secondtoolbaras a child control
of the firsttoolbar. However, the area occupied by thetoolbaris
black.Buttonhighlighting works though (shows a grey emptybutton).
The icons on the firsttoolbarare not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the secondtoolbarwork?
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigningbuttonimages from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the largerbutton. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So thebutton
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I've read several supposed solutions to this problem, but none of them
actually work. I'm considering moving to the approach you're using,
building a secondtoolbarin my maintoolbar, but I'm wondering first
if it actually solves the problem. How exactly are you building the
childtoolbar? Maybe we can figure this out together...
I have not yet succeeded to make it work. Due to time pressure I am
now using an image button instead that I add as a custom window to the
toolbar. I will certainly post more info when I get it to work.
RECT rc;
GetClientRect(mParentHandle, &rc);
mSubToolbar = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
NULL,
0
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| TBSTYLE_FLAT
| TBSTYLE_TRANSPARENT
//| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
,
rc.left,rc.top,100,24,
mToolbarHandle, // original toolbar
(HMENU)(INT_PTR)IDC_TOOLBAR_SUBTOOLBAR,
GetModuleHandle(0),
NULL
);
SendMessage(mSubToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)
sizeof(TBBUTTON), 0);
// Create the image list.
HIMAGELIST hImageList = ImageList_Create(80, 16, ILC_COLOR32, 10, 10);
CGdiPlusBitmapResource theBmpRes // helper class, can be found on
google
(
MAKEINTRESOURCE(IDI_TOOLBAR_LOGO),
RT_RCDATA,
mModuleHandle
);
HICON theIcon;
theBmpRes.m_pBitmap->GetHICON(&theIcon);
ImageList_AddIcon(hImageList, theIcon);
DeleteObject(theIcon);
TBBUTTON theToolbarButton;
theToolbarButton.iBitmap = 1;
theToolbarButton.idCommand = IDC_TOOLBAR_SUBTOOLBAR;
theToolbarButton.fsState = TBSTATE_ENABLED;
theToolbarButton.fsStyle = BTNS_BUTTON | BTNS_DROPDOWN;
theToolbarButton.dwData = 0;
theToolbarButton.iString = (INT_PTR)TEXT("Test");
SendMessage(mSubToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
SendMessage(mSubToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)
(LPTBBUTTON) &theToolbarButton);
SendMessage(mSubToolbar, TB_AUTOSIZE, 0, 0);
Hope this helps a bit,
Francis
I've tried using your code, but I can't get a subToolbar to appear. I
think I'm confused as to the difference between mParentHandle and
mToolbarHandle. Also, are you using MFC or ATL?
I've been trying to use NM_CUSTOMDRAW as well, but I can't seem to get
that to work. I can capture the NM_CUSTOMDRAW message, but then my
buttons just don't seem to get drawn, even when I try to just do the
default behavior.
Have you had any more luck?
After a lot more struggling today I am now considering to go the
NM_CUSTOMDRAW route. I think it's a more standard and better supported
solution than the other methods that I have tried up until now.
I've found several examples of how you're 'supposed' to use
NM_CUSTOMDRAW, but as I said, whenever I try to use them I end up with
buttons that don't get drawn properly. The icons and text are there,
but moving the mouse over the buttons does nothing, and depending on
how I have implemented NM_CUSTOMDRAW, clicking may or may not work. I
agree that this is the way to go, but most of the forum posts I've
seen on NM_CUSTOMDRAW just say 'it works, just follow the MSDN
documentation.' However, that hasn't seemed to quite cut it for
me... I'm working on a few other things in parallel, but I'll keep
trying to tinker with this periodically, and I'll let you know if I
stumble on anything useful. Please do the same...
Ok, here's my current hack solution. It will do until I can find
something more proper. I read a post somewhere where it was suggested
to set the button style to BTNS_SHOWTEXT, then add a caption
consisting of a number of spaces. If you add the proper number of
spaces, the button width will stretch to the correct size. However,
this would break if the user changed system fonts to be large or extra
large. But if you merely fix the font of the toolbar, this can't
happen. So, for now, I'm using:

HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(m_hWnd,WM_SETFONT, (WPARAM)hFont,MAKELPARAM(TRUE,0));

The next step would be to calculate the proper number of spaces to
make the caption based on the current system font. That should allow
for font size changes. Eventually, I want to try rewriting my toolbar
entirely using more modern structures (I based it on a CodeProject
article that was written a long time ago, and I have a feeling that
might contribute to some of my issues). But until I have time to do
all that, this will suffice. Still, if you come up with a more
elegant solution, please post it. Thanks.
Francis
2008-01-17 19:09:28 UTC
Permalink
Post by Bennett
Post by Bennett
Post by Francis
Post by Bennett
Post by Francis
Post by b***@gmail.com
Ok, it works a little. I created a secondtoolbaras a child control
of the firsttoolbar. However, the area occupied by thetoolbaris
black.Buttonhighlighting works though (shows a grey emptybutton).
The icons on the firsttoolbarare not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the secondtoolbarwork?
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigningbuttonimages from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the largerbutton. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So thebutton
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I've read several supposed solutions to this problem, but none of them
actually work. I'm considering moving to the approach you're using,
building a secondtoolbarin my maintoolbar, but I'm wondering first
if it actually solves the problem. How exactly are you building the
childtoolbar? Maybe we can figure this out together...
I have not yet succeeded to make it work. Due to time pressure I am
now using an image button instead that I add as a custom window to the
toolbar. I will certainly post more info when I get it to work.
RECT rc;
GetClientRect(mParentHandle, &rc);
mSubToolbar = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
NULL,
0
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| TBSTYLE_FLAT
| TBSTYLE_TRANSPARENT
//| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
,
rc.left,rc.top,100,24,
mToolbarHandle, // original toolbar
(HMENU)(INT_PTR)IDC_TOOLBAR_SUBTOOLBAR,
GetModuleHandle(0),
NULL
);
SendMessage(mSubToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)
sizeof(TBBUTTON), 0);
// Create the image list.
HIMAGELIST hImageList = ImageList_Create(80, 16, ILC_COLOR32, 10, 10);
CGdiPlusBitmapResource theBmpRes // helper class, can be found on
google
(
MAKEINTRESOURCE(IDI_TOOLBAR_LOGO),
RT_RCDATA,
mModuleHandle
);
HICON theIcon;
theBmpRes.m_pBitmap->GetHICON(&theIcon);
ImageList_AddIcon(hImageList, theIcon);
DeleteObject(theIcon);
TBBUTTON theToolbarButton;
theToolbarButton.iBitmap = 1;
theToolbarButton.idCommand = IDC_TOOLBAR_SUBTOOLBAR;
theToolbarButton.fsState = TBSTATE_ENABLED;
theToolbarButton.fsStyle = BTNS_BUTTON | BTNS_DROPDOWN;
theToolbarButton.dwData = 0;
theToolbarButton.iString = (INT_PTR)TEXT("Test");
SendMessage(mSubToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
SendMessage(mSubToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)
(LPTBBUTTON) &theToolbarButton);
SendMessage(mSubToolbar, TB_AUTOSIZE, 0, 0);
Hope this helps a bit,
Francis
I've tried using your code, but I can't get a subToolbar to appear. I
think I'm confused as to the difference between mParentHandle and
mToolbarHandle. Also, are you using MFC or ATL?
I've been trying to use NM_CUSTOMDRAW as well, but I can't seem to get
that to work. I can capture the NM_CUSTOMDRAW message, but then my
buttons just don't seem to get drawn, even when I try to just do the
default behavior.
Have you had any more luck?
After a lot more struggling today I am now considering to go the
NM_CUSTOMDRAW route. I think it's a more standard and better supported
solution than the other methods that I have tried up until now.
I've found several examples of how you're 'supposed' to use
NM_CUSTOMDRAW, but as I said, whenever I try to use them I end up with
buttons that don't get drawn properly. The icons and text are there,
but moving the mouse over the buttons does nothing, and depending on
how I have implemented NM_CUSTOMDRAW, clicking may or may not work. I
agree that this is the way to go, but most of the forum posts I've
seen on NM_CUSTOMDRAW just say 'it works, just follow the MSDN
documentation.' However, that hasn't seemed to quite cut it for
me... I'm working on a few other things in parallel, but I'll keep
trying to tinker with this periodically, and I'll let you know if I
stumble on anything useful. Please do the same...
Ok, here's my current hack solution. It will do until I can find
something more proper. I read a post somewhere where it was suggested
to set the button style to BTNS_SHOWTEXT, then add a caption
consisting of a number of spaces. If you add the proper number of
spaces, the button width will stretch to the correct size. However,
this would break if the user changed system fonts to be large or extra
large. But if you merely fix the font of the toolbar, this can't
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(m_hWnd,WM_SETFONT, (WPARAM)hFont,MAKELPARAM(TRUE,0));
The next step would be to calculate the proper number of spaces to
make the caption based on the current system font. That should allow
for font size changes. Eventually, I want to try rewriting my toolbar
entirely using more modern structures (I based it on a CodeProject
article that was written a long time ago, and I have a feeling that
might contribute to some of my issues). But until I have time to do
all that, this will suffice. Still, if you come up with a more
elegant solution, please post it. Thanks.
I don't understand this solution. Isn't the text always displayed at
the right side of the image?

Btw, your first suggestion of using multiple image lists was a good
one I think. Because you can afterwards resize the individual buttons
using TB_SETBUTTONINFO. But the problem here was the same, that the
text is always placed after the image, and its horizontal distance
from the left border of the button is always equal to the width of the
larger image. So the real problem here is positioning the text next to
the image, not the resizing of the image.

My temporary solution is even more lame. I asked our designer to
simply make a 16x16 icon for the first button :D :D

Another solution is to not use a toolbar but to position a number
CButton controls next to each other as if it is a toolbar. There is a
toolbar for Facebook called "My FB Toolbar". If you install it you can
use Spy++ or Winspector to analyze its structure.

I don't know if your toolbar also contains custom windows. Mine has a
combo box, and I had some problems with focus and keyboard input for
that control. I found a sample provided by Microsoft that was very
helpful. Just for your information if you ever need it, it's called
"KBBAR Internet Explorer Toolband" (http://support.microsoft.com/kb/
246234).

Another recent discovery for me was google codesearch (www.google.com/
codesearch). This is a great resource for finding code samples based
on real-life projects.

You may know already about these of course :)


Francis
Francis
2008-01-17 19:11:29 UTC
Permalink
Post by Bennett
Post by Bennett
Post by Francis
Post by Bennett
Post by Francis
Post by b***@gmail.com
Ok, it works a little. I created a secondtoolbaras a child control
of the firsttoolbar. However, the area occupied by thetoolbaris
black.Buttonhighlighting works though (shows a grey emptybutton).
The icons on the firsttoolbarare not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the secondtoolbarwork?
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigningbuttonimages from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the largerbutton. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So thebutton
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I've read several supposed solutions to this problem, but none of them
actually work. I'm considering moving to the approach you're using,
building a secondtoolbarin my maintoolbar, but I'm wondering first
if it actually solves the problem. How exactly are you building the
childtoolbar? Maybe we can figure this out together...
I have not yet succeeded to make it work. Due to time pressure I am
now using an image button instead that I add as a custom window to the
toolbar. I will certainly post more info when I get it to work.
RECT rc;
GetClientRect(mParentHandle, &rc);
mSubToolbar = CreateWindowEx
(
0,
TOOLBARCLASSNAME,
NULL,
0
| WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
| TBSTYLE_FLAT
| TBSTYLE_TRANSPARENT
//| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
,
rc.left,rc.top,100,24,
mToolbarHandle, // original toolbar
(HMENU)(INT_PTR)IDC_TOOLBAR_SUBTOOLBAR,
GetModuleHandle(0),
NULL
);
SendMessage(mSubToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)
sizeof(TBBUTTON), 0);
// Create the image list.
HIMAGELIST hImageList = ImageList_Create(80, 16, ILC_COLOR32, 10, 10);
CGdiPlusBitmapResource theBmpRes // helper class, can be found on
google
(
MAKEINTRESOURCE(IDI_TOOLBAR_LOGO),
RT_RCDATA,
mModuleHandle
);
HICON theIcon;
theBmpRes.m_pBitmap->GetHICON(&theIcon);
ImageList_AddIcon(hImageList, theIcon);
DeleteObject(theIcon);
TBBUTTON theToolbarButton;
theToolbarButton.iBitmap = 1;
theToolbarButton.idCommand = IDC_TOOLBAR_SUBTOOLBAR;
theToolbarButton.fsState = TBSTATE_ENABLED;
theToolbarButton.fsStyle = BTNS_BUTTON | BTNS_DROPDOWN;
theToolbarButton.dwData = 0;
theToolbarButton.iString = (INT_PTR)TEXT("Test");
SendMessage(mSubToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
SendMessage(mSubToolbar, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)
(LPTBBUTTON) &theToolbarButton);
SendMessage(mSubToolbar, TB_AUTOSIZE, 0, 0);
Hope this helps a bit,
Francis
I've tried using your code, but I can't get a subToolbar to appear. I
think I'm confused as to the difference between mParentHandle and
mToolbarHandle. Also, are you using MFC or ATL?
I've been trying to use NM_CUSTOMDRAW as well, but I can't seem to get
that to work. I can capture the NM_CUSTOMDRAW message, but then my
buttons just don't seem to get drawn, even when I try to just do the
default behavior.
Have you had any more luck?
After a lot more struggling today I am now considering to go the
NM_CUSTOMDRAW route. I think it's a more standard and better supported
solution than the other methods that I have tried up until now.
I've found several examples of how you're 'supposed' to use
NM_CUSTOMDRAW, but as I said, whenever I try to use them I end up with
buttons that don't get drawn properly. The icons and text are there,
but moving the mouse over the buttons does nothing, and depending on
how I have implemented NM_CUSTOMDRAW, clicking may or may not work. I
agree that this is the way to go, but most of the forum posts I've
seen on NM_CUSTOMDRAW just say 'it works, just follow the MSDN
documentation.' However, that hasn't seemed to quite cut it for
me... I'm working on a few other things in parallel, but I'll keep
trying to tinker with this periodically, and I'll let you know if I
stumble on anything useful. Please do the same...
Ok, here's my current hack solution. It will do until I can find
something more proper. I read a post somewhere where it was suggested
to set the button style to BTNS_SHOWTEXT, then add a caption
consisting of a number of spaces. If you add the proper number of
spaces, the button width will stretch to the correct size. However,
this would break if the user changed system fonts to be large or extra
large. But if you merely fix the font of the toolbar, this can't
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(m_hWnd,WM_SETFONT, (WPARAM)hFont,MAKELPARAM(TRUE,0));
The next step would be to calculate the proper number of spaces to
make the caption based on the current system font. That should allow
for font size changes. Eventually, I want to try rewriting my toolbar
entirely using more modern structures (I based it on a CodeProject
article that was written a long time ago, and I have a feeling that
might contribute to some of my issues). But until I have time to do
all that, this will suffice. Still, if you come up with a more
elegant solution, please post it. Thanks.
And I forgot, the sourgeforge is also a great resource, just like
google's codesearch.
Christian ASTOR
2008-01-17 19:37:35 UTC
Permalink
Still, if you come up with a more elegant solution, please post it.
The standard way since Win 3.1 is to embed a (OD) button (or a Toolbar
since Win 95) ...
(WM_NOTIFY, if used, must just be correct)
Francis
2008-01-18 10:07:55 UTC
Permalink
Post by Christian ASTOR
Still, if you come up with a more elegant solution, please post it.
The standard way since Win 3.1 is to embed a (OD) button (or a Toolbar
since Win 95) ...
(WM_NOTIFY, if used, must just be correct)
I wonder how the Google toolbar for IE is made. The first button is
has a larger icon, and Spy++ does not show it as a separate control.
Francis
2008-01-15 01:57:03 UTC
Permalink
Post by b***@gmail.com
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigning button images from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the larger button. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So the button
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I'm very interested in the progression of this issue, as I'm having
the exact same problem. I've been trying to approach it using
imagelists, then assigning button images from those imagelists. What
I've found out is that each imagelist can only hold images of 1 size,
so I have to make a second imagelist for the larger button. You then
send a CCM_SETVERSION message with a parameter of 5, to allow for
multiple imagelists. This part works great, and the images all show
up with the correct size, but the problem is that all buttons are
constrained to be the size of the first image used. So the button
under the large image only occupies a fraction of the image, and the
rest of the buttons cover the rest of the image.
I've been experimenting with the multiple image list solution. After
you have added the buttons to the toolbar you can change the sizes of
buttons:

TBBUTTONINFO tbButtonInfo;
tbButtonInfo.cbSize = sizeof(TBBUTTONINFO);
tbButtonInfo.dwMask = TBIF_SIZE;
SendMessage
(
mToolbarHandle,
TB_GETBUTTONINFO,
(WPARAM)(INT)item->id(),
(LPARAM)(LPTBBUTTONINFO)&tbButtonInfo
);
tbButtonInfo.cx = 16;

SendMessage
(
mToolbarHandle,
TB_SETBUTTONINFO,
(WPARAM)(INT)item->id(),
(LPARAM)(LPTBBUTTONINFO)&tbButtonInfo
);


However, even now it is STILL not ok. Because the buttons that have
text will now not be rendered correctly. The text will have an
horizontal offset of 80 pixels, far away from the 16x16 icons.
Resizing it will only cut off the text, and not reposition it.

I have an idea, it's a little crazy, but I've spent some time trying
it out anyway. It is possible to convert text to bitmaps. So it would
be possible to compose our icons from the icon + text. We can then
make the bitmaps so that the text is always next to its icon. These
bitmaps are then used as toolbar icons. However, alpha channel info
will be lost, so somehow this should be restored. And that's where I
am stuck.

This is the code that I use for generating the bitmaps:

SIZE GetTextSize(HWND hWnd, const std::wstring & inString)
{
// get the size in pixels for the given text and font
SIZE theResult;
theResult.cx = 0;
theResult.cy = 0;

HDC hDC = GetDC(hWnd);
SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
GetTextExtentPoint32(hDC, (LPWSTR)inString.c_str(),
(int)inString.size(), &theResult);
ReleaseDC(hWnd, hDC);
return theResult;
}

//1.Create compatible DC ( CreateCompatibleDC() )
//2.Create compatible Bitmap ( CreateCompatibleBitamp() )
//3.Select Bitmap into DC ( SelectObject(...) )
//4.Draw at DC ( TextOut() )
//5.Unselect Bitmap (use SelectObject with result of previous calling
SelectObject)
//6.Delete DC ( DeleteDC() )

Following snippit uses Gdiplus::Bitmap object that stores the current
icon (can easily be created) and itemText is the string containing the
text that goes with the current icon:

SIZE size = GetTextSize(mToolbarHandle, itemText);

size.cy = itemBitmapSize.cy;
HDC hDC = GetDC(mToolbarHandle);
HDC hCompatibleDC = CreateCompatibleDC(hDC);
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, size.cx +
itemBitmapSize.cx, size.cy);
HGDIOBJ hPrevGdiObj = SelectObject(hCompatibleDC, hBitmap);
SelectObject(hCompatibleDC, GetStockObject(DEFAULT_GUI_FONT));
Gdiplus::Graphics graphics(hCompatibleDC);
graphics.DrawImage
(
gdiplusBitmap,
(Gdiplus::REAL)0,
(Gdiplus::REAL)0,
(Gdiplus::REAL)gdiplusBitmap->GetWidth(),
(Gdiplus::REAL)gdiplusBitmap->GetHeight()
);
TextOut(hCompatibleDC, size.cx, 0, (LPWSTR)itemText.c_str(),
(int)itemText.size());
SelectObject(hDC, hPrevGdiObj);

item->setBitmap(hBitmap, hDC);
DeleteDC(hDC);
bitmapSize.cx += size.cx;

Now this actually gives some visible output. However, the bitmaps have
black background (transparency is gone) and the parts where the text
is printed have white background. So there is still some work needed
to unify the background colors, and to restore transparency so that
they show nicely in the toolbar.

This is some work, and a bit dirty.. but at this point this looks like
a more hopeful solution than the subtoolbar idea.


Francis
Christian ASTOR
2008-01-15 06:14:52 UTC
Permalink
Post by Francis
Ok, it works a little. I created a second toolbar as a child control
of the first toolbar. However, the area occupied by the toolbar is
black. Button highlighting works though (shows a grey empty button).
The icons on the first toolbar are not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the second toolbar work?
No, there is nothing to do.
It works for me from a basic Win32 app...
Francis
2008-01-15 17:42:36 UTC
Permalink
Post by Christian ASTOR
Post by Francis
Ok, it works a little. I created a second toolbar as a child control
of the first toolbar. However, the area occupied by the toolbar is
black. Button highlighting works though (shows a grey empty button).
The icons on the first toolbar are not harmed and buttons work
perfectly.
Do I need to override WM_PAINT messages or something in order to make
rendering for the second toolbar work?
No, there is nothing to do.
It works for me from a basic Win32 app...
I made some more progress yesterday. I wrote about it in reply 8 on
this thread. It didn't work well though. I am considering using custom
draw methods.
Continue reading on narkive:
Loading...