\r
#define DEFPAD_CX 7\r
#define DEFPAD_CY 6\r
+#define DEFLISTGAP 4\r
+\r
+/* vertical padding used in list mode when image is present */\r
+#define LISTPAD_CY 9\r
\r
-/* gap between border of button and text/image */\r
-#define OFFSET_X 1\r
-#define OFFSET_Y 1\r
/* how wide to treat the bitmap if it isn't present */\r
-#define LIST_IMAGE_ABSENT_WIDTH 2\r
+#define NONLIST_NOTEXT_OFFSET 2\r
\r
#define TOOLBAR_NOWHERE (-1)\r
\r
#define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)\r
#define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)\r
\r
-static inline int TOOLBAR_GetListTextOffset(TOOLBAR_INFO *infoPtr, INT iListGap)\r
-{\r
- return GetSystemMetrics(SM_CXEDGE) + iListGap - infoPtr->szPadding.cx/2;\r
-}\r
-\r
/* Used to find undocumented extended styles */\r
#define TBSTYLE_EX_ALL (TBSTYLE_EX_DRAWDDARROWS | \\r
TBSTYLE_EX_UNDOC1 | \\r
}\r
\r
\r
+static inline BOOL\r
+TOOLBAR_IsValidImageList(TOOLBAR_INFO *infoPtr, INT index)\r
+{\r
+ HIMAGELIST himl = GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr, index));\r
+ return (himl != NULL) && (ImageList_GetImageCount(himl) > 0);\r
+}\r
+\r
+\r
/***********************************************************************\r
* TOOLBAR_GetImageListForDrawing\r
*\r
}\r
\r
\r
-/***********************************************************************\r
-* TOOLBAR_TestImageExist\r
-*\r
-* This function is similar to TOOLBAR_GetImageListForDrawing, except it does not\r
-* return the image list. The I_IMAGECALLBACK functionality is implemented.\r
-*/\r
-static BOOL\r
-TOOLBAR_TestImageExist (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HIMAGELIST himl)\r
-{\r
- INT index;\r
-\r
- if (!himl) return FALSE;\r
-\r
- if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {\r
- if (btnPtr->iBitmap == I_IMAGENONE) return FALSE;\r
- ERR("index %d is not valid, max %d\n",\r
- btnPtr->iBitmap, infoPtr->nNumBitmaps);\r
- return FALSE;\r
- }\r
-\r
- if ((index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) {\r
- if ((index == I_IMAGECALLBACK) ||\r
- (index == I_IMAGENONE)) return FALSE;\r
- ERR("TBN_GETDISPINFO returned invalid index %d\n",\r
- index);\r
- return FALSE;\r
- }\r
- return TRUE;\r
-}\r
-\r
-\r
static void\r
TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc, TOOLBAR_INFO *infoPtr)\r
{\r
\r
/* draws a blank frame for a toolbar button */\r
static void\r
-TOOLBAR_DrawFrame(const TOOLBAR_INFO *infoPtr, BOOL flat, const NMTBCUSTOMDRAW *tbcd)\r
+TOOLBAR_DrawFrame(const TOOLBAR_INFO *infoPtr, const NMTBCUSTOMDRAW *tbcd)\r
{\r
HDC hdc = tbcd->nmcd.hdc;\r
RECT rc = tbcd->nmcd.rc;\r
if (infoPtr->dwItemCDFlag & TBCDRF_NOEDGES)\r
return;\r
\r
- if (flat)\r
+ if (infoPtr->dwStyle & TBSTYLE_FLAT)\r
{\r
if (pressed_look)\r
DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT);\r
\r
rc = btnPtr->rect;\r
CopyRect (&rcArrow, &rc);\r
- CopyRect(&rcBitmap, &rc);\r
\r
/* get a pointer to the text */\r
lpText = TOOLBAR_GetText(infoPtr, btnPtr);\r
rcArrow.left = right;\r
}\r
\r
- /* copy text rect after adjusting for drop-down arrow\r
- * so that text is centred in the rectangle not containing\r
+ /* copy text & bitmap rects after adjusting for drop-down arrow\r
+ * so that text & bitmap is centred in the rectangle not containing\r
* the arrow */\r
CopyRect(&rcText, &rc);\r
+ CopyRect(&rcBitmap, &rc);\r
\r
/* Center the bitmap horizontally and vertically */\r
if (dwStyle & TBSTYLE_LIST)\r
- rcBitmap.left += GetSystemMetrics(SM_CXEDGE);\r
+ {\r
+ if (lpText &&\r
+ infoPtr->nMaxTextRows > 0 &&\r
+ (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) ||\r
+ (btnPtr->fsStyle & BTNS_SHOWTEXT)) )\r
+ rcBitmap.left += GetSystemMetrics(SM_CXEDGE) + infoPtr->szPadding.cx / 2;\r
+ else\r
+ rcBitmap.left += GetSystemMetrics(SM_CXEDGE) + infoPtr->iListGap / 2;\r
+ }\r
else\r
- rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;\r
+ rcBitmap.left += (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;\r
\r
- if(lpText)\r
- rcBitmap.top+= GetSystemMetrics(SM_CYEDGE);\r
- else\r
- rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;\r
+ rcBitmap.top += infoPtr->szPadding.cy / 2;\r
\r
- TRACE("iBitmap: %d, start=(%ld,%ld) w=%d, h=%d\n",\r
+ TRACE("iBitmap=%d, start=(%ld,%ld) w=%d, h=%d\n",\r
btnPtr->iBitmap, rcBitmap.left, rcBitmap.top,\r
infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);\r
- TRACE ("iString: %x\n", btnPtr->iString);\r
- TRACE ("Stringtext: %s\n", debugstr_w(lpText));\r
+ TRACE("Text=%s\n", debugstr_w(lpText));\r
+ TRACE("iListGap=%d, padding = { %ld, %ld }\n", infoPtr->iListGap, infoPtr->szPadding.cx, infoPtr->szPadding.cy);\r
\r
- /* draw text */\r
- if (lpText) {\r
- rcText.left += GetSystemMetrics(SM_CXEDGE) + OFFSET_X;\r
- rcText.right -= GetSystemMetrics(SM_CXEDGE) + OFFSET_X;\r
- if (GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr,btnPtr->iBitmap)) &&\r
- TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))\r
+ /* calculate text position */\r
+ if (lpText)\r
+ {\r
+ rcText.left += GetSystemMetrics(SM_CXEDGE);\r
+ rcText.right -= GetSystemMetrics(SM_CXEDGE);\r
+ if (dwStyle & TBSTYLE_LIST)\r
{\r
- if (dwStyle & TBSTYLE_LIST)\r
- rcText.left += infoPtr->nBitmapWidth + TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap);\r
- else\r
- rcText.top += GetSystemMetrics(SM_CYEDGE) + OFFSET_Y + infoPtr->nBitmapHeight + infoPtr->szPadding.cy/2;\r
+ if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))\r
+ rcText.left += infoPtr->nBitmapWidth + infoPtr->iListGap + 2;\r
}\r
else\r
- if (dwStyle & TBSTYLE_LIST)\r
- rcText.left += LIST_IMAGE_ABSENT_WIDTH + TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap);\r
-\r
- if (!(infoPtr->dwItemCDFlag & TBCDRF_NOOFFSET) &&\r
- (btnPtr->fsState & (TBSTATE_PRESSED | TBSTATE_CHECKED)))\r
- OffsetRect(&rcText, 1, 1);\r
+ {\r
+ if (ImageList_GetImageCount(GETDEFIMAGELIST(infoPtr, 0)) > 0)\r
+ rcText.top += infoPtr->szPadding.cy/2 + infoPtr->nBitmapHeight + 1;\r
+ else\r
+ rcText.top += infoPtr->szPadding.cy/2 + 2;\r
+ }\r
}\r
\r
/* Initialize fields in all cases, because we use these later\r
goto FINALNOTIFY;\r
}\r
\r
+ if (!(infoPtr->dwItemCDFlag & TBCDRF_NOOFFSET) &&\r
+ (btnPtr->fsState & (TBSTATE_PRESSED | TBSTATE_CHECKED)))\r
+ OffsetRect(&rcText, 1, 1);\r
+\r
if (!(tbcd.nmcd.uItemState & CDIS_HOT) && \r
((tbcd.nmcd.uItemState & CDIS_CHECKED) || (tbcd.nmcd.uItemState & CDIS_INDETERMINATE)))\r
TOOLBAR_DrawPattern (&rc, &tbcd);\r
}\r
}\r
\r
- TOOLBAR_DrawFrame(infoPtr, dwStyle & TBSTYLE_FLAT, &tbcd);\r
+ TOOLBAR_DrawFrame(infoPtr, &tbcd);\r
\r
if (drawSepDropDownArrow)\r
TOOLBAR_DrawSepDDArrow(infoPtr, &tbcd, &rcArrow, btnPtr->bDropDownPressed);\r
}\r
\r
\r
+/***********************************************************************\r
+* TOOLBAR_MeasureButton\r
+*\r
+* Calculates the width and height required for a button. Used in\r
+* TOOLBAR_CalcToolbar to set the all-button width and height and also for\r
+* the width of buttons that are autosized.\r
+*\r
+* Note that it would have been rather elegant to use one piece of code for\r
+* both the laying out of the toolbar and for controlling where button parts\r
+* are drawn, but the native control has inconsistencies between the two that\r
+* prevent this from being effectively. These inconsistencies can be seen as\r
+* artefacts where parts of the button appear outside of the bounding button\r
+* rectangle.\r
+*\r
+* There are several cases for the calculation of the button dimensions and\r
+* button part positioning:\r
+*\r
+* List\r
+* ====\r
+*\r
+* With Bitmap:\r
+*\r
+* +--------------------------------------------------------+ ^\r
+* | ^ ^ | |\r
+* | | pad.cy / 2 | centred | |\r
+* | pad.cx/2 + cxedge +--------------+ +------------+ | | DEFPAD_CY +\r
+* |<----------------->| nBitmapWidth | | Text | | | max(nBitmapHeight, szText.cy)\r
+* | |<------------>| | | | |\r
+* | +--------------+ +------------+ | |\r
+* |<-------------------------------------->| | |\r
+* | cxedge + iListGap + nBitmapWidth + 2 |<-----------> | |\r
+* | szText.cx | |\r
+* +--------------------------------------------------------+ -\r
+* <-------------------------------------------------------->\r
+* 2*cxedge + nBitmapWidth + iListGap + szText.cx + pad.cx\r
+*\r
+* Without Bitmap (I_IMAGENONE):\r
+*\r
+* +-----------------------------------+ ^\r
+* | ^ | |\r
+* | | centred | | LISTPAD_CY +\r
+* | +------------+ | | szText.cy\r
+* | | Text | | |\r
+* | | | | |\r
+* | +------------+ | |\r
+* |<----------------->| | |\r
+* | cxedge |<-----------> | |\r
+* | szText.cx | |\r
+* +-----------------------------------+ -\r
+* <----------------------------------->\r
+* szText.cx + pad.cx\r
+*\r
+* Without text:\r
+*\r
+* +--------------------------------------+ ^\r
+* | ^ | |\r
+* | | padding.cy/2 | | DEFPAD_CY +\r
+* | +------------+ | | nBitmapHeight\r
+* | | Bitmap | | |\r
+* | | | | |\r
+* | +------------+ | |\r
+* |<------------------->| | |\r
+* | cxedge + iListGap/2 |<-----------> | |\r
+* | nBitmapWidth | |\r
+* +--------------------------------------+ -\r
+* <-------------------------------------->\r
+* 2*cxedge + nBitmapWidth + iListGap\r
+*\r
+* Non-List\r
+* ========\r
+*\r
+* With bitmap:\r
+*\r
+* +-----------------------------------+ ^\r
+* | ^ | |\r
+* | | pad.cy / 2 | | nBitmapHeight +\r
+* | - | | szText.cy +\r
+* | +------------+ | | DEFPAD_CY + 1\r
+* | centred | Bitmap | | |\r
+* |<----------------->| | | |\r
+* | +------------+ | |\r
+* | ^ | |\r
+* | 1 | | |\r
+* | - | |\r
+* | centred +---------------+ | |\r
+* |<--------------->| Text | | |\r
+* | +---------------+ | |\r
+* +-----------------------------------+ -\r
+* <----------------------------------->\r
+* pad.cx + max(nBitmapWidth, szText.cx)\r
+*\r
+* Without bitmaps (NULL imagelist or ImageList_GetImageCount() = 0):\r
+*\r
+* +---------------------------------------+ ^\r
+* | ^ | |\r
+* | | 2 + pad.cy / 2 | |\r
+* | - | | szText.cy +\r
+* | centred +-----------------+ | | pad.cy + 2\r
+* |<--------------->| Text | | |\r
+* | +-----------------+ | |\r
+* | | |\r
+* +---------------------------------------+ -\r
+* <--------------------------------------->\r
+* 2*cxedge + pad.cx + szText.cx\r
+*\r
+* Without text:\r
+* As for with bitmaps, but with szText.cx zero.\r
+*/\r
+static inline SIZE TOOLBAR_MeasureButton(TOOLBAR_INFO *infoPtr, SIZE sizeString, BOOL bHasBitmap, BOOL bValidImageList)\r
+{\r
+ SIZE sizeButton;\r
+ if (infoPtr->dwStyle & TBSTYLE_LIST)\r
+ {\r
+ /* set button height from bitmap / text height... */\r
+ sizeButton.cy = max((bHasBitmap ? infoPtr->nBitmapHeight : 0),\r
+ sizeString.cy);\r
+\r
+ /* ... add on the necessary padding */\r
+ if (bValidImageList)\r
+ {\r
+ if (bHasBitmap)\r
+ sizeButton.cy += DEFPAD_CY;\r
+ else\r
+ sizeButton.cy += LISTPAD_CY;\r
+ }\r
+ else\r
+ sizeButton.cy += infoPtr->szPadding.cy;\r
+\r
+ /* calculate button width */\r
+ if (bHasBitmap)\r
+ {\r
+ sizeButton.cx = 2*GetSystemMetrics(SM_CXEDGE) +\r
+ infoPtr->nBitmapWidth + infoPtr->iListGap;\r
+ if (sizeString.cx > 0)\r
+ sizeButton.cx += sizeString.cx + infoPtr->szPadding.cx;\r
+ }\r
+ else\r
+ sizeButton.cx = sizeString.cx + infoPtr->szPadding.cx;\r
+ }\r
+ else\r
+ {\r
+ if (bHasBitmap)\r
+ {\r
+ sizeButton.cy = infoPtr->nBitmapHeight + 1 +\r
+ sizeString.cy + DEFPAD_CY;\r
+ sizeButton.cx = infoPtr->szPadding.cx +\r
+ max(sizeString.cx, infoPtr->nBitmapWidth);\r
+ }\r
+ else\r
+ {\r
+ sizeButton.cy = sizeString.cy + infoPtr->szPadding.cy +\r
+ NONLIST_NOTEXT_OFFSET;\r
+ sizeButton.cx = 2*GetSystemMetrics(SM_CXEDGE) +\r
+ infoPtr->szPadding.cx + sizeString.cx;\r
+ }\r
+ }\r
+ return sizeButton;\r
+}\r
+\r
+\r
/***********************************************************************\r
* TOOLBAR_CalcToolbar\r
*\r
* the tooltip window if appropriate. Finally, it updates the rcBound\r
* rect and calculates the new required toolbar window height.\r
*/\r
-\r
static void\r
TOOLBAR_CalcToolbar (HWND hwnd)\r
{\r
TBUTTON_INFO *btnPtr;\r
INT i, nRows, nSepRows;\r
INT x, y, cx, cy;\r
- SIZE sizeString;\r
+ SIZE sizeString, sizeButton;\r
BOOL bWrap;\r
BOOL usesBitmaps = FALSE;\r
+ BOOL validImageList = FALSE;\r
BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);\r
\r
TOOLBAR_CalcStrings (hwnd, &sizeString);\r
if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))\r
usesBitmaps = TRUE;\r
}\r
- if (dwStyle & TBSTYLE_LIST)\r
- {\r
- infoPtr->nButtonHeight = max((usesBitmaps) ? infoPtr->nBitmapHeight :\r
- 0, sizeString.cy) + infoPtr->szPadding.cy;\r
- infoPtr->nButtonWidth = ((usesBitmaps) ? infoPtr->nBitmapWidth :\r
- LIST_IMAGE_ABSENT_WIDTH) + sizeString.cx + infoPtr->szPadding.cx;\r
- if (sizeString.cx > 0)\r
- infoPtr->nButtonWidth += TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap) + infoPtr->szPadding.cx/2;\r
- TRACE("LIST style, But w=%d h=%d, useBitmaps=%d, Bit w=%d h=%d\n",\r
- infoPtr->nButtonWidth, infoPtr->nButtonHeight, usesBitmaps,\r
- infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);\r
- }\r
- else {\r
- if (sizeString.cy > 0)\r
- {\r
- if (usesBitmaps)\r
- infoPtr->nButtonHeight = sizeString.cy +\r
- infoPtr->szPadding.cy/2 + /* this is the space to separate text from bitmap */\r
- infoPtr->nBitmapHeight + infoPtr->szPadding.cy;\r
- else\r
- infoPtr->nButtonHeight = sizeString.cy + infoPtr->szPadding.cy;\r
- }\r
- else\r
- infoPtr->nButtonHeight = infoPtr->nBitmapHeight + infoPtr->szPadding.cy;\r
-\r
- if (sizeString.cx > infoPtr->nBitmapWidth)\r
- infoPtr->nButtonWidth = sizeString.cx + infoPtr->szPadding.cx;\r
- else\r
- infoPtr->nButtonWidth = infoPtr->nBitmapWidth + infoPtr->szPadding.cx;\r
- }\r
+ if (TOOLBAR_IsValidImageList(infoPtr, 0))\r
+ validImageList = TRUE;\r
+ sizeButton = TOOLBAR_MeasureButton(infoPtr, sizeString, usesBitmaps, validImageList);\r
+ infoPtr->nButtonWidth = sizeButton.cx;\r
+ infoPtr->nButtonHeight = sizeButton.cy;\r
\r
if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )\r
infoPtr->nButtonWidth = infoPtr->cxMin;\r
/* from above, minimum is a button, and possible text */\r
cx = infoPtr->nButtonWidth;\r
\r
- /* cannot use just ButtonHeight, we may have no buttons! */\r
- if (infoPtr->nNumButtons > 0)\r
- infoPtr->nHeight = infoPtr->nButtonHeight;\r
+ infoPtr->nHeight = infoPtr->nButtonHeight;\r
\r
cy = infoPtr->nHeight;\r
\r
SelectObject (hdc, hOldFont);\r
ReleaseDC (hwnd, hdc);\r
\r
- /* add space on for button frame, etc */\r
- cx = sz.cx + infoPtr->szPadding.cx;\r
- \r
- /* add list padding */\r
- if ((dwStyle & TBSTYLE_LIST) && sz.cx > 0)\r
- cx += TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap) + infoPtr->szPadding.cx/2;\r
-\r
- if (TOOLBAR_TestImageExist (infoPtr, btnPtr, GETDEFIMAGELIST(infoPtr,0)))\r
- {\r
- if (dwStyle & TBSTYLE_LIST)\r
- cx += infoPtr->nBitmapWidth;\r
- else if (cx < (infoPtr->nBitmapWidth+infoPtr->szPadding.cx))\r
- cx = infoPtr->nBitmapWidth+infoPtr->szPadding.cx;\r
- }\r
- else if (dwStyle & TBSTYLE_LIST)\r
- cx += LIST_IMAGE_ABSENT_WIDTH;\r
+ sizeButton = TOOLBAR_MeasureButton(infoPtr, sz,\r
+ TOOLBAR_IsValidBitmapIndex(infoPtr, infoPtr->buttons[i].iBitmap),\r
+ validImageList);\r
+ cx = sizeButton.cx;\r
}\r
else\r
cx = infoPtr->nButtonWidth;\r
\r
no_highlight = TOOLBAR_SendNotify(&nmhotitem.hdr, infoPtr, TBN_HOTITEMCHANGE);\r
\r
- /* now invalidate the old and new buttons so they will be painted */\r
- if (oldBtnPtr)\r
+ /* now invalidate the old and new buttons so they will be painted,\r
+ * but only if they are enabled - disabled buttons cannot become hot */\r
+ if (oldBtnPtr && (oldBtnPtr->fsState & TBSTATE_ENABLED))\r
InvalidateRect(infoPtr->hwndSelf, &oldBtnPtr->rect, TRUE);\r
- if (btnPtr && !no_highlight)\r
+ if (btnPtr && !no_highlight && (btnPtr->fsState & TBSTATE_ENABLED))\r
{\r
btnPtr->bHot = TRUE;\r
InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);\r
if (!ImageList_GetIconSize(himl, &infoPtr->nBitmapWidth,\r
&infoPtr->nBitmapHeight))\r
{\r
- infoPtr->nBitmapWidth = 0;\r
- infoPtr->nBitmapHeight = 0;\r
+ infoPtr->nBitmapWidth = 1;\r
+ infoPtr->nBitmapHeight = 1;\r
}\r
\r
TRACE("hwnd %p, new himl=%p, id = %d, count=%d, bitmap w=%d, h=%d\n",\r
* to control the bottom and right borders [with the border being\r
* szPadding.cx - (GetSystemMetrics(SM_CXEDGE)+1)], otherwise the padding\r
* is shared evenly on both sides of the button.\r
+ * See blueprints in comments above TOOLBAR_MeasureButton for more info.\r
*/\r
static LRESULT\r
TOOLBAR_SetPadding (HWND hwnd, WPARAM wParam, LPARAM lParam)\r
DWORD oldPad;\r
\r
oldPad = MAKELONG(infoPtr->szPadding.cx, infoPtr->szPadding.cy);\r
- infoPtr->szPadding.cx = LOWORD((DWORD)lParam);\r
- infoPtr->szPadding.cy = HIWORD((DWORD)lParam);\r
+ infoPtr->szPadding.cx = min(LOWORD((DWORD)lParam), GetSystemMetrics(SM_CXEDGE));\r
+ infoPtr->szPadding.cy = min(HIWORD((DWORD)lParam), GetSystemMetrics(SM_CYEDGE));\r
TRACE("cx=%ld, cy=%ld\n",\r
infoPtr->szPadding.cx, infoPtr->szPadding.cy);\r
return (LRESULT) oldPad;\r
infoPtr->clrBtnShadow = CLR_DEFAULT;\r
infoPtr->szPadding.cx = DEFPAD_CX;\r
infoPtr->szPadding.cy = DEFPAD_CY;\r
- infoPtr->iListGap = infoPtr->szPadding.cx / 2;\r
+ infoPtr->iListGap = DEFLISTGAP;\r
infoPtr->dwStyle = dwStyle;\r
infoPtr->tbim.iButton = -1;\r
GetClientRect(hwnd, &infoPtr->client_rect);\r