I've managed to add a button to the IE toolbar, by implementing
IOleCommandTarget and doing some registry manipulation. It's not very
difficult, really.
My problem is twofold:
1) I'd like my button to be a dropdown button (with menuitems),
rather than a simple pushbutton.
2) Additionally I'd like to change the icon of the button. I don't mean the
"hot"
and "cold" icons, which depend on whether the mouse cursor hovers over the
button. I mean I'd like to change the button icon when some other condition
occurs, like a change in the current web page.
My question is: Do I need to use ShellBrowser.SetToolbarItems to
change my button in this manner? If so, how? It seems to me, this method
is only useful when I've created my own toolbar, not when I'm adding
to the standard toolbar.
Troels
If you don't want the explanation but just some working code,
I'll release a component in the near future (well, during the next
month), which allows you to add BHOs and toolbar buttons to IE.
I'll let you all know when it's done. Full src and demos will be
available.
As for the questions:
-------------------------------------------
> 1) I'd like my button to be a dropdown button (with menuitems),
> rather than a simple pushbutton.
This article describes how to do it:
http://msdn.microsoft.com/library/en-us/dhtmltechcol/cols/dnwebteam/webteam11062001.asp
(see Magic Lantern section).
However, you have to modify the sample somewhat to make the
check/uncheck feature work. Here's the code I use in the Exec method,
after the various AppendMenu calls:
GetCursorPos(pt);
hWndToolbar := WindowFromPoint(pt);
// Get number of buttons on the toolbar this button belongs to
nButtonCount := SendMessage(hWndToolbar, TB_BUTTONCOUNT, 0, 0);
OldButtonStyle := SendMessage(hWndToolbar, TB_GETSTYLE, 0, 0);
// Find this button by finding which of the buttons is under the cursor
nTargetButton := -1;
ScreenToClient(hWndToolbar, pt);
for I := 0 to nButtonCount -1 do
begin
if SendMessage(hWndToolbar, TB_GETITEMRECT, I, Integer(@rect)) <> 0 then
if PtInRect(rect, pt) then
begin
nTargetButton := I;
Break;
end;
end;
if nTargetButton <> -1 then
begin
tbbi.idCommand := 1111; // Needs to have a unique value for various
TB_XXX messages to work
SendMessage(hWndToolbar, TB_SETCMDID, nTargetButton, tbbi.idCommand);
SendMessage(hWndToolbar, TB_SETSTYLE, 0, OldButtonStyle or
TBSTYLE_CHECKGROUP);
// Make the button appear pressed
SendMessage(hWndToolbar, TB_CHECKBUTTON, tbbi.idCommand, Integer(True));
end;
......
// Display and track the menu
......
if nTargetButton <> -1 then
begin
// Make the button appear not pressed
SendMessage(hWndToolbar, TB_CHECKBUTTON, tbbi.idCommand,
Integer(False));
SendMessage(hWndToolbar, TB_SETSTYLE, 0, OldButtonStyle);
end;
And here are the vars you'll need:
var
hWndToolbar: HWND;
tbbi: TBBUTTONINFO;
pt: TPoint;
rect: TRect;
nButtonCount, nTargetButton: Integer;
OldButtonStyle: Integer;
uses
Windows, CommCtrl;
Still, the button is not a real dropdown button - it doesn't have an
arrow, and it's too narrow. The solution to this would be to not use
IOleCommandTarget and instead simply make the BHO implement
IDispatch, then call TB_ADDBUTTONS and TB_ADDBITMAP
in the IDispatch.SetSite method. The problem with this approach is
you need the handle to the toolbar, which we so far have found
by using a hack.
I'll look more into this problem. I suppose it's possible to find
the toolbar handle somehow.
-------------------------------------------
> 2) I'd like to change the icon of the button. I don't mean the "hot"
> and "cold" icons, which depend on whether the mouse cursor hovers over the
> button. I mean I'd like to change the button icon when some other
> condition
> occurs, like a change in the current web page.
This is indeed possible. I tried many different approaches but found
only one way to make it work.
The hWndToolbar and idCommand parameters correspond to the
hWndToolbar and tbbi.idCommand vars from before.
procedure ChangeButtonImage(hWndToolbar: HWND; idCommand: Integer);
var
AddedBitmap, AddedHotBitmap: Integer;
hIml, hImlHot: HIMAGELIST;
hBmp, hBmpHot: HBITMAP;
begin
// Load bitmaps from resource file
hBmp := LoadBitmap(HInstance, PChar(1616));
hBmpHot := LoadBitmap(HInstance, PChar(16162));
// Get imagelists of toolbar
hIml := SendMessage(hWndToolbar, TB_GETIMAGELIST, 0, 0);
hImlHot := SendMessage(hWndToolbar, TB_GETHOTIMAGELIST, 0, 0);
// Cold icon
AddedBitmap := ImageList_Add(hIml, hBmp, 0);
SendMessage(hWndToolbar, TB_CHANGEBITMAP, idCommand,
MakeLParam(AddedBitmap, 0));
// Hot icon
AddedHotBitmap := ImageList_Add(hImlHot, hBmpHot, 0);
SendMessage(hWndToolbar, TB_CHANGEBITMAP, idCommand,
MakeLParam(AddedHotBitmap, 0));
// Clean up
DeleteObject(hBmp);
DeleteObject(hBmpHot);
end;
-------------------------------------------
That's all, folks.
Troels