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.



Reply via email to