I have been struggling with getting drop-down menus from toolbar buttons
working. I'm nearly there, but not quite. I'll post separately to
share my finding once I have some tidier working code. I've found a
number of problems that need fixing in the XS source (some related to
drop-down menus, others that I have stumbled across while researching
toolbars in general). Here's a quick summary with patches below (I've
compiled and checked these changes, but don't have CVS write at
sourceforge, so would appreciate it if someone else could validate them
and check them in).
Cheers,
Rob.
Summary of issues:
(1) Toolbar TBN_DROPDOWN messages are not being delivered to the
ButtonClick handler as the switch in Toolbar_onEvent for WM_NOTIFY
messages is incorrect.
(2) SetButtonSize() has incorrect method name in documentation.
(3) GetBitmap(), GetButtonInfo() and SetButtonInfo() are incorrectly
documented as taking a button index as a parameter, when they actually
take a command ID.
(4) SetButtonInfo() always fails, as the button.cbSize element of the
parameter structure is not set.
(5) GetButtonInfo() returns values other than 0 or 1 for some of the
boolean elements of its hash
(6) GetButtonInfo() fails when returning information for the first
button on the toolbar, as the TB_GETBUTTONINFO message returns the
(zero-based) button index and not true/false for success/failure.
Actually need to check return value as -1 for failure.
(7) As a side effect of (1) I discovered that Hook() never delivers
WM_NOTIFY to the handler callbacks. This is due to a similar bug as (1)
where the message code is being taken from the wrong parameter:
HIWORD(wparam) (which is correct for WM_COMMAND messages), rather than
((LPNMHDR) lparam)->code (which is what should be used for WM_NOTIFY
messages).
diff -c -r1.8 GUI_MessageLoops.cpp
*** GUI_MessageLoops.cpp 29 Sep 2004 21:17:56 -0000 1.8
--- GUI_MessageLoops.cpp 23 Mar 2005 21:09:14 -0000
***************
*** 296,302 ****
}
if (childud->avHooks != NULL)
! DoHook(NOTXSCALL childud, (UINT) HIWORD(wParam),
wParam, lParam, &PerlResult, WM_NOTIFY);
if(childud->forceResult != 0) {
perlud->forceResult = childud->forceResult;
--- 296,302 ----
}
if (childud->avHooks != NULL)
! DoHook(NOTXSCALL childud, (UINT) (((LPNMHDR)
lParam)->code), wParam, lParam, &PerlResult, WM_NOTIFY);
if(childud->forceResult != 0) {
perlud->forceResult = childud->forceResult;
diff -c -r1.3 Toolbar.xs
*** Toolbar.xs 4 Apr 2004 18:01:34 -0000 1.3
--- Toolbar.xs 23 Mar 2005 20:56:48 -0000
***************
*** 86,92 ****
{
LPNMTOOLBAR tbn = (LPNMTOOLBAR) lParam;
! switch(HIWORD(wParam)) {
case TBN_DROPDOWN:
PerlResult = DoEvent(NOTXSCALL perlud,
PERLWIN32GUI_NEM_CONTROL1, "ButtonClick",
PERLWIN32GUI_ARGTYPE_LONG, (LONG) tbn->iItem,
--- 86,92 ----
{
LPNMTOOLBAR tbn = (LPNMTOOLBAR) lParam;
! switch(tbn->hdr.code) {
case TBN_DROPDOWN:
PerlResult = DoEvent(NOTXSCALL perlud,
PERLWIN32GUI_NEM_CONTROL1, "ButtonClick",
PERLWIN32GUI_ARGTYPE_LONG, (LONG) tbn->iItem,
***************
*** 147,152 ****
--- 147,153 ----
###########################################################################
# (@)METHOD:AddButtons(NUMBER, (BITMAP, COMMAND, STATE, STYLE,
STRING) ...)
# Adds buttons to the toolbar. Note that BITMAP, COMMAND, STATE,
STYLE and
+
# STRING are all integers. BITMAP specifies the bitmap index to
use for the
# button (see AddBitmap() or SetImageList()), COMMAND specifies
the value
# sent to the ButtonClick event when the button is clicked, STATE
sets state
***************
*** 410,417 ****
RETVAL
###########################################################################
! # (@)METHOD:GetBitmap(BUTTON)
! # Retrieves the index of the bitmap associated with a button in a
toolbar.
LRESULT
GetBitmap(handle, button)
HWND handle
--- 411,418 ----
RETVAL
###########################################################################
! # (@)METHOD:GetBitmap(COMMAND)
! # Retrieves the index of the bitmap associated with the specified
command identifier.
LRESULT
GetBitmap(handle, button)
HWND handle
***************
*** 458,465 ****
XSRETURN_UNDEF;
###########################################################################
! # (@)METHOD:GetButtonInfo(BUTTON)
! # Retrieves information about the specified button in a toolbar.
void
GetButtonInfo(handle, index)
HWND handle
--- 459,466 ----
XSRETURN_UNDEF;
###########################################################################
! # (@)METHOD:GetButtonInfo(COMMAND)
! # Retrieves information about the button associated with the
specified command identifier.
void
GetButtonInfo(handle, index)
HWND handle
***************
*** 474,480 ****
button.dwMask = TBIF_COMMAND | TBIF_IMAGE | TBIF_LPARAM |
TBIF_SIZE | TBIF_STATE | TBIF_STYLE | TBIF_TEXT;
button.pszText = Text;
button.cchText = 1024;
! if (SendMessage(handle, TB_GETBUTTONINFO, (WPARAM) index, (LPARAM)
&button)) {
EXTEND(SP, 28);
XST_mPV( 0, "-command");
XST_mIV( 1, button.idCommand);
--- 475,481 ----
button.dwMask = TBIF_COMMAND | TBIF_IMAGE | TBIF_LPARAM |
TBIF_SIZE | TBIF_STATE | TBIF_STYLE | TBIF_TEXT;
button.pszText = Text;
button.cchText = 1024;
! if (SendMessage(handle, TB_GETBUTTONINFO, (WPARAM) index, (LPARAM)
&button) != -1) {
EXTEND(SP, 28);
XST_mPV( 0, "-command");
XST_mIV( 1, button.idCommand);
***************
*** 489,509 ****
XST_mPV(10, "-width");
XST_mIV(11, button.cx);
XST_mPV(12, "-checked");
! XST_mIV(13, (button.fsState & TBSTATE_CHECKED));
XST_mPV(14, "-ellipses");
! XST_mIV(15, (button.fsState & TBSTATE_ELLIPSES));
XST_mPV(16, "-enabled");
! XST_mIV(17, (button.fsState & TBSTATE_ENABLED));
XST_mPV(18, "-hidden");
! XST_mIV(19, (button.fsState & TBSTATE_HIDDEN));
XST_mPV(20, "-grayed");
! XST_mIV(21, (button.fsState & TBSTATE_INDETERMINATE));
XST_mPV(22, "-marked");
! XST_mIV(23, (button.fsState & TBSTATE_MARKED));
XST_mPV(24, "-pressed");
! XST_mIV(25, (button.fsState & TBSTATE_PRESSED));
XST_mPV(26, "-wrap");
! XST_mIV(27, (button.fsState & TBSTATE_WRAP));
XSRETURN(28);
}
else
--- 490,510 ----
XST_mPV(10, "-width");
XST_mIV(11, button.cx);
XST_mPV(12, "-checked");
! XST_mIV(13, (button.fsState & TBSTATE_CHECKED)==TBSTATE_CHECKED);
XST_mPV(14, "-ellipses");
! XST_mIV(15, (button.fsState &
TBSTATE_ELLIPSES)==TBSTATE_ELLIPSES);
XST_mPV(16, "-enabled");
! XST_mIV(17, (button.fsState & TBSTATE_ENABLED)==TBSTATE_ENABLED);
XST_mPV(18, "-hidden");
! XST_mIV(19, (button.fsState & TBSTATE_HIDDEN)==TBSTATE_HIDDEN);
XST_mPV(20, "-grayed");
! XST_mIV(21, (button.fsState &
TBSTATE_INDETERMINATE)==TBSTATE_INDETERMINATE);
XST_mPV(22, "-marked");
! XST_mIV(23, (button.fsState & TBSTATE_MARKED)==TBSTATE_MARKED);
XST_mPV(24, "-pressed");
! XST_mIV(25, (button.fsState & TBSTATE_PRESSED)==TBSTATE_PRESSED);
XST_mPV(26, "-wrap");
! XST_mIV(27, (button.fsState & TBSTATE_WRAP)==TBSTATE_WRAP);
XSRETURN(28);
}
else
***************
*** 1096,1103 ****
RETVAL
###########################################################################
! # (@)METHOD:SetButtonInfo(BUTTON, %OPTIONS)
! # Sets the information for an existing button in a toolbar.
#
# B<%OPTIONS> :
# -command => ID
--- 1097,1104 ----
RETVAL
###########################################################################
! # (@)METHOD:SetButtonInfo(COMMAND, %OPTIONS)
! # Sets the information for the button associated with the
specified command identifier.
#
# B<%OPTIONS> :
# -command => ID
***************
*** 1139,1144 ****
--- 1140,1146 ----
unsigned int tlen;
CODE:
ZeroMemory(&button, sizeof(TBBUTTONINFO));
+ button.cbSize = sizeof(TBBUTTONINFO);
next_i = -1;
for(i = 2; i < items; i++) {
if(next_i == -1) {
***************
*** 1239,1245 ****
RETVAL
###########################################################################
! # (@)METHOD:SetBitmapSize([X=24, Y=22])
# Sets the size of the buttons to be added to a toolbar.
# The size can be set only before adding any bitmaps to the toolbar.
# If an application does not explicitly set the buttons size, the
size defaults to 24 by 22 pixels.
--- 1241,1247 ----
RETVAL
###########################################################################
! # (@)METHOD:SetButtonSize([X=24, Y=22])
# Sets the size of the buttons to be added to a toolbar.
# The size can be set only before adding any bitmaps to the toolbar.
# If an application does not explicitly set the buttons size, the
size defaults to 24 by 22 pixels.