- Implement TBSTYLE_FLAT as "transparent" toolbar and buttons. (Skip

FillRect and BF_MIDDLE on _FLAT toolbars.)
- Issue FIXMEs for unsupported styles.
- If the "hidden" state has changed then recalc the buttons.
- Support TBSTYLE_CUSTOMERASE (used by IE4) ans issue some of the
  necessary NM_CUSTOMDRAW notifies.
- Pass the WM_ERASEBKGND to parent if the toolbar is "transparent".
- Invalidate the area 1 bigger than the button rect on a WM_MOUSELEAVE
  so that the edge is "erased" by the parent.
- Support the PGN_CALCSIZE notify since a toolbar can be a child of the
  Pager control.
This commit is contained in:
Guy L. Albertelli 2001-08-13 20:09:18 +00:00 committed by Alexandre Julliard
parent be73d10dc5
commit f617391dad
1 changed files with 140 additions and 20 deletions

View File

@ -4,6 +4,16 @@
* Copyright 1998,1999 Eric Kohl
* Copyright 2000 Eric Kohl for CodeWeavers
*
* 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
* identical to TBSTYLE_FLAT."
* As implemented by both v4.71 and v5.80 of the native COMCTL32.DLL
* you can create a TBSTYLE_LIST without TBSTYLE_FLAT and the result
* is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does
* *not* imply TBSTYLE_FLAT as documented. (GA 8/2001)
*
*
* TODO:
* - A little bug in TOOLBAR_DrawMasked()
* - Button wrapping (under construction).
@ -174,6 +184,25 @@ TOOLBAR_DumpToolbar(TOOLBAR_INFO *iP, INT line)
}
/***********************************************************************
* TOOLBAR_CheckStyle
*
* This function validates that the styles set are implemented and
* issues FIXME's warning of possible problems. In a perfect world this
* function should be null.
*/
static void
TOOLBAR_CheckStyle (HWND hwnd, DWORD dwStyle)
{
if (dwStyle & TBSTYLE_ALTDRAG)
FIXME("[%04x] TBSTYLE_ALTDRAG not implemented\n", hwnd);
if (dwStyle & TBSTYLE_REGISTERDROP)
FIXME("[%04x] TBSTYLE_REGISTERDROP not implemented\n", hwnd);
if (dwStyle & TBSTYLE_TRANSPARENT)
FIXME("[%04x] TBSTYLE_TRANSPARENT not implemented\n", hwnd);
}
static INT
TOOLBAR_SendNotify (NMHDR *nmhdr, TOOLBAR_INFO *infoPtr, UINT code)
{
@ -400,7 +429,6 @@ TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
{
RECT rcText = btnPtr->rect;
HFONT hOldFont;
INT nOldBkMode;
COLORREF clrOld;
LPWSTR lpText = NULL;
HIMAGELIST himl = infoPtr->himlDef;
@ -449,7 +477,6 @@ TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
rcText.left, rcText.top, rcText.right, rcText.bottom);
hOldFont = SelectObject (hdc, infoPtr->hFont);
nOldBkMode = SetBkMode (hdc, TRANSPARENT);
if (!(nState & TBSTATE_ENABLED)) {
clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
OffsetRect (&rcText, 1, 1);
@ -469,8 +496,6 @@ TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
SetTextColor (hdc, clrOld);
SelectObject (hdc, hOldFont);
if (nOldBkMode != TRANSPARENT)
SetBkMode (hdc, nOldBkMode);
}
}
@ -547,7 +572,8 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
CopyRect (&rcArrow, &rc);
CopyRect(&rcBitmap, &rc);
FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
if (!infoPtr->bTransparent)
FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
if (hasDropDownArrow)
{
@ -619,9 +645,9 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
if (btnPtr->fsState & TBSTATE_PRESSED) {
if (dwStyle & TBSTYLE_FLAT)
{
DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
if (hasDropDownArrow)
DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
}
else
{
@ -646,7 +672,7 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
(btnPtr->fsState & TBSTATE_CHECKED)) {
if (dwStyle & TBSTYLE_FLAT)
DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
BF_RECT | BF_MIDDLE | BF_ADJUST);
BF_RECT | BF_ADJUST);
else
DrawEdge (hdc, &rc, EDGE_SUNKEN,
BF_RECT | BF_MIDDLE | BF_ADJUST);
@ -677,16 +703,21 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
{
if (btnPtr->bHot)
{
DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT);
if (hasDropDownArrow)
DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT);
}
else
#if 1
else /* The following code needs to be removed after
* "hot item" support has been implemented for the
* case where it is being de-selected.
*/
{
FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
if (hasDropDownArrow)
FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
}
#endif
if (hasDropDownArrow)
TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
@ -732,7 +763,7 @@ TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
{
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
TBUTTON_INFO *btnPtr;
INT i;
INT i, oldBKmode = 0;
RECT rcTemp;
/* if imagelist belongs to the app, it can be changed
@ -742,6 +773,9 @@ TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
TOOLBAR_DumpToolbar (infoPtr, __LINE__);
if (infoPtr->bTransparent)
oldBKmode = SetBkMode (hdc, TRANSPARENT);
/* redraw necessary buttons */
btnPtr = infoPtr->buttons;
for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
@ -749,6 +783,9 @@ TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
}
if (infoPtr->bTransparent && (oldBKmode != TRANSPARENT))
SetBkMode (hdc, oldBKmode);
}
/***********************************************************************
@ -847,7 +884,7 @@ TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
* wrapping should occur based on the width of the toolbar window.
* It does *not* calculate button placement itself. That task
* takes place in TOOLBAR_CalcToolbar. If the program wants to manage
* the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE
* the toolbar wrapping on its own, it can use the TBSTYLE_WRAPABLE
* flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
*/
@ -3859,6 +3896,14 @@ TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
btnPtr = &infoPtr->buttons[nIndex];
/* if hidden state has changed the invalidate entire window and recalc */
if ((btnPtr->fsState & TBSTATE_HIDDEN) != (LOWORD(lParam) & TBSTATE_HIDDEN)) {
btnPtr->fsState = LOWORD(lParam);
TOOLBAR_CalcToolbar (hwnd);
InvalidateRect(hwnd, 0, TOOLBAR_HasText(infoPtr, btnPtr));
return TRUE;
}
/* process state changing if current state doesn't match new state */
if(btnPtr->fsState != LOWORD(lParam))
{
@ -3967,7 +4012,7 @@ TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
infoPtr->nOldHit = -1;
infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
infoPtr->hwndNotify = GetParent (hwnd);
infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
infoPtr->bTransparent = (dwStyle & (TBSTYLE_FLAT | TBSTYLE_TRANSPARENT));
infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
infoPtr->bAnchor = FALSE; /* no anchor highlighting */
infoPtr->iVersion = 0;
@ -3996,6 +4041,8 @@ TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
}
}
TOOLBAR_CheckStyle (hwnd, dwStyle);
TOOLBAR_CalcToolbar(hwnd);
return 0;
@ -4045,10 +4092,62 @@ static LRESULT
TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
NMTBCUSTOMDRAW tbcd;
INT ret;
if (infoPtr->bTransparent)
return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
if (dwStyle & TBSTYLE_CUSTOMERASE) {
ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
tbcd.nmcd.dwDrawStage = CDDS_PREERASE;
tbcd.nmcd.hdc = (HDC)wParam;
ret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
/* FIXME: in general the return flags *can* be or'ed together */
switch (ret)
{
case CDRF_DODEFAULT:
break;
case CDRF_SKIPDEFAULT:
return TRUE;
default:
FIXME("[%04x] response %d not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
hwnd, ret);
}
}
/* If the toolbar is "transparent" then pass the WM_ERASEBKGND up
* to my parent for processing.
*/
if (infoPtr->bTransparent) {
POINT pt, ptorig;
HDC hdc = (HDC)wParam;
HWND parent;
pt.x = 0;
pt.y = 0;
parent = GetParent(hwnd);
MapWindowPoints(hwnd, parent, &pt, 1);
OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig);
SendMessageA (parent, WM_ERASEBKGND, wParam, lParam);
SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0);
return TRUE;
}
if (dwStyle & TBSTYLE_CUSTOMERASE) {
ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
tbcd.nmcd.dwDrawStage = CDDS_POSTERASE;
tbcd.nmcd.hdc = (HDC)wParam;
ret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
switch (ret)
{
case CDRF_DODEFAULT:
break;
case CDRF_SKIPDEFAULT:
return TRUE;
default:
FIXME("[%04x] response %d not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
hwnd, ret);
}
}
return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
}
@ -4305,6 +4404,7 @@ TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
TBUTTON_INFO *hotBtnPtr, *btnPtr;
RECT rc1;
if (infoPtr->nOldHit < 0)
return TRUE;
@ -4316,8 +4416,9 @@ TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
{
hotBtnPtr->bHot = FALSE;
InvalidateRect (hwnd, &hotBtnPtr->rect, TOOLBAR_HasText(infoPtr,
rc1 = hotBtnPtr->rect;
InflateRect (&rc1, 1, 1);
InvalidateRect (hwnd, &rc1, TOOLBAR_HasText(infoPtr,
hotBtnPtr));
}
@ -4329,7 +4430,9 @@ TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
btnPtr->fsState &= ~TBSTATE_PRESSED;
InvalidateRect (hwnd, &(btnPtr->rect), TRUE);
rc1 = hotBtnPtr->rect;
InflateRect (&rc1, 1, 1);
InvalidateRect (hwnd, &rc1, TRUE);
}
infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
@ -4500,6 +4603,23 @@ 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;
if (lppgc->dwFlag == PGF_CALCWIDTH) {
lppgc->iWidth = infoPtr->nWidth;
TRACE("processed PGN_CALCSIZE, returning horz size = %d\n",
infoPtr->nWidth);
}
else {
lppgc->iHeight = infoPtr->nHeight;
TRACE("processed PGN_CALCSIZE, returning vert size = %d\n",
infoPtr->nHeight);
}
return 0;
}
TRACE("passing WM_NOTIFY!\n");
if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
@ -4647,6 +4767,7 @@ TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
else {
infoPtr->dwDTFlags = DT_CENTER;
}
TOOLBAR_CheckStyle (hwnd, lpStyle->styleNew);
}
TOOLBAR_AutoSize (hwnd);
@ -5027,4 +5148,3 @@ TOOLBAR_Unregister (void)
{
UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);
}