parent
fb1845db31
commit
7d22cc16d9
|
@ -18,6 +18,8 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* Differences between MSDN and actual native control operation:
|
||||
* 1. MSDN says: "TBSTYLE_LIST: Creates a flat toolbar with button text
|
||||
* to the right of the bitmap. Otherwise, this style is
|
||||
|
@ -27,11 +29,25 @@
|
|||
* is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does
|
||||
* *not* imply TBSTYLE_FLAT as documented. (GA 8/2001)
|
||||
*
|
||||
*
|
||||
* This code was audited for completeness against the documented features
|
||||
* of Comctl32.dll version 6.0 on Mar. 14, 2004, by Robert Shearman.
|
||||
*
|
||||
* Unless otherwise noted, we believe this code to be complete, as per
|
||||
* the specification mentioned above.
|
||||
* If you discover missing features or bugs please note them below.
|
||||
*
|
||||
* TODO:
|
||||
* - Button wrapping (under construction).
|
||||
* - Messages.
|
||||
* - Notifications
|
||||
* - Messages:
|
||||
* - TB_GETINSERTMARK
|
||||
* - TB_GETINSERTMARKCOLOR
|
||||
* - TB_GETMETRICS
|
||||
* - TB_GETOBJECT
|
||||
* - TB_INSERTMARKHITTEST
|
||||
* - TB_MOVEBUTTON
|
||||
* - TB_SETINSERTMARK
|
||||
* - TB_SETMETRICS
|
||||
* - Notifications:
|
||||
* - NM_CHAR
|
||||
* - NM_KEYDOWN
|
||||
* - NM_LDOWN
|
||||
|
@ -44,13 +60,11 @@
|
|||
* - TBN_SAVE
|
||||
* - TBN_TOOLBARCHANGE
|
||||
* - Fix TB_SETROWS.
|
||||
* - Tooltip support (almost complete).
|
||||
* - Fix TOOLBAR_SetButtonInfo32A/W.
|
||||
* - iString of -1 is undocumented
|
||||
* - iListGap custom draw support.
|
||||
* - Customization dialog:
|
||||
* - Add flat look.
|
||||
* - Minor buglet in 'available buttons' list:
|
||||
* Buttons are not listed in M$-like order. M$ seems to use a single
|
||||
* Buttons are not listed in MS-like order. MS seems to use a single
|
||||
* internal list to store the button information of both listboxes.
|
||||
* - Drag list support.
|
||||
*
|
||||
|
@ -163,7 +177,8 @@ typedef struct
|
|||
COLORREF clrBtnShadow; /* color for Flag Separator */
|
||||
RECT rcBound; /* bounding rectangle */
|
||||
INT iVersion;
|
||||
|
||||
LPWSTR pszTooltipText; /* temporary store for a string > 80 characters
|
||||
* for TTN_GETDISPINFOW notification */
|
||||
TBUTTON_INFO *buttons; /* pointer to button array */
|
||||
LPWSTR *strings; /* pointer to string array */
|
||||
TBITMAP_INFO *bitmaps;
|
||||
|
@ -568,6 +583,7 @@ TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, RECT *rcText, LPWSTR lpText,
|
|||
HFONT hOldFont = 0;
|
||||
COLORREF clrOld = 0;
|
||||
COLORREF clrOldBk = 0;
|
||||
int oldBkMode = 0;
|
||||
UINT state = tbcd->nmcd.uItemState;
|
||||
|
||||
/* draw text */
|
||||
|
@ -590,8 +606,9 @@ TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, RECT *rcText, LPWSTR lpText,
|
|||
clrOld = SetTextColor (hdc, comctl32_color.clr3dShadow);
|
||||
}
|
||||
else if ((state & CDIS_MARKED) && !(infoPtr->dwItemCDFlag & TBCDRF_NOMARK)) {
|
||||
clrOld = SetTextColor (hdc, tbcd->clrText);
|
||||
clrOld = SetTextColor (hdc, tbcd->clrTextHighlight);
|
||||
clrOldBk = SetBkColor (hdc, tbcd->clrMark);
|
||||
oldBkMode = SetBkMode (hdc, OPAQUE); /* FIXME: should this be in the NMTBCUSTOMDRAW structure? */
|
||||
}
|
||||
else {
|
||||
clrOld = SetTextColor (hdc, tbcd->clrText);
|
||||
|
@ -600,7 +617,10 @@ TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, RECT *rcText, LPWSTR lpText,
|
|||
DrawTextW (hdc, lpText, -1, rcText, infoPtr->dwDTFlags);
|
||||
SetTextColor (hdc, clrOld);
|
||||
if ((state & CDIS_MARKED) && !(infoPtr->dwItemCDFlag & TBCDRF_NOMARK))
|
||||
{
|
||||
SetBkColor (hdc, clrOldBk);
|
||||
SetBkMode (hdc, oldBkMode);
|
||||
}
|
||||
SelectObject (hdc, hOldFont);
|
||||
}
|
||||
}
|
||||
|
@ -698,14 +718,12 @@ TOOLBAR_DrawImage(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, INT left, INT top
|
|||
INT offset = 0;
|
||||
UINT draw_flags = ILD_NORMAL;
|
||||
|
||||
if (tbcd->nmcd.uItemState & CDIS_DISABLED)
|
||||
if (tbcd->nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE))
|
||||
{
|
||||
himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DISABLED, &index);
|
||||
if (!himl)
|
||||
draw_masked = TRUE;
|
||||
}
|
||||
else if (tbcd->nmcd.uItemState & CDIS_INDETERMINATE)
|
||||
draw_masked = TRUE;
|
||||
else if ((tbcd->nmcd.uItemState & CDIS_HOT) && (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & TBSTYLE_FLAT))
|
||||
{
|
||||
/* if hot, attempt to draw with hot image list, if fails,
|
||||
|
@ -2879,14 +2897,14 @@ TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
BOOL bChecked = FALSE;
|
||||
|
||||
nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
|
||||
|
||||
TRACE("hwnd=%p, btn index=%d, lParam=0x%08lx\n", hwnd, nIndex, lParam);
|
||||
|
||||
if (nIndex == -1)
|
||||
return FALSE;
|
||||
|
||||
btnPtr = &infoPtr->buttons[nIndex];
|
||||
|
||||
if (!(btnPtr->fsStyle & BTNS_CHECK))
|
||||
return FALSE;
|
||||
|
||||
bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
|
||||
|
||||
if (LOWORD(lParam) == FALSE)
|
||||
|
@ -3027,6 +3045,9 @@ TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
DWORD bState;
|
||||
|
||||
nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
|
||||
|
||||
TRACE("hwnd=%p, btn index=%d, lParam=0x%08lx\n", hwnd, wParam, lParam);
|
||||
|
||||
if (nIndex == -1)
|
||||
return FALSE;
|
||||
|
||||
|
@ -4658,6 +4679,8 @@ TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
|
||||
|
||||
TRACE("hwnd=%p, hwndTooltip=%p, lParam=0x%lx\n", hwnd, (HWND)wParam, lParam);
|
||||
|
||||
if (infoPtr == NULL)
|
||||
return 0;
|
||||
infoPtr->hwndToolTip = (HWND)wParam;
|
||||
|
@ -5013,6 +5036,10 @@ TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
if (infoPtr->hwndToolTip)
|
||||
DestroyWindow (infoPtr->hwndToolTip);
|
||||
|
||||
/* delete temporary buffer for tooltip text */
|
||||
if (infoPtr->pszTooltipText)
|
||||
HeapFree(GetProcessHeap(), 0, infoPtr->pszTooltipText);
|
||||
|
||||
/* delete button data */
|
||||
if (infoPtr->buttons)
|
||||
Free (infoPtr->buttons);
|
||||
|
@ -5615,66 +5642,183 @@ TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
|
||||
|
||||
/* handles requests from the tooltip control on what text to display */
|
||||
static LRESULT TOOLBAR_TTGetDispInfo (TOOLBAR_INFO *infoPtr, NMTTDISPINFOW *lpnmtdi)
|
||||
{
|
||||
int index = TOOLBAR_GetButtonIndex(infoPtr, lpnmtdi->hdr.idFrom, FALSE);
|
||||
|
||||
TRACE("button index = %d\n", index);
|
||||
|
||||
if (infoPtr->pszTooltipText)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, infoPtr->pszTooltipText);
|
||||
infoPtr->pszTooltipText = NULL;
|
||||
}
|
||||
|
||||
if (index < 0)
|
||||
return 0;
|
||||
|
||||
if (infoPtr->bNtfUnicode)
|
||||
{
|
||||
WCHAR wszBuffer[INFOTIPSIZE+1];
|
||||
NMTBGETINFOTIPW tbgit;
|
||||
int len; /* in chars */
|
||||
|
||||
wszBuffer[0] = '\0';
|
||||
wszBuffer[INFOTIPSIZE] = '\0';
|
||||
|
||||
tbgit.pszText = wszBuffer;
|
||||
tbgit.cchTextMax = INFOTIPSIZE;
|
||||
tbgit.iItem = lpnmtdi->hdr.idFrom;
|
||||
tbgit.lParam = infoPtr->buttons[index].dwData;
|
||||
|
||||
TOOLBAR_SendNotify(&tbgit.hdr, infoPtr, TBN_GETINFOTIPW);
|
||||
|
||||
TRACE("TBN_GETINFOTIPW - got string %s\n", debugstr_w(tbgit.pszText));
|
||||
|
||||
len = strlenW(tbgit.pszText);
|
||||
if (len > sizeof(lpnmtdi->szText)/sizeof(lpnmtdi->szText[0])-1)
|
||||
{
|
||||
/* need to allocate temporary buffer in infoPtr as there
|
||||
* isn't enough space in buffer passed to us by the
|
||||
* tooltip control */
|
||||
infoPtr->pszTooltipText = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
|
||||
if (infoPtr->pszTooltipText)
|
||||
{
|
||||
memcpy(infoPtr->pszTooltipText, tbgit.pszText, (len+1)*sizeof(WCHAR));
|
||||
lpnmtdi->lpszText = infoPtr->pszTooltipText;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (len > 0)
|
||||
{
|
||||
memcpy(lpnmtdi->lpszText, tbgit.pszText, (len+1)*sizeof(WCHAR));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CHAR szBuffer[INFOTIPSIZE+1];
|
||||
NMTBGETINFOTIPA tbgit;
|
||||
int len; /* in chars */
|
||||
|
||||
szBuffer[0] = '\0';
|
||||
szBuffer[INFOTIPSIZE] = '\0';
|
||||
|
||||
tbgit.pszText = szBuffer;
|
||||
tbgit.cchTextMax = INFOTIPSIZE;
|
||||
tbgit.iItem = lpnmtdi->hdr.idFrom;
|
||||
tbgit.lParam = infoPtr->buttons[index].dwData;
|
||||
|
||||
TOOLBAR_SendNotify(&tbgit.hdr, infoPtr, TBN_GETINFOTIPA);
|
||||
|
||||
TRACE("TBN_GETINFOTIPA - got string %s\n", debugstr_a(tbgit.pszText));
|
||||
|
||||
len = -1 + MultiByteToWideChar(CP_ACP, 0, tbgit.pszText, -1, NULL, 0);
|
||||
if (len > sizeof(lpnmtdi->szText)/sizeof(lpnmtdi->szText[0])-1)
|
||||
{
|
||||
/* need to allocate temporary buffer in infoPtr as there
|
||||
* isn't enough space in buffer passed to us by the
|
||||
* tooltip control */
|
||||
infoPtr->pszTooltipText = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
|
||||
if (infoPtr->pszTooltipText)
|
||||
{
|
||||
MultiByteToWideChar(CP_ACP, 0, tbgit.pszText, len+1, infoPtr->pszTooltipText, (len+1)*sizeof(WCHAR));
|
||||
lpnmtdi->lpszText = infoPtr->pszTooltipText;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (len > 0)
|
||||
{
|
||||
MultiByteToWideChar(CP_ACP, 0, tbgit.pszText, len+1, lpnmtdi->lpszText, (len+1)*sizeof(WCHAR));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* if button has text, but it is not shown then automatically
|
||||
* use that text as tooltip */
|
||||
if ((infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) &&
|
||||
!(infoPtr->buttons[index].fsStyle & BTNS_SHOWTEXT))
|
||||
{
|
||||
LPWSTR pszText = TOOLBAR_GetText(infoPtr, &infoPtr->buttons[index]);
|
||||
int len = pszText ? strlenW(pszText) : 0;
|
||||
|
||||
TRACE("using button hidden text %s\n", debugstr_w(pszText));
|
||||
|
||||
if (len > sizeof(lpnmtdi->szText)/sizeof(lpnmtdi->szText[0])-1)
|
||||
{
|
||||
/* need to allocate temporary buffer in infoPtr as there
|
||||
* isn't enough space in buffer passed to us by the
|
||||
* tooltip control */
|
||||
infoPtr->pszTooltipText = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
|
||||
if (infoPtr->pszTooltipText)
|
||||
{
|
||||
memcpy(infoPtr->pszTooltipText, pszText, (len+1)*sizeof(WCHAR));
|
||||
lpnmtdi->lpszText = infoPtr->pszTooltipText;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (len > 0)
|
||||
{
|
||||
memcpy(lpnmtdi->lpszText, pszText, (len+1)*sizeof(WCHAR));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Sending tooltip notification to %p\n", infoPtr->hwndNotify);
|
||||
|
||||
/* last resort: send notification on to app */
|
||||
/* FIXME: find out what is really used here */
|
||||
return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, 0, (LPARAM)lpnmtdi);
|
||||
}
|
||||
|
||||
|
||||
inline static LRESULT
|
||||
TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
|
||||
LPNMHDR lpnmh = (LPNMHDR)lParam;
|
||||
|
||||
if (lpnmh->code == PGN_CALCSIZE) {
|
||||
LPNMPGCALCSIZE lppgc = (LPNMPGCALCSIZE)lParam;
|
||||
switch (lpnmh->code)
|
||||
{
|
||||
case PGN_CALCSIZE:
|
||||
{
|
||||
LPNMPGCALCSIZE lppgc = (LPNMPGCALCSIZE)lParam;
|
||||
|
||||
if (lppgc->dwFlag == PGF_CALCWIDTH) {
|
||||
lppgc->iWidth = infoPtr->rcBound.right - infoPtr->rcBound.left;
|
||||
TRACE("processed PGN_CALCSIZE, returning horz size = %d\n",
|
||||
lppgc->iWidth);
|
||||
}
|
||||
else {
|
||||
lppgc->iHeight = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
|
||||
TRACE("processed PGN_CALCSIZE, returning vert size = %d\n",
|
||||
lppgc->iHeight);
|
||||
}
|
||||
return 0;
|
||||
if (lppgc->dwFlag == PGF_CALCWIDTH) {
|
||||
lppgc->iWidth = infoPtr->rcBound.right - infoPtr->rcBound.left;
|
||||
TRACE("processed PGN_CALCSIZE, returning horz size = %d\n",
|
||||
lppgc->iWidth);
|
||||
}
|
||||
else {
|
||||
lppgc->iHeight = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
|
||||
TRACE("processed PGN_CALCSIZE, returning vert size = %d\n",
|
||||
lppgc->iHeight);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lpnmh->code == PGN_SCROLL) {
|
||||
LPNMPGSCROLL lppgs = (LPNMPGSCROLL)lParam;
|
||||
case PGN_SCROLL:
|
||||
{
|
||||
LPNMPGSCROLL lppgs = (LPNMPGSCROLL)lParam;
|
||||
|
||||
lppgs->iScroll = (lppgs->iDir & (PGF_SCROLLLEFT | PGF_SCROLLRIGHT)) ?
|
||||
infoPtr->nButtonWidth : infoPtr->nButtonHeight;
|
||||
TRACE("processed PGN_SCROLL, returning scroll=%d, dir=%d\n",
|
||||
lppgs->iScroll, lppgs->iDir);
|
||||
return 0;
|
||||
lppgs->iScroll = (lppgs->iDir & (PGF_SCROLLLEFT | PGF_SCROLLRIGHT)) ?
|
||||
infoPtr->nButtonWidth : infoPtr->nButtonHeight;
|
||||
TRACE("processed PGN_SCROLL, returning scroll=%d, dir=%d\n",
|
||||
lppgs->iScroll, lppgs->iDir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TTN_GETDISPINFOW:
|
||||
return TOOLBAR_TTGetDispInfo(infoPtr, (LPNMTTDISPINFOW)lParam);
|
||||
|
||||
TRACE("passing WM_NOTIFY!\n");
|
||||
case TTN_GETDISPINFOA:
|
||||
FIXME("TTN_GETDISPINFOA - stub\n");
|
||||
return 0;
|
||||
|
||||
if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
|
||||
if (infoPtr->bNtfUnicode)
|
||||
return SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
|
||||
wParam, lParam);
|
||||
else
|
||||
return SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
|
||||
wParam, lParam);
|
||||
|
||||
#if 0
|
||||
if (lpnmh->code == TTN_GETDISPINFOA) {
|
||||
LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
|
||||
|
||||
FIXME("retrieving ASCII string\n");
|
||||
|
||||
}
|
||||
else if (lpnmh->code == TTN_GETDISPINFOW) {
|
||||
LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
|
||||
|
||||
FIXME("retrieving UNICODE string\n");
|
||||
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -5694,6 +5838,11 @@ TOOLBAR_NotifyFormat(TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
INT i;
|
||||
|
||||
TRACE("wParam = 0x%x, lParam = 0x%08lx\n", wParam, lParam);
|
||||
|
||||
if ((lParam == NF_QUERY) && ((HWND)wParam == infoPtr->hwndToolTip))
|
||||
return NFR_UNICODE;
|
||||
|
||||
if (lParam == NF_REQUERY) {
|
||||
i = SendMessageA(infoPtr->hwndNotify,
|
||||
WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY);
|
||||
|
|
Loading…
Reference in New Issue