Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
toolbar.c.1475
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 103k
Category:
Windows Kernel
Development Platform:
Visual C++
- /*
- ** Toolbar.c
- **
- ** This is it, the incredibly famous toolbar control. Most of
- ** the customization stuff is in another file.
- */
- #include "ctlspriv.h"
- #include "toolbar.h"
- #include "image.h"
- #include <limits.h>
- #define LPARAM_TO_POINT(lParam, pt) ((pt).x = LOWORD(lParam),
- (pt).y = HIWORD(lParam))
- #define TBIMAGELIST
- // these values are defined by the UI gods...
- #define DEFAULTBITMAPX 16
- #define DEFAULTBITMAPY 15
- #define LIST_GAP g_cxEdge * 2
- #define SMALL_DXYBITMAP 16 // new dx dy for sdt images
- #define LARGE_DXYBITMAP 24
- #define DEFAULTBUTTONX 24
- #define DEFAULTBUTTONY 22
- // horizontal/vertical space taken up by button chisel, sides,
- // and a 1 pixel margin. used in GrowToolbar.
- #define XSLOP 7
- #define YSLOP 6
- const int g_dxButtonSep = 8;
- const int s_xFirstButton = 0; // was 8 in 3.1
- #define s_dxOverlap 0 // was 1 in 3.1
- // Globals - since all of these globals are used durring a paint we have to
- // take a criticial section around all toolbar paints. this sucks.
- //
- const UINT wStateMasks[] = {
- TBSTATE_ENABLED,
- TBSTATE_CHECKED,
- TBSTATE_PRESSED,
- TBSTATE_HIDDEN,
- TBSTATE_INDETERMINATE,
- TBSTATE_HIGHLIGHTED
- };
- #define TBISSTRINGPTR(iString) (((iString) != -1) && (HIWORD(iString)))
- LRESULT CALLBACK ToolbarWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
- void NEAR PASCAL TBOnButtonStructSize(PTBSTATE ptb, UINT uStructSize);
- BOOL NEAR PASCAL SetBitmapSize(PTBSTATE ptb, int width, int height);
- int NEAR PASCAL AddBitmap(PTBSTATE ptb, int nButtons, HINSTANCE hBMInst, UINT wBMID);
- BOOL NEAR PASCAL GrowToolbar(PTBSTATE ptb, int newButWidth, int newButHeight, BOOL bInside);
- void NEAR PASCAL TBBuildImageList(PTBSTATE ptb);
- BOOL NEAR PASCAL GetItemRect(PTBSTATE ptb, UINT uButton, LPRECT lpRect);
- LPTSTR TB_StrForButton(PTBSTATE ptb, LPTBBUTTON pTBButton);
- #define TBInvalidateImageList(ptb) ((ptb)->fHimlValid = FALSE)
- #define TBHasStrings(ptb) ((ptb)->nStrings || (ptb)->fNoStringPool)
- LRESULT ToolbarDragCallback(HWND hwnd, UINT code, WPARAM wp, LPARAM lp)
- {
- PTBSTATE ptb = (PTBSTATE)GetWindowInt(hwnd, 0);
- LRESULT lres;
- switch (code)
- {
- case DPX_DRAGHIT:
- if (lp)
- {
- POINT pt = {((POINTL *)lp)->x, ((POINTL *)lp)->y};
- int item;
- MapWindowPoints(NULL, ptb->ci.hwnd, &pt, 1);
- item = TBHitTest(ptb, pt.x, pt.y);
- lres = (LRESULT)((item >= 0)? ptb->Buttons[item].idCommand : -1);
- }
- else
- lres = -1;
- break;
- case DPX_GETOBJECT:
- lres = (LRESULT)GetItemObject(&ptb->ci, TBN_GETOBJECT, &IID_IDropTarget, (LPNMOBJECTNOTIFY)lp);
- break;
- case DPX_SELECT:
- if ((int)wp >= 0)
- {
- SendMessage(ptb->ci.hwnd, TB_HIGHLIGHTBUTTON, wp,
- MAKELPARAM((lp != DROPEFFECT_NONE), 0));
- }
- lres = 0;
- break;
- default:
- lres = -1;
- break;
- }
- return lres;
- }
- //#define HeightWithString(ptb, h) (h + ptb->dyIconFont + 1)
- int HeightWithString(PTBSTATE ptb, int h)
- {
- if (ptb->ci.style & TBSTYLE_LIST)
- return (max(h, ptb->dyIconFont));
- else if (ptb->dyIconFont)
- return (h + ptb->dyIconFont + 1);
- else
- return (h);
- }
- int TBWidthOfButton(PTBSTATE ptb, PTBBUTTON pButton)
- {
- if (pButton->fsStyle & TBSTYLE_SEP)
- return pButton->iBitmap;
- else if ((pButton->fsStyle & TBSTYLE_DROPDOWN) && !(ptb->ci.style & TBSTYLE_FLAT))
- return ptb->iButWidth + (ptb->iButWidth /2);
- else
- return ptb->iButWidth;
- }
- BOOL NEAR PASCAL TBRecalc(PTBSTATE ptb)
- {
- TEXTMETRIC tm;
- int i;
- HDC hdc;
- UINT uiStyle = 0;
- int cxMax;
- HFONT hOldFont;
- ptb->dyIconFont = 0;
- if (!TBHasStrings(ptb)) {
- cxMax = ptb->iDxBitmap;
- } else {
- SIZE size;
- LPCTSTR pstr;
- RECT rcText = {0,0,0,0};
- int cxExtra = XSLOP;
- hdc = GetDC(ptb->ci.hwnd);
- if (!hdc)
- return(FALSE);
- hOldFont = SelectObject(hdc, ptb->hfontIcon);
- GetTextMetrics(hdc, &tm);
- if (ptb->nTextRows)
- ptb->dyIconFont = (tm.tmHeight * ptb->nTextRows) +
- (tm.tmExternalLeading * (ptb->nTextRows - 1)); // add an edge ?
- if (ptb->ci.style & TBSTYLE_LIST)
- cxExtra += ptb->iDxBitmap + LIST_GAP;
- cxMax = 0;
- // walk strings to find max width
- for (i = 0; i < ptb->iNumButtons; i++)
- {
- pstr = TB_StrForButton(ptb, &ptb->Buttons[i]);
- if (pstr) {
- GetTextExtentPoint(hdc, pstr, lstrlen(pstr), &size);
- if (cxMax < size.cx)
- cxMax = size.cx;
- }
- }
- // if cxMax is less than the iButMinWidth - dxBitmap (if LIST) then
- // cxMax = iButMinWidth
- if (ptb->iButMinWidth && (ptb->iButMinWidth > (cxMax + cxExtra)))
- cxMax = ptb->iButMinWidth - cxExtra;
- // Is the cxMax + dxBitmap (if LIST) more than the max width ?
- if (ptb->iButMaxWidth && (ptb->iButMaxWidth < (cxMax + cxExtra)))
- {
- int cyMax = 0;
- cxMax = ptb->iButMaxWidth - cxExtra;
- uiStyle = DT_CALCRECT;
- if (ptb->nTextRows > 1)
- uiStyle |= DT_WORDBREAK | DT_EDITCONTROL;
- else
- uiStyle |= DT_SINGLELINE;
- // walk strings to set the TBSTATE_ELLIPSES
- for (i = 0; i < ptb->iNumButtons; i++)
- {
- BOOL fEllipsed = FALSE;
- pstr = TB_StrForButton(ptb, &ptb->Buttons[i]);
- if (pstr) {
- rcText.bottom = ptb->dyIconFont;
- rcText.right = cxMax;
- DrawText(hdc, pstr, lstrlen(pstr), &rcText, uiStyle);
- if (ptb->nTextRows > 1)
- fEllipsed = (BOOL)(rcText.bottom > ptb->dyIconFont);
- else
- fEllipsed = (BOOL)(rcText.right > cxMax);
- if (cyMax < rcText.bottom)
- cyMax = rcText.bottom;
- }
- if (fEllipsed)
- ptb->Buttons[i].fsState |= TBSTATE_ELLIPSES;
- else
- ptb->Buttons[i].fsState &= ~TBSTATE_ELLIPSES;
- }
- // Set the text height to the tallest text, with the top end being the number
- // of rows specified by MAXTEXTROWS
- if (ptb->dyIconFont > cyMax)
- ptb->dyIconFont = cyMax;
- }
- else
- {
- for (i = 0; i < ptb->iNumButtons; i++)
- ptb->Buttons[i].fsState &= ~TBSTATE_ELLIPSES;
- if ((ptb->nTextRows) && (ptb->dyIconFont > size.cy))
- ptb->dyIconFont = size.cy;
- }
- if (ptb->iButMinWidth && (ptb->iButMinWidth > (cxMax + cxExtra)))
- cxMax = ptb->iButMinWidth - cxExtra;
- if (hOldFont)
- SelectObject(hdc, hOldFont);
- ReleaseDC(ptb->ci.hwnd, hdc);
- }
- return(GrowToolbar(ptb, cxMax, HeightWithString(ptb, ptb->iDyBitmap), TRUE));
- }
- BOOL NEAR PASCAL TBChangeFont(PTBSTATE ptb, WPARAM wParam, HFONT hFont)
- {
- LOGFONT lf;
- BOOL fWasFontCreated = ptb->fFontCreated;
- if ((wParam != 0) && (wParam != SPI_SETICONTITLELOGFONT) && (wParam != SPI_SETNONCLIENTMETRICS))
- return(FALSE);
- if (!SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0))
- return(FALSE);
- if (!hFont) {
- if (!(hFont = CreateFontIndirect(&lf)))
- return(FALSE);
- ptb->fFontCreated = TRUE;
- }
- if (ptb->hfontIcon && fWasFontCreated)
- DeleteObject(ptb->hfontIcon);
- ptb->hfontIcon = hFont;
- return(TBRecalc(ptb));
- }
- void TBSetFont(PTBSTATE ptb, HFONT hFont, BOOL fInval)
- {
- TBChangeFont(ptb, 0, hFont);
- if (fInval)
- InvalidateRect(ptb->ci.hwnd, NULL, TRUE);
- }
- HWND WINAPI CreateToolbarEx(HWND hwnd, DWORD ws, UINT wID, int nBitmaps,
- HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
- int iNumButtons, int dxButton, int dyButton,
- int dxBitmap, int dyBitmap, UINT uStructSize)
- {
- HWND hwndToolbar = CreateWindow(c_szToolbarClass, NULL, WS_CHILD | ws,
- 0, 0, 100, 30, hwnd, (HMENU)wID, HINST_THISDLL, NULL);
- if (hwndToolbar)
- {
- PTBSTATE ptb = (PTBSTATE)GetWindowInt(hwndToolbar, 0);
- TBOnButtonStructSize(ptb, uStructSize);
- if ((dxBitmap && dyBitmap && !SetBitmapSize(ptb, dxBitmap, dyBitmap)) ||
- (dxButton && dyButton && !SetBitmapSize(ptb,dxButton, dyButton)))
- {
- //!!!! do we actually need to deal with this?
- DestroyWindow(hwndToolbar);
- hwndToolbar = NULL;
- goto Error;
- }
- AddBitmap(ptb, nBitmaps, hBMInst, wBMID);
- InsertButtons(ptb, (UINT)-1, iNumButtons, (LPTBBUTTON)lpButtons, TRUE);
- // ptb may be bogus now after above button insert
- }
- Error:
- return hwndToolbar;
- }
- /* This is no longer declared in COMMCTRL.H. It only exists for compatibility
- ** with existing apps; new apps must use CreateToolbarEx.
- */
- HWND WINAPI CreateToolbar(HWND hwnd, DWORD ws, UINT wID, int nBitmaps, HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons, int iNumButtons)
- {
- // old-style toolbar, so no divider.
- return CreateToolbarEx(hwnd, ws | CCS_NODIVIDER, wID, nBitmaps, hBMInst, wBMID,
- lpButtons, iNumButtons, 0, 0, 0, 0, sizeof(OLDTBBUTTON));
- }
- #pragma code_seg(CODESEG_INIT)
- BOOL FAR PASCAL InitToolbarClass(HINSTANCE hInstance)
- {
- WNDCLASS wc;
- if (!GetClassInfo(hInstance, c_szToolbarClass, &wc)) {
- #ifndef WIN32
- extern LRESULT CALLBACK _ToolbarWndProc(HWND, UINT, WPARAM, LPARAM);
- wc.lpfnWndProc = _ToolbarWndProc;
- #else
- wc.lpfnWndProc = (WNDPROC)ToolbarWndProc;
- #endif
- wc.lpszClassName = c_szToolbarClass;
- wc.style = CS_DBLCLKS | CS_GLOBALCLASS;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = sizeof(PTBSTATE);
- wc.hInstance = hInstance; // use DLL instance if in DLL
- wc.hIcon = NULL;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
- wc.lpszMenuName = NULL;
- if (!RegisterClass(&wc))
- return FALSE;
- }
- return TRUE;
- }
- #pragma code_seg()
- #define BEVEL 2
- #define FRAME 1
- void NEAR PASCAL PatB(HDC hdc,int x,int y,int dx,int dy, DWORD rgb)
- {
- RECT rc;
- SetBkColor(hdc,rgb);
- rc.left = x;
- rc.top = y;
- rc.right = x + dx;
- rc.bottom = y + dy;
- ExtTextOut(hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
- }
- // Parameter fHighlight determines whether to draw text highlighted, for
- // new TBSTATE_HIGHLIGHTED
- //
- void NEAR PASCAL DrawString(PTBSTATE ptb, HDC hdc, int x, int y, int dx, int dy, PTSTR pszString,
- BOOL fHighlight)
- {
- int oldMode;
- COLORREF oldBkColor;
- COLORREF oldTextColor;
- int len;
- RECT rcText;
- UINT uiStyle = 0;
- if (!(ptb->ci.style & TBSTYLE_LIST) && ((ptb->iDyBitmap + YSLOP + g_cyEdge) >= ptb->iButHeight))
- // there's no room to show the text -- bail out
- return;
- if (fHighlight)
- {
- oldMode = SetBkMode (hdc, OPAQUE);
- oldBkColor = SetBkColor (hdc, g_clrHighlight);
- oldTextColor = SetTextColor (hdc, g_clrHighlightText);
- }
- else
- oldMode = SetBkMode(hdc, TRANSPARENT);
- len = lstrlen(pszString);
- uiStyle = DT_END_ELLIPSIS;
- if (ptb->nTextRows > 1)
- uiStyle |= DT_WORDBREAK | DT_EDITCONTROL;
- if (ptb->ci.style & TBSTYLE_LIST)
- {
- uiStyle |= DT_LEFT | DT_VCENTER | DT_SINGLELINE;
- dy = max(ptb->dyIconFont, ptb->iDyBitmap);
- }
- else
- {
- uiStyle |= DT_CENTER;
- if (!dy || ptb->dyIconFont < dy)
- dy = ptb->dyIconFont;
- }
- SetRect( &rcText, x, y, x + dx, y + dy);
- DrawTextEx(hdc, (LPTSTR)pszString, len, &rcText, uiStyle, NULL);
- SetBkMode(hdc, oldMode);
- if (fHighlight)
- {
- SetBkColor (hdc, oldBkColor);
- SetTextColor (hdc, oldTextColor);
- }
- }
- LPTSTR TB_StrForButton(PTBSTATE ptb, LPTBBUTTON pTBButton)
- {
- if (TBISSTRINGPTR(pTBButton->iString))
- return (LPTSTR)pTBButton->iString;
- else {
- if (pTBButton->iString != -1 &&
- pTBButton->iString < ptb->nStrings)
- return ptb->pStrings[pTBButton->iString];
- return NULL;
- }
- }
- // create a mono bitmap mask:
- // 1's where color == COLOR_BTNFACE || COLOR_3DHILIGHT
- // 0's everywhere else
- void NEAR PASCAL CreateMask(PTBSTATE ptb, LPTBBUTTON pTBButton, int xoffset, int yoffset, int dx, int dy, BOOL fDrawGlyph)
- {
- IMAGELISTDRAWPARAMS imldp;
- // initalize whole area with 1's
- PatBlt(ptb->hdcMono, 0, 0, dx, dy, WHITENESS);
- // create mask based on color bitmap
- // convert this to 1's
- if (fDrawGlyph)
- {
- imldp.cbSize = sizeof(imldp);
- imldp.himl = ptb->himl;
- imldp.i = pTBButton->iBitmap;
- imldp.hdcDst = ptb->hdcMono;
- imldp.x = xoffset;
- imldp.y = yoffset;
- imldp.cx = 0;
- imldp.cy = 0;
- imldp.xBitmap= 0;
- imldp.yBitmap= 0;
- imldp.rgbBk = g_clrBtnFace;
- imldp.rgbFg = CLR_DEFAULT;
- imldp.fStyle = ILD_ROP | ILD_MASK;
- imldp.dwRop = SRCCOPY;
- ImageList_DrawIndirect(&imldp);
- imldp.fStyle = ILD_ROP | ILD_IMAGE;
- imldp.rgbBk = g_clrBtnHighlight;
- imldp.dwRop = SRCPAINT;
- ImageList_DrawIndirect(&imldp);
- }
- if (pTBButton->iString != -1 && (pTBButton->iString < ptb->nStrings))
- {
- xoffset = 1;
- if (ptb->ci.style & TBSTYLE_LIST)
- {
- xoffset += ptb->iDxBitmap + LIST_GAP;
- dx -= ptb->iDxBitmap + LIST_GAP;
- }
- else {
- yoffset += ptb->iDyBitmap + 1;
- dy -= ptb->iDyBitmap + 1;
- }
- // The FALSE in 4th param is so we don't get a box in the mask.
- DrawString(ptb, ptb->hdcMono, xoffset, yoffset, dx - g_cxEdge, dy - g_cyEdge, TB_StrForButton(ptb, pTBButton),
- FALSE);
- }
- }
- void FAR PASCAL DrawBlankButton(HDC hdc, int x, int y, int dx, int dy, UINT state)
- {
- RECT r1;
- // face color
- // The Office toolbar sends us bitmaps that are smaller than they claim they are
- // So we need to do the PatB or the window background shows through around the
- // edges of the button bitmap -jjk
- if (!(state & TBSTATE_CHECKED))
- PatB(hdc, x, y, dx, dy, g_clrBtnFace);
- r1.left = x;
- r1.top = y;
- r1.right = x + dx;
- r1.bottom = y + dy;
- DrawEdge(hdc, &r1, (state & (TBSTATE_CHECKED | TBSTATE_PRESSED)) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_SOFT);
- }
- #define DSPDxax 0x00E20746
- #define PSDPxax 0x00B8074A
- void NEAR PASCAL DrawFace(PTBSTATE ptb, LPTBBUTTON ptButton, HDC hdc, int x, int y,
- int offx, int offy, int dx, int dy, UINT state)
- {
- LPTSTR psz;
- IMAGELISTDRAWPARAMS imldp;
- BOOL fHotTrack = FALSE;
- if (state & TBSTATE_ENABLED)
- {
- if ((ptb->ci.style & TBSTYLE_FLAT) && (&ptb->Buttons[ptb->nCurHTButton]==ptButton))
- fHotTrack = TRUE;
- // The following is in place to prevent hot tracking during the following conds:
- // - drag & drop toolbar customization
- // - when the mouse capture is on a particular button-press.
- // This does _not_ drop out of the loop because we don't want to break update
- // behavior; thus we'll have a little flickering on refresh as we pass over
- // these buttons.
- if (!(state & TBSTATE_PRESSED) && (GetKeyState (VK_LBUTTON) < 0))
- fHotTrack = FALSE;
- if (ptb->ci.style & TBSTYLE_FLAT)
- {
- UINT bdr = 0;
- if (state & (TBSTATE_CHECKED | TBSTATE_PRESSED))
- bdr = BDR_SUNKENOUTER;
- else if (fHotTrack)
- bdr = BDR_RAISEDINNER;
- if (bdr)
- {
- RECT rect;
- GetItemRect(ptb, ((DWORD) ptButton - (DWORD) ptb->Buttons) / sizeof(TBBUTTON), &rect);
- DrawEdge(hdc, &rect, bdr, BF_RECT);
- }
- }
- }
- imldp.himl = NULL;
- if (fHotTrack)
- imldp.himl = ptb->himlHot ? ptb->himlHot : ptb->himl;
- else if (!(state & TBSTATE_ENABLED) && ptb->himlDisabled)
- imldp.himl = ptb->himlDisabled;
- else if (ptb->himl)
- imldp.himl = ptb->himl;
- if (imldp.himl)
- {
- imldp.cbSize = sizeof(imldp);
- imldp.i = ptButton->iBitmap;
- imldp.hdcDst = hdc;
- imldp.x = x + offx;
- imldp.y = y + offy;
- imldp.cx = 0;
- imldp.cy = 0;
- imldp.xBitmap= 0;
- imldp.yBitmap= 0;
- imldp.rgbBk = (ptb->ci.style & TBSTYLE_TRANSPARENT) ? CLR_NONE : g_clrBtnFace;
- imldp.rgbFg = CLR_DEFAULT;
- imldp.fStyle = ILD_NORMAL;
- if (state & (TBSTATE_CHECKED | TBSTATE_INDETERMINATE))
- imldp.fStyle = ILD_TRANSPARENT;
- #ifdef TBHIGHLIGHT_GLYPH
- if (state & TBSTATE_HIGHLIGHTED)
- imldp.fStyle = ILD_TRANSPARENT | ILD_BLEND50;
- #endif
- ImageList_DrawIndirect(&imldp);
- }
- psz = TB_StrForButton(ptb, ptButton);
- if (psz)
- {
- if (state & (TBSTATE_PRESSED | TBSTATE_CHECKED))
- {
- x++;
- if (ptb->ci.style & TBSTYLE_LIST)
- y++;
- }
- if (ptb->ci.style & TBSTYLE_LIST)
- {
- x += ptb->iDxBitmap + LIST_GAP;
- dx -= ptb->iDxBitmap + LIST_GAP;
- }
- else {
- y += offy + ptb->iDyBitmap;
- dy -= offy + ptb->iDyBitmap;
- }
- DrawString(ptb, hdc, x + 1, y + 1, dx - g_cxEdge, dy - g_cyEdge,
- psz,
- (state & (TBSTATE_HIGHLIGHTED)) && (ptb->ci.style & TBSTYLE_LIST));
- }
- }
- void FAR PASCAL DrawButton(HDC hdc, int x, int y, PTBSTATE ptb, LPTBBUTTON ptButton, BOOL fActive)
- {
- int yOffset;
- HBRUSH hbrOld;
- UINT state;
- int dxFace, dyFace;
- int xCenterOffset;
- int dx = TBWidthOfButton(ptb, ptButton);
- HFONT oldhFont;
- int dy = ptb->iButHeight;
- NMCUSTOMDRAW nmcd;
- DWORD dwRet;
- COLORREF clrSave = SetTextColor(hdc, g_clrBtnText);
- state = (UINT)ptButton->fsState;
- // make local copy of state and do proper overriding
- if (state & TBSTATE_INDETERMINATE) {
- if (state & TBSTATE_PRESSED)
- state &= ~TBSTATE_INDETERMINATE;
- else if (state & TBSTATE_ENABLED)
- state = TBSTATE_INDETERMINATE;
- else
- state &= ~TBSTATE_INDETERMINATE;
- }
- if (!fActive) {
- state &= ~TBSTATE_ENABLED;
- }
- oldhFont = SelectObject(hdc, ptb->hfontIcon);
- nmcd.hdc = hdc;
- nmcd.dwItemSpec = ptButton->idCommand;
- nmcd.uItemState = 0;
- if (state & TBSTATE_CHECKED)
- nmcd.uItemState |= CDIS_CHECKED;
- if (state & TBSTATE_PRESSED)
- nmcd.uItemState |= CDIS_SELECTED;
- if (!(state & TBSTATE_ENABLED))
- nmcd.uItemState |= CDIS_DISABLED;
- if ((ptb->ci.style & TBSTYLE_FLAT) && (&ptb->Buttons[ptb->nCurHTButton]==ptButton))
- nmcd.uItemState |= CDIS_HOT;
- nmcd.lItemlParam = 0;
- dwRet = CICustomDrawNotify(&ptb->ci, CDDS_ITEMPREPAINT, &nmcd);
- if (!(dwRet & CDRF_SKIPDEFAULT))
- {
- dxFace = ptb->iButWidth - (2 * g_cxEdge);// this the witdh of the face, not the entire button (dropdown case)
- dyFace = dy - (2 * g_cyEdge);
- if (!(ptb->ci.style & TBSTYLE_FLAT))
- DrawBlankButton(hdc, x, y, dx, dy, state);
- // move coordinates inside border and away from upper left highlight.
- // the extents change accordingly.
- x += g_cxEdge;
- y += g_cyEdge;
- // calculate offset of face from (x,y). y is always from the top,
- // so the offset is easy. x needs to be centered in face.
- yOffset = 1;
- if (ptb->ci.style & TBSTYLE_LIST)
- xCenterOffset = XSLOP / 2;
- else
- xCenterOffset = (dxFace - ptb->iDxBitmap)/2;
- if (state & (TBSTATE_PRESSED | TBSTATE_CHECKED))
- {
- // pressed state moves down and to the right
- xCenterOffset++;
- yOffset++;
- }
- // draw the dithered background
- if ((state & (TBSTATE_CHECKED | TBSTATE_INDETERMINATE)) || ((state & TBSTATE_HIGHLIGHTED)
- && !(ptb->ci.style & TBSTYLE_FLAT)))
- {
- hbrOld = SelectObject(hdc, g_hbrMonoDither);
- if (hbrOld)
- {
- COLORREF clrText, clrBack;
- #ifdef TBHIGHLIGHT_BACK
- if (state & TBSTATE_HIGHLIGHTED)
- clrText = SetTextColor(hdc, g_clrHighlight);
- else
- #endif
- clrText = SetTextColor(hdc, g_clrBtnHighlight); // 0 -> 0
- clrBack = SetBkColor(hdc, g_clrBtnFace); // 1 -> 1
- // only draw the dither brush where the mask is 1's
- PatBlt(hdc, x, y, dxFace, dyFace, PATCOPY);
- SelectObject(hdc, hbrOld);
- SetTextColor(hdc, clrText);
- SetBkColor(hdc, clrBack);
- }
- }
- // now put on the face
- // TODO: Validate himlDisabled and ensure that the index is in range
- if ((state & TBSTATE_ENABLED) || ptb->himlDisabled)
- {
- // regular version
- DrawFace(ptb, ptButton, hdc, x, y, xCenterOffset, yOffset, dxFace, dyFace, state);
- }
- if (!(state & TBSTATE_ENABLED))
- {
- HBITMAP hbmOld;
- //initialize the monochrome dc
- if (!ptb->hdcMono) {
- ptb->hdcMono = CreateCompatibleDC(hdc);
- if (!ptb->hdcMono)
- return;
- SetTextColor(ptb->hdcMono, 0L);
- SelectObject(ptb->hdcMono, ptb->hfontIcon);
- }
- hbmOld = SelectObject(ptb->hdcMono, ptb->hbmMono);
- // disabled version (or indeterminate)
- CreateMask(ptb, ptButton, xCenterOffset, yOffset, dxFace, dyFace, (ptb->himlDisabled == NULL));
- SetTextColor(hdc, 0L); // 0's in mono -> 0 (for ROP)
- SetBkColor(hdc, 0x00FFFFFF); // 1's in mono -> 1
- // draw glyph's white understrike
- if (!(state & TBSTATE_INDETERMINATE)) {
- hbrOld = SelectObject(hdc, g_hbrBtnHighlight);
- if (hbrOld) {
- // draw hilight color where we have 0's in the mask
- BitBlt(hdc, x + 1, y + 1, dxFace, dyFace, ptb->hdcMono, 0, 0, PSDPxax);
- SelectObject(hdc, hbrOld);
- }
- }
- // gray out glyph
- hbrOld = SelectObject(hdc, g_hbrBtnShadow);
- if (hbrOld) {
- // draw the shadow color where we have 0's in the mask
- BitBlt(hdc, x, y, dxFace, dyFace, ptb->hdcMono, 0, 0, PSDPxax);
- SelectObject(hdc, hbrOld);
- }
- if (state & TBSTATE_CHECKED) {
- BitBlt(ptb->hdcMono, 1, 1, dxFace - 1, dyFace - 1, ptb->hdcMono, 0, 0, SRCAND);
- }
- SelectObject(ptb->hdcMono, hbmOld);
- }
- if ((ptButton->fsStyle & TBSTYLE_DROPDOWN) && !(ptb->ci.style & TBSTYLE_FLAT))
- {
- RECT rc;
- POINT pts[3];
- int iHeight;
- int iWidth;
- HBRUSH hbr;
- HPEN hpen;
- rc.left = x - (2*g_cxEdge) + ptb->iButWidth + (yOffset-1);
- rc.top = y + g_cyBorder;
- rc.bottom = y + dy - (2 * g_cyEdge) - (2*g_cyBorder);
- rc.right = rc.left - ptb->iButWidth + dx;
- DrawEdge(hdc, &rc, EDGE_ETCHED, BF_LEFT);
- rc.left += g_cxEdge;
- rc.right -= g_cxEdge;
- rc.top += yOffset;
- iWidth = RECTWIDTH(rc);
- iWidth -= g_cxEdge; // make it a little smaller than the rect
- if (iWidth < 3) iWidth = 3;
- iWidth &= (~1); // make it even
- iHeight = (iWidth) / 2;
- pts[0].y = pts[1].y = (RECTHEIGHT(rc) - iHeight + 1)/2 + rc.top; // +1 to bias lower
- pts[2].y = pts[0].y + iHeight;
- pts[0].x = (RECTWIDTH(rc) - iWidth + 1) / 2 + rc.left; // +1 to bias right
- pts[1].x = pts[0].x + iWidth;
- pts[2].x = pts[0].x + iWidth/2;
- hbr = GetStockObject(BLACK_BRUSH);
- hpen = GetStockObject(BLACK_PEN);
- hbr = SelectObject(hdc, hbr);
- hpen = SelectObject(hdc, hpen);
- Polygon(hdc, pts, 3);
- SelectObject(hdc, hbr);
- SelectObject(hdc, hpen);
- }
- }
- if (dwRet & CDRF_NOTIFYPOSTPAINT)
- CICustomDrawNotify(&ptb->ci, CDDS_ITEMPOSTPAINT, &nmcd);
- SetTextColor(hdc, clrSave);
- if (oldhFont)
- SelectObject(hdc, oldhFont);
- }
- // make sure that g_hbmMono is big enough to do masks for this
- // size of button. if not, fail.
- BOOL NEAR PASCAL CheckMonoMask(PTBSTATE ptb, int width, int height)
- {
- BITMAP bm;
- HBITMAP hbmTemp;
- if (ptb->hbmMono) {
- GetObject(ptb->hbmMono, sizeof(BITMAP), &bm);
- if (width <= bm.bmWidth && height <= bm.bmHeight) {
- return TRUE;
- }
- }
- hbmTemp = CreateMonoBitmap(width, height);
- if (!hbmTemp)
- return FALSE;
- if (ptb->hbmMono)
- DeleteObject(ptb->hbmMono);
- ptb->hbmMono = hbmTemp;
- return TRUE;
- }
- /*
- ** GrowToolbar
- **
- ** Attempt to grow the button size.
- **
- ** The calling function can either specify a new internal measurement
- ** or a new external measurement.
- */
- BOOL NEAR PASCAL GrowToolbar(PTBSTATE ptb, int newButWidth, int newButHeight, BOOL bInside)
- {
- if (!newButWidth)
- newButWidth = DEFAULTBUTTONX;
- if (!newButHeight)
- newButHeight = DEFAULTBUTTONY;
- // if growing based on inside measurement, get full size
- if (bInside)
- {
- if (ptb->ci.style & TBSTYLE_LIST)
- newButWidth += ptb->iDxBitmap + LIST_GAP;
- newButHeight += YSLOP;
- newButWidth += XSLOP;
- // if toolbar already has strings, don't shrink width it because it
- // might clip room for the string
- if ((newButWidth < ptb->iButWidth) && ptb->nStrings)
- newButWidth = ptb->iButWidth;
- }
- else {
- if (newButHeight == -1)
- newButHeight = ptb->iButHeight;
- if (newButWidth == -1)
- newButWidth = ptb->iButWidth;
- if (newButHeight < ptb->iDyBitmap + YSLOP)
- newButHeight = ptb->iDyBitmap + YSLOP;
- if (newButWidth < ptb->iDxBitmap + XSLOP)
- newButWidth = ptb->iDxBitmap + XSLOP;
- }
- // if the size of the toolbar is actually growing, see if shadow
- // bitmaps can be made sufficiently large.
- if (!ptb->hbmMono || (newButWidth > ptb->iButWidth) || (newButHeight > ptb->iButHeight)) {
- if (!CheckMonoMask(ptb, newButWidth, newButHeight))
- return(FALSE);
- }
- if (!bInside && (ptb->iButWidth != newButWidth) || (ptb->iButHeight != newButHeight))
- InvalidateRect(ptb->ci.hwnd, NULL, TRUE);
- ptb->iButWidth = newButWidth;
- ptb->iButHeight = newButHeight;
- // bar height has 2 pixels above, 2 below
- if (ptb->ci.style & TBSTYLE_TRANSPARENT)
- ptb->iYPos = 0;
- else
- ptb->iYPos = 2;
- FlushToolTipsMgr(ptb);
- return TRUE;
- }
- BOOL NEAR PASCAL SetBitmapSize(PTBSTATE ptb, int width, int height)
- {
- int realh;
- if (!width)
- width = 1;
- if (!height)
- height = 1;
- if (width == -1)
- width = ptb->iDxBitmap;
- if (height == -1)
- height = ptb->iDyBitmap;
- realh = height;
- if ((ptb->iDxBitmap == width) && (ptb->iDyBitmap == height))
- return TRUE;
- if (TBHasStrings(ptb))
- realh = HeightWithString(ptb, height);
- if (GrowToolbar(ptb, width, realh, TRUE)) {
- ptb->iDxBitmap = width;
- ptb->iDyBitmap = height;
- // the size changed, we need to rebuild the imagelist
- TBInvalidateImageList(ptb);
- return TRUE;
- }
- return FALSE;
- }
- void NEAR PASCAL TB_OnSysColorChange(PTBSTATE ptb)
- {
- InitGlobalColors();
- // Reset all of the bitmaps
- if (ptb->himl)
- ImageList_SetBkColor(ptb->himl, (ptb->ci.style & TBSTYLE_TRANSPARENT) ? CLR_NONE : g_clrBtnFace);
- if (ptb->himlHot)
- ImageList_SetBkColor(ptb->himlHot, (ptb->ci.style & TBSTYLE_TRANSPARENT) ? CLR_NONE : g_clrBtnFace);
- }
- #define CACHE 0x01
- #define BUILD 0x02
- void PASCAL ReleaseMonoDC(PTBSTATE ptb)
- {
- if (ptb->hdcMono) {
- SelectObject(ptb->hdcMono, g_hfontSystem);
- DeleteDC(ptb->hdcMono);
- ptb->hdcMono = NULL;
- }
- }
- void TB_OnEraseBkgnd(PTBSTATE ptb, HDC hdc)
- {
- NMCUSTOMDRAW nmcd;
- DWORD dwRes = FALSE;
- nmcd.hdc = hdc;
- nmcd.uItemState = 0;
- nmcd.lItemlParam = 0;
- if (ptb->ci.style & TBSTYLE_CUSTOMERASE) {
- ptb->ci.dwCustom = CICustomDrawNotify(&ptb->ci, CDDS_PREERASE, &nmcd);
- } else {
- ptb->ci.dwCustom = CDRF_DODEFAULT;
- }
- if (!(ptb->ci.dwCustom & CDRF_SKIPDEFAULT))
- {
- // for transparent toolbars, forward erase background to parent
- // but handle thru DefWindowProc in the event parent doesn't paint
- if (!(ptb->ci.style & TBSTYLE_TRANSPARENT) ||
- !CCForwardEraseBackground(ptb->ci.hwnd, hdc))
- DefWindowProc(ptb->ci.hwnd, WM_ERASEBKGND, (WPARAM) hdc, 0);
- }
- if (ptb->ci.dwCustom & CDRF_NOTIFYPOSTERASE)
- CICustomDrawNotify(&ptb->ci, CDDS_POSTERASE, &nmcd);
- }
- void NEAR PASCAL ToolbarPaint(PTBSTATE ptb, HDC hdcIn)
- {
- RECT rc;
- HDC hdc;
- PAINTSTRUCT ps;
- int iButton, xButton, yButton, cxBar;
- PTBBUTTON pAllButtons = ptb->Buttons;
- NMCUSTOMDRAW nmcd;
- GetClientRect(ptb->ci.hwnd, &rc);
- cxBar = rc.right - rc.left;
- if (hdcIn)
- {
- hdc = hdcIn;
- }
- else
- hdc = BeginPaint(ptb->ci.hwnd, &ps);
- if (!rc.right)
- goto Error1;
- nmcd.hdc = hdc;
- nmcd.uItemState = 0;
- nmcd.lItemlParam = 0;
- ptb->ci.dwCustom = CICustomDrawNotify(&ptb->ci, CDDS_PREPAINT, &nmcd);
- if (!(ptb->ci.dwCustom & CDRF_SKIPDEFAULT))
- {
- if (!ptb->fHimlValid)
- TBBuildImageList(ptb);
- yButton = ptb->iYPos;
- rc.top = ptb->iYPos;
- rc.bottom = ptb->iYPos + ptb->iButHeight;
- for (iButton = 0, xButton = ptb->xFirstButton;
- iButton < ptb->iNumButtons; iButton++)
- {
- PTBBUTTON pButton = &pAllButtons[iButton];
- if (!(pButton->fsState & TBSTATE_HIDDEN))
- {
- int cxButton = TBWidthOfButton(ptb, pButton);
- if (!(pButton->fsStyle & TBSTYLE_SEP) || (ptb->ci.style & TBSTYLE_FLAT))
- {
- // is there anything to draw?
- rc.left = xButton;
- rc.right = xButton + cxButton;
- if (RectVisible(hdc, &rc))
- {
- if (pButton->fsStyle & TBSTYLE_SEP)
- {
- // must be a flat separator
- if (ptb->ci.style & CCS_VERT)
- {
- int iSave = rc.top;
- rc.top += ((rc.bottom - rc.top) - 1) / 2;
- rc.top = iSave;
- InflateRect(&rc, -g_cxEdge, 0);
- DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOP);
- InflateRect(&rc, g_cxEdge, 0);
- }
- else
- {
- rc.left += (cxButton - 1) / 2;
- InflateRect(&rc, 0, -g_cyEdge);
- DrawEdge(hdc, &rc, EDGE_ETCHED, BF_LEFT);
- InflateRect(&rc, 0, g_cyEdge);
- }
- }
- else
- DrawButton(hdc, xButton, yButton, ptb, pButton, ptb->fActive);
- }
- }
- xButton += (cxButton - s_dxOverlap);
- if (pButton->fsState & TBSTATE_WRAP)
- {
- int dy;
- if (pButton->fsStyle & TBSTYLE_SEP)
- {
- if (ptb->ci.style & TBSTYLE_FLAT)
- {
- RECT rcMid;
- rcMid.top = rc.top + ptb->iButHeight + ((pButton->iBitmap - 1) / 2);
- rcMid.bottom = rcMid.top + g_cxEdge;
- rcMid.left = g_cxEdge;
- rcMid.right = cxBar - g_cxEdge;
- DrawEdge(hdc, &rcMid, EDGE_ETCHED, BF_TOP);
- dy = ptb->iButHeight + pButton->iBitmap;
- }
- else
- dy = ptb->iButHeight + pButton->iBitmap * 2 / 3;
- }
- else
- dy = ptb->iButHeight;
- xButton = ptb->xFirstButton;
- yButton += dy;
- rc.top += dy;
- rc.bottom += dy;
- }
- }
- }
- ReleaseMonoDC(ptb);
- }
- if (ptb->ci.dwCustom & CDRF_NOTIFYPOSTPAINT)
- {
- nmcd.hdc = hdc;
- nmcd.uItemState = 0;
- nmcd.lItemlParam = 0;
- CICustomDrawNotify(&ptb->ci, CDDS_POSTPAINT, &nmcd);
- }
- Error1:
- if (hdcIn == NULL)
- EndPaint(ptb->ci.hwnd, &ps);
- }
- BOOL NEAR PASCAL GetItemRect(PTBSTATE ptb, UINT uButton, LPRECT lpRect)
- {
- UINT iButton, xPos, yPos;
- PTBBUTTON pButton;
- if (uButton >= (UINT)ptb->iNumButtons
- || (ptb->Buttons[uButton].fsState & TBSTATE_HIDDEN))
- {
- return FALSE;
- }
- xPos = ptb->xFirstButton;
- yPos = ptb->iYPos;
- for (iButton = 0, pButton = ptb->Buttons; iButton < uButton; iButton++, pButton++)
- {
- if (!(pButton->fsState & TBSTATE_HIDDEN))
- {
- xPos += TBWidthOfButton(ptb, pButton) - s_dxOverlap;
- if (pButton->fsState & TBSTATE_WRAP)
- {
- yPos += ptb->iButHeight;
- if (pButton->fsStyle & TBSTYLE_SEP)
- {
- if (ptb->ci.style & TBSTYLE_FLAT)
- yPos += pButton->iBitmap;
- else
- yPos += pButton->iBitmap * 2 / 3;
- }
- xPos = ptb->xFirstButton;
- }
- }
- }
- // pButton should now point at the required button, and xPos should be
- // its left edge. Note that we already checked if the button was hidden above
- lpRect->left = xPos;
- lpRect->right = xPos + TBWidthOfButton(ptb, pButton);
- lpRect->top = yPos;
- lpRect->bottom = yPos + ptb->iButHeight;
- return TRUE;
- }
- void NEAR PASCAL InvalidateButton(PTBSTATE ptb, PTBBUTTON pButtonToPaint, BOOL fErase)
- {
- RECT rc;
- if (GetItemRect(ptb, pButtonToPaint-ptb->Buttons, &rc))
- {
- InvalidateRect(ptb->ci.hwnd, &rc, fErase);
- }
- }
- // do hit testing by sliding the origin of the supplied point
- //
- // returns:
- // >= 0 index of non sperator item hit
- // < 0 index of seperator or nearest non seperator item (area just below and to the left)
- //
- // +--------------------------------------
- // | -1 -1 -1 -1
- // | btn sep btn
- // | +-----+ +-----+
- // | | | | |
- // | -1 | 0 | -1 | 2 | -3
- // | | | | |
- // | +-----+ +-----+
- // |
- // | -1 -1 -1 -2 -3
- //
- int FAR PASCAL TBHitTest(PTBSTATE ptb, int xPos, int yPos)
- {
- int prev = 0;
- int last = 0;
- int i;
- RECT rc;
- if (ptb->iNumButtons == 0)
- return(-1);
- for (i=0; i<ptb->iNumButtons; i++)
- {
- // BUGBUG.. this makes it n**2
- if (GetItemRect(ptb, i, &rc))
- {
- if (yPos >= rc.top && yPos <= rc.bottom)
- {
- if (xPos >= rc.left && xPos <= rc.right)
- {
- if (ptb->Buttons[i].fsStyle & TBSTYLE_SEP)
- return - i - 1;
- else
- return i;
- }
- else
- {
- prev = i + 1;
- }
- }
- else
- {
- last = i;
- }
- }
- }
- if (prev)
- return -1 - prev;
- else if (yPos > rc.bottom)
- // this means that we are off the bottom of the toolbar
- return(- i - 1);
- return last + 1;
- }
- int NEAR PASCAL CountRows(PTBSTATE ptb)
- {
- PTBBUTTON pButton, pBtnLast;
- int rows = 1;
- pBtnLast = &(ptb->Buttons[ptb->iNumButtons]);
- for (pButton = ptb->Buttons; pButton<pBtnLast; pButton++) {
- if (pButton->fsState & TBSTATE_WRAP) {
- rows++;
- if (pButton->fsStyle & TBSTYLE_SEP)
- rows++;
- }
- }
- return rows;
- }
- /**** WrapToolbar:
- * The buttons in the toolbar is layed out from left to right,
- * top to bottom. If adding another button to the current row,
- * while computing the layout, would cause that button to extend
- * beyond the right edge or the client area, then locate a break-
- * point (marked with the TBSTATE_WRAP flag). A break-point is:
- *
- * a) The right-most separator on the current row.
- *
- * b) The right-most button if there is no separator on the current row.
- *
- * A new row is also started at the end of any button group (sequence
- * of buttons that are dlimited by separators) that are taller than
- * or equal to two rows.
- */
- void NEAR PASCAL WrapToolbar(PTBSTATE ptb, int dx, LPRECT lpRect, int FAR *pRows)
- {
- BOOL fInvalidate = FALSE;
- PTBBUTTON pButton, pBtnT, pBtnLast;
- int xPos, yPos, xMax;
- BOOL bFoundIt;
- BOOL bNextBreak = FALSE;
- xMax = ptb->iButWidth;
- xPos = ptb->xFirstButton;
- yPos = ptb->iYPos;
- pBtnLast = &(ptb->Buttons[ptb->iNumButtons]);
- if (pRows)
- (*pRows)=1;
- for (pButton = ptb->Buttons; pButton<pBtnLast; pButton++)
- {
- pButton->fsState &= ~TBSTATE_WRAP;
- if (!(pButton->fsState & TBSTATE_HIDDEN))
- {
- xPos += TBWidthOfButton(ptb, pButton) - s_dxOverlap;
- // The current row exceeds the right edge. Wrap it.
- if (!(pButton->fsStyle&TBSTYLE_SEP) && (xPos > dx)) {
- for (pBtnT=pButton, bFoundIt = FALSE;
- pBtnT>ptb->Buttons && !(pBtnT->fsState & TBSTATE_WRAP);
- pBtnT--)
- {
- if ((pBtnT->fsStyle & TBSTYLE_SEP) &&
- !(pBtnT->fsState & TBSTATE_HIDDEN))
- {
- fInvalidate = TRUE;
- pBtnT->fsState |= TBSTATE_WRAP;
- xPos = ptb->xFirstButton;
- if (ptb->ci.style & TBSTYLE_FLAT)
- yPos += pBtnT->iBitmap + ptb->iButHeight;
- else
- yPos += pBtnT->iBitmap * 2 / 3 + ptb->iButHeight;
- bFoundIt = TRUE;
- pButton = pBtnT;
- bNextBreak = FALSE;
- if (pRows)
- (*pRows)++;
- break;
- }
- }
- // Did we find a separator? Force a wrap anyway!
- if (bFoundIt==FALSE)
- {
- pBtnT = pButton;
- if (pButton!=ptb->Buttons) {
- /* Back-up to first non-hidden button. */
- do {
- pBtnT--;
- } while ((pBtnT>ptb->Buttons) &&
- (pBtnT->fsState & TBSTATE_HIDDEN));
- /* Is it already wrapped? */
- if (pBtnT->fsState & TBSTATE_WRAP)
- pBtnT = pButton;
- }
- fInvalidate = TRUE;
- pBtnT->fsState |= TBSTATE_WRAP;
- xPos = ptb->xFirstButton;
- yPos += ptb->iButHeight;
- pButton = pBtnT;
- bNextBreak = TRUE;
- }
- // Count another row.
- if (pRows)
- (*pRows)++;
- }
- else
- {
- UINT fOldState = pButton->fsState;
- pButton->fsState &= ~TBSTATE_WRAP;
- if ((pButton->fsStyle&TBSTYLE_SEP) && (bNextBreak))
- {
- bNextBreak = FALSE;
- pButton->fsState |= TBSTATE_WRAP;
- xPos = ptb->xFirstButton;
- if (ptb->ci.style & TBSTYLE_FLAT)
- yPos += ptb->iButHeight + pButton->iBitmap;
- else
- yPos += ptb->iButHeight + pButton->iBitmap * 2 / 3 ;
- if (pRows)
- (*pRows)+=2;
- }
- if (fOldState != pButton->fsState) {
- fInvalidate = TRUE;
- }
- }
- if (!(pButton->fsStyle&TBSTYLE_SEP))
- xMax = max(xPos, xMax);
- }
- }
- if (lpRect)
- {
- lpRect->left = 0;
- lpRect->right = xMax;
- lpRect->top = 0;
- lpRect->bottom = yPos + ptb->iYPos + ptb->iButHeight;
- }
- if (fInvalidate)
- InvalidateRect(ptb->ci.hwnd, NULL, TRUE);
- }
- BOOL NEAR PASCAL BoxIt(PTBSTATE ptb, int height, BOOL fLarger, LPRECT lpRect)
- {
- int dx, bwidth;
- int rows, prevRows, prevWidth;
- RECT rcCur;
- if (height<1)
- height = 1;
- rows = CountRows(ptb);
- if (height==rows || ptb->iNumButtons==0)
- {
- GetClientRect(ptb->ci.hwnd, lpRect);
- return FALSE;
- }
- bwidth = ptb->iButWidth-s_dxOverlap;
- prevRows = ptb->iNumButtons+1;
- prevWidth = bwidth;
- for (rows=height+1, dx = bwidth; rows>height;dx+=bwidth/4)
- {
- WrapToolbar(ptb, dx, &rcCur, &rows);
- if (rows<prevRows && rows>height)
- {
- prevWidth = dx;
- prevRows = rows;
- }
- }
- if (rows<height && fLarger)
- {
- WrapToolbar(ptb, prevWidth, &rcCur, NULL);
- }
- if (lpRect)
- *lpRect = rcCur;
- return TRUE;
- }
- int FAR PASCAL PositionFromID(PTBSTATE ptb, int id)
- {
- int i;
- // Handle case where this is sent at the wrong time..
- if (ptb == NULL)
- return -1;
- // note, we don't skip seperators, so you better not have conflicting
- // cmd ids and seperator ids.
- for (i = 0; i < ptb->iNumButtons; i++)
- if (ptb->Buttons[i].idCommand == id)
- return i; // position found
- return -1; // ID not found!
- }
- // check a radio button by button index.
- // the button matching idCommand was just pressed down. this forces
- // up all other buttons in the group.
- // this does not work with buttons that are forced up with
- void NEAR PASCAL MakeGroupConsistant(PTBSTATE ptb, int idCommand)
- {
- int i, iFirst, iLast, iButton;
- int cButtons = ptb->iNumButtons;
- PTBBUTTON pAllButtons = ptb->Buttons;
- iButton = PositionFromID(ptb, idCommand);
- if (iButton < 0)
- return;
- // assertion
- // if (!(pAllButtons[iButton].fsStyle & TBSTYLE_CHECK))
- // return;
- // did the pressed button just go down?
- if (!(pAllButtons[iButton].fsState & TBSTATE_CHECKED))
- return; // no, can't do anything
- // find the limits of this radio group
- for (iFirst = iButton; (iFirst > 0) && (pAllButtons[iFirst].fsStyle & TBSTYLE_GROUP); iFirst--)
- if (!(pAllButtons[iFirst].fsStyle & TBSTYLE_GROUP))
- iFirst++;
- cButtons--;
- for (iLast = iButton; (iLast < cButtons) && (pAllButtons[iLast].fsStyle & TBSTYLE_GROUP); iLast++);
- if (!(pAllButtons[iLast].fsStyle & TBSTYLE_GROUP))
- iLast--;
- // search for the currently down button and pop it up
- for (i = iFirst; i <= iLast; i++) {
- if (i != iButton) {
- // is this button down?
- if (pAllButtons[i].fsState & TBSTATE_CHECKED) {
- pAllButtons[i].fsState &= ~TBSTATE_CHECKED; // pop it up
- InvalidateButton(ptb, &pAllButtons[i], TRUE);
- break; // only one button is down right?
- }
- }
- }
- }
- void NEAR PASCAL DestroyStrings(PTBSTATE ptb)
- {
- PTSTR *p;
- PTSTR end = 0, start = 0;
- int i;
- p = ptb->pStrings;
- for (i = 0; i < ptb->nStrings; i++) {
- if (!((*p < end) && (*p > start))) {
- start = (*p);
- end = start + (LocalSize((HANDLE)*p) / sizeof(TCHAR));
- LocalFree((HANDLE)*p);
- }
- p++;
- }
- LocalFree((HANDLE)ptb->pStrings);
- }
- #define MAXSTRINGSIZE 1024
- int NEAR PASCAL AddStrings(PTBSTATE ptb, WPARAM wParam, LPARAM lParam)
- {
- int i = 0,j = 0, cxMax = 0;
- LPTSTR lpsz;
- PTSTR pString, psz;
- int numstr;
- PTSTR *pFoo;
- PTSTR *pOffset;
- TCHAR cSeparator;
- int len;
- // read the string as a resource
- if (wParam != 0) {
- pString = (PTSTR)LocalAlloc(LPTR, (MAXSTRINGSIZE * sizeof (TCHAR)));
- if (!pString)
- return -1;
- i = LoadString((HINSTANCE)wParam, LOWORD(lParam), (LPTSTR)pString, MAXSTRINGSIZE);
- if (!i) {
- LocalFree(pString);
- return -1;
- }
- // realloc string buffer to actual needed size
- LocalReAlloc(pString, (i+1) * sizeof (TCHAR), LMEM_MOVEABLE);
- // convert separators to '' and count number of strings
- cSeparator = *pString;
- #if !defined(UNICODE) // && defined(DBCS)
- for (numstr = 0, psz = pString + 1, i--; i; i--, psz++ ) {
- if (*psz == cSeparator) {
- if (i != 1) // We don't want to count the second terminator as another string
- numstr++;
- *psz = 0; // terminate with 0
- }
- // extra i-- if DBCS
- if (IsDBCSLeadByte(*psz))
- {
- *(WORD *)(psz-1) = *(WORD *)psz;
- psz++;
- i--;
- }
- else
- {
- // shift string to the left to overwrite separator identifier
- *(psz - 1) = *psz;
- }
- }
- #else
- for (numstr = 0, psz = pString + 1, i--; i; i--, psz++) {
- if (*psz == cSeparator) {
- if (i != 1) // We don't want to count the second terminator as another string
- numstr++;
- *psz = 0; // terminate with 0
- }
- // shift string to the left to overwrite separator identifier
- *(psz - 1) = *psz;
- }
- #endif
- }
- // read explicit string. copy it into local memory, too.
- else {
- // find total length and number of strings
- for (i = 0, numstr = 0, lpsz = (LPTSTR)lParam;;) {
- i++;
- if (*lpsz == 0) {
- numstr++;
- if (*(lpsz + 1) == 0)
- break;
- }
- lpsz++;
- }
- pString = (PTSTR)LocalAlloc(LPTR, (i * sizeof (TCHAR)));
- if (!pString)
- return -1;
- hmemcpy(pString, (void FAR *)lParam, i * sizeof(TCHAR));
- }
- // make room for increased string pointer table
- pFoo = (PTSTR *)CCLocalReAlloc(ptb->pStrings,
- (ptb->nStrings + numstr) * sizeof(PTSTR));
- if (!pFoo) {
- goto Failure;
- }
- ptb->pStrings = pFoo;
- // pointer to next open slot in string index table.
- pOffset = ptb->pStrings + ptb->nStrings;
- for (i = 0; i < numstr; i++, pOffset++)
- {
- *pOffset = pString;
- len = lstrlen(pString);
- pString += len + 1;
- }
- // is the world big enough to handle the larger buttons?
- i = ptb->nStrings;
- ptb->nStrings += numstr;
- if (!TBRecalc(ptb))
- {
- ptb->nStrings -= numstr;
- // back out changes.
- ptb->pStrings = (PTSTR *)CCLocalReAlloc(ptb->pStrings,
- ptb->nStrings * sizeof(PTSTR));
- Failure:
- LocalFree(pString);
- return -1;
- }
- return i; // index of first added string
- }
- #ifdef WIN32
- void NEAR PASCAL MapToStandardBitmaps(HINSTANCE FAR *phinst, UINT FAR * pidBM, int FAR *pnButtons)
- {
- if (*phinst == HINST_COMMCTRL) {
- *phinst = g_hinst;
- // low 2 bits are coded M(mono == ~color) L(large == ~small)
- // 0 0 -> color small
- // 0 1 -> color large
- // ...
- // 1 1 -> mono large
- switch (*pidBM)
- {
- case IDB_STD_SMALL_COLOR:
- case IDB_STD_LARGE_COLOR:
- case IDB_STD_SMALL_MONO:
- case IDB_STD_LARGE_MONO:
- *pidBM = IDB_STDTB_SMALL_COLOR + (*pidBM & 1);
- *pnButtons = STD_PRINT + 1;
- break;
- case IDB_HIST_SMALL_COLOR:
- case IDB_HIST_LARGE_COLOR:
- //case IDB_HIST_SMALL_MONO:
- //case IDB_HIST_LARGE_MONO:
- *pidBM = IDB_HISTTB_SMALL_COLOR + (*pidBM & 1);
- *pnButtons = HIST_LAST + 1;
- break;
- case IDB_VIEW_SMALL_COLOR:
- case IDB_VIEW_LARGE_COLOR:
- case IDB_VIEW_SMALL_MONO:
- case IDB_VIEW_LARGE_MONO:
- *pidBM = IDB_VIEWTB_SMALL_COLOR + (*pidBM & 1);
- *pnButtons = VIEW_NEWFOLDER + 1;
- break;
- }
- }
- }
- #endif
- HBITMAP _CopyBitmap(PTBSTATE ptb, HBITMAP hbm, int cx, int cy)
- {
- HBITMAP hbmCopy;
- RECT rc = {0 ,0, cx, cy};
- HDC hdcWin;
- HDC hdcSrc, hdcDest;
- hbmCopy = CreateColorBitmap(cx, cy);
- hdcWin = GetDC(ptb->ci.hwnd);
- hdcSrc = CreateCompatibleDC(hdcWin);
- hdcDest = CreateCompatibleDC(hdcWin);
- if (hdcWin && hdcSrc && hdcDest) {
- SelectObject(hdcSrc, hbm);
- SelectObject(hdcDest, hbmCopy);
- // fill the background
- PatB(hdcDest, 0, 0, cx, cy, g_clrBtnFace);
- BitBlt(hdcDest, 0, 0, cx, cy,
- hdcSrc, 0, 0, SRCCOPY);
- }
- if (hdcWin)
- ReleaseDC(ptb->ci.hwnd, hdcWin);
- if (hdcSrc)
- DeleteDC(hdcSrc);
- if (hdcDest)
- DeleteDC(hdcDest);
- return hbmCopy;
- }
- BOOL TBAddBitmapToImageList(PTBSTATE ptb, PTBBMINFO pTemp)
- {
- HBITMAP hbm = NULL, hbmTemp = NULL;
- if (!ptb->himl) {
- ptb->himl = ImageList_Create(ptb->iDxBitmap, ptb->iDyBitmap, ILC_MASK | ILC_COLORDDB, 4, 4);
- if (!ptb->himl)
- return(FALSE);
- ImageList_SetBkColor(ptb->himl, (ptb->ci.style & TBSTYLE_TRANSPARENT) ? CLR_NONE : g_clrBtnFace);
- }
- if (pTemp->hInst) {
- hbm = hbmTemp = CreateMappedBitmap(pTemp->hInst, pTemp->wID, 0, NULL, 0);
- } else if (pTemp->wID) {
- hbm = (HBITMAP)pTemp->wID;
- }
- if (hbm) {
- //
- // Fix up bitmaps that aren't iDxBitmap x iDyBitmap
- //
- BITMAP bm;
- GetObject( hbm, sizeof(bm), &bm);
- if (bm.bmWidth < ptb->iDxBitmap) {
- bm.bmWidth = ptb->iDxBitmap;
- }
- if (bm.bmHeight < ptb->iDyBitmap) {
- bm.bmHeight = ptb->iDyBitmap;
- }
- // Handle case when the bitmaps is smaller or larger than what it is supposed to be
- // ptb->iDxBitmaps specifies the width a bitmap should be.
- // The error cases we are catching are:
- // If the pTemp->nButtons is 0 then we assume there is one button
- // If the pTemp->nButtons specifies a number but the width of the bitmap is not right,
- // then we assume that nButtons is right and change the width of the bitmap
- if (!pTemp->nButtons)
- bm.bmWidth = ptb->iDxBitmap;
- else
- bm.bmWidth = ptb->iDxBitmap * pTemp->nButtons;
- hbm = (HBITMAP)_CopyBitmap(ptb, hbm, bm.bmWidth, bm.bmHeight);
- }
- // AddMasked parties on the bitmap, so we want to use a local copy
- if (hbm) {
- ImageList_AddMasked(ptb->himl, hbm, g_clrBtnFace);
- DeleteObject(hbm);
- }
- if (hbmTemp) {
- DeleteObject(hbmTemp);
- }
- return(TRUE);
- }
- void NEAR PASCAL TBBuildImageList(PTBSTATE ptb)
- {
- int i;
- PTBBMINFO pTemp;
- ptb->fHimlValid = TRUE;
- // is the parent dealing natively with imagelists? if so,
- // don't do this back compat building
- if (ptb->fHimlNative)
- return;
- if (ptb->himl) {
- ImageList_Destroy(ptb->himl);
- ptb->himl = NULL;
- }
- for (i = 0, pTemp = ptb->pBitmaps; i < ptb->nBitmaps; i++, pTemp++) {
- TBAddBitmapToImageList(ptb, pTemp);
- }
- }
- /* Adds a new bitmap to the list of BMs available for this toolbar.
- * Returns the index of the first button in the bitmap or -1 if there
- * was an error.
- */
- int NEAR PASCAL AddBitmap(PTBSTATE ptb, int nButtons, HINSTANCE hBMInst, UINT idBM)
- {
- PTBBMINFO pTemp;
- int nBM, nIndex;
- // map things to the standard toolbar images
- #ifdef WIN32
- if (hBMInst == HINST_COMMCTRL) // -1
- {
- // set the proper dimensions...
- if (idBM & 1)
- SetBitmapSize(ptb, LARGE_DXYBITMAP, LARGE_DXYBITMAP);
- else
- SetBitmapSize(ptb, SMALL_DXYBITMAP, SMALL_DXYBITMAP);
- MapToStandardBitmaps(&hBMInst, &idBM, &nButtons);
- }
- #endif
- if (ptb->pBitmaps)
- {
- /* Check if the bitmap has already been added
- */
- for (nBM=ptb->nBitmaps, pTemp=ptb->pBitmaps, nIndex=0;
- nBM>0; --nBM, ++pTemp)
- {
- if (pTemp->hInst==hBMInst && pTemp->wID==idBM)
- {
- /* We already have this bitmap, but have we "registered" all
- * the buttons in it?
- */
- if (pTemp->nButtons >= nButtons)
- return(nIndex);
- if (nBM == 1)
- {
- /* If this is the last bitmap, we can easily increase the
- * number of buttons without messing anything up.
- */
- pTemp->nButtons = nButtons;
- return(nIndex);
- }
- }
- nIndex += pTemp->nButtons;
- }
- }
- pTemp = (PTBBMINFO)CCLocalReAlloc(ptb->pBitmaps,
- (ptb->nBitmaps + 1)*sizeof(TBBMINFO));
- if (!pTemp)
- return(-1);
- ptb->pBitmaps = pTemp;
- pTemp = ptb->pBitmaps + ptb->nBitmaps;
- pTemp->hInst = hBMInst;
- pTemp->wID = idBM;
- pTemp->nButtons = nButtons;
- if (!TBAddBitmapToImageList(ptb, pTemp))
- return(-1);
- ++ptb->nBitmaps;
- for (nButtons=0, --pTemp; pTemp>=ptb->pBitmaps; --pTemp)
- nButtons += pTemp->nButtons;
- return(nButtons);
- }
- /* Adds a bitmap to the list of BMs available for this
- * toolbar. Returns the index of the first button in the bitmap or -1 if there
- * was an error.
- */
- int PASCAL TBLoadImages(PTBSTATE ptb, int id, HINSTANCE hinst)
- {
- int iTemp;
- TBBMINFO bmi;
- MapToStandardBitmaps(&hinst, &id, &iTemp);
- bmi.hInst = hinst;
- bmi.wID = id;
- bmi.nButtons = iTemp;
- if (ptb->himl)
- iTemp = ImageList_GetImageCount(ptb->himl);
- else
- iTemp = 0;
- if (!TBAddBitmapToImageList(ptb, &bmi))
- return(-1);
- ptb->fHimlNative = TRUE;
- return iTemp;
- }
- BOOL NEAR PASCAL ReplaceBitmap(PTBSTATE ptb, LPTBREPLACEBITMAP lprb)
- {
- int nBM;
- PTBBMINFO pTemp;
- #ifdef WIN32
- int iTemp;
- MapToStandardBitmaps(&lprb->hInstOld, &lprb->nIDOld, &iTemp);
- MapToStandardBitmaps(&lprb->hInstNew, &lprb->nIDNew, &lprb->nButtons);
- #endif
- for (nBM=ptb->nBitmaps, pTemp=ptb->pBitmaps;
- nBM>0; --nBM, ++pTemp)
- {
- if (pTemp->hInst==lprb->hInstOld && pTemp->wID==lprb->nIDOld)
- {
- // number of buttons must match
- pTemp->hInst = lprb->hInstNew;
- pTemp->wID = lprb->nIDNew;
- pTemp->nButtons = lprb->nButtons;
- TBInvalidateImageList(ptb);
- return TRUE;
- }
- }
- return FALSE;
- }
- void FAR PASCAL FlushToolTipsMgr(PTBSTATE ptb) {
- // change all the rects for the tool tips mgr. this is
- // cheap, and we don't do it often, so go ahead
- // and do them all.
- if(ptb->hwndToolTips) {
- UINT i;
- TOOLINFO ti;
- PTBBUTTON pButton;
- ti.cbSize = sizeof(ti);
- ti.hwnd = ptb->ci.hwnd;
- ti.lpszText = LPSTR_TEXTCALLBACK;
- for ( i = 0, pButton = ptb->Buttons;
- i < (UINT)ptb->iNumButtons;
- i++, pButton++) {
- if (!(pButton->fsStyle & TBSTYLE_SEP)) {
- ti.uId = pButton->idCommand;
- if (!GetItemRect(ptb, i, &ti.rect))
- ti.rect.left = ti.rect.right = ti.rect.top = ti.rect.bottom = 0;
- SendMessage(ptb->hwndToolTips, TTM_NEWTOOLRECT, 0, (LPARAM)((LPTOOLINFO)&ti));
- }
- }
- }
- }
- BOOL FAR PASCAL InsertButtons(PTBSTATE ptb, UINT uWhere, UINT uButtons, LPTBBUTTON lpButtons, BOOL fNative)
- {
- PTBBUTTON pIn, pOut;
- PTBSTATE ptbNew;
- UINT uAdded;
- UINT uStart;
- BOOL fRecalc;
- // comments by chee (not the original author) so they not be
- // exactly right... be warned.
- if (!ptb || !ptb->uStructSize)
- return FALSE;
- // enlarge the main structure
- ptbNew = (PTBSTATE)CCLocalReAlloc(ptb, sizeof(TBSTATE) - sizeof(TBBUTTON)
- + (ptb->iNumButtons + uButtons) * sizeof(TBBUTTON));
- if (!ptbNew)
- return FALSE;
- ptb = ptbNew;
- SetWindowInt(ptb->ci.hwnd, 0, (int)ptb);
- // if where points beyond the end, set it at the end
- if (uWhere > (UINT)ptb->iNumButtons)
- uWhere = ptb->iNumButtons;
- // Need to save these since the values gues toasted.
- uAdded = uButtons;
- uStart = uWhere;
- // move buttons above uWhere up uButton spaces
- // the uWhere gets inverted and counts to zero..
- for (pIn=ptb->Buttons+ptb->iNumButtons-1, pOut=pIn+uButtons,
- uWhere=(UINT)ptb->iNumButtons-uWhere; uWhere>0;
- --pIn, --pOut, --uWhere)
- *pOut = *pIn;
- // only need to recalc if there are strings & room enough to actually show them
- fRecalc = (TBHasStrings(ptb) && ((ptb->ci.style & TBSTYLE_LIST) || ((ptb->iDyBitmap + YSLOP + g_cyEdge) < ptb->iButHeight)));
- // now do the copy.
- for (lpButtons=(LPTBBUTTON)((LPBYTE)lpButtons+ptb->uStructSize*(uButtons-1)),
- ptb->iNumButtons+=(int)uButtons; // init
- uButtons>0; //test
- --pOut, lpButtons=(LPTBBUTTON)((LPBYTE)lpButtons-ptb->uStructSize), --uButtons)
- {
- TBInputStruct(ptb, pOut, lpButtons);
- if (TBISSTRINGPTR(pOut->iString)) {
- LPTSTR psz = (LPTSTR)pOut->iString;
- #ifdef UNICODE
- if (!fNative) {
- psz = ProduceWFromA(ptb->ci.uiCodePage, (LPSTR)psz);
- }
- #endif
- pOut->iString = 0;
- Str_Set((LPTSTR*)&pOut->iString, psz);
- #ifdef UNICODE
- if (!fNative)
- FreeProducedString(psz);
- #endif
- if (!ptb->fNoStringPool)
- fRecalc = TRUE;
- ptb->fNoStringPool = TRUE;
- }
- if(ptb->hwndToolTips && !(lpButtons->fsStyle & TBSTYLE_SEP)) {
- TOOLINFO ti;
- // don't bother setting the rect because we'll do it below
- // in FlushToolTipsMgr;
- ti.cbSize = sizeof(ti);
- ti.uFlags = 0;
- ti.hwnd = ptb->ci.hwnd;
- ti.uId = lpButtons->idCommand;
- ti.lpszText = LPSTR_TEXTCALLBACK;
- SendMessage(ptb->hwndToolTips, TTM_ADDTOOL, 0,
- (LPARAM)(LPTOOLINFO)&ti);
- }
- if ((pOut->fsStyle & TBSTYLE_SEP) && pOut->iBitmap <=0)
- pOut->iBitmap = g_dxButtonSep;
- }
- // Re-compute layout if toolbar is wrapable.
- if (ptb->ci.style & TBSTYLE_WRAPABLE) {
- SendMessage(ptb->ci.hwnd, TB_AUTOSIZE, 0, 0);
- }
- FlushToolTipsMgr(ptb);
- if (fRecalc)
- TBRecalc(ptb);
- //
- // Reorder notification so apps can go requery what's on the toolbar if
- // more than 1 button was added; otherwise, just say create.
- //
- if (uAdded == 1)
- MyNotifyWinEvent(EVENT_OBJECT_CREATE, ptb->ci.hwnd, OBJID_CLIENT,
- uWhere+1);
- else
- MyNotifyWinEvent(EVENT_OBJECT_REORDER, ptb->ci.hwnd, OBJID_CLIENT, 0);
- // We need to completely redraw the toolbar at this point.
- // this MUST be done last!
- // tbrecalc and others will nuke out invalid area and we won't paint if this isn't last
- InvalidateRect(ptb->ci.hwnd, NULL, TRUE);
- return(TRUE);
- }
- /* Notice that the state structure is not realloc'ed smaller at this
- * point. This is a time optimization, and the fact that the structure
- * will not move is used in other places.
- */
- BOOL FAR PASCAL DeleteButton(PTBSTATE ptb, UINT uIndex)
- {
- PTBBUTTON pIn, pOut;
- BOOL fRecalc;
- if (uIndex >= (UINT)ptb->iNumButtons)
- return FALSE;
- MyNotifyWinEvent(EVENT_OBJECT_DESTROY, ptb->ci.hwnd, OBJID_CLIENT, uIndex+1);
- if (ptb->hwndToolTips) {
- TOOLINFO ti;
- ti.cbSize = sizeof(ti);
- ti.hwnd = ptb->ci.hwnd;
- ti.uId = ptb->Buttons[uIndex].idCommand;
- SendMessage(ptb->hwndToolTips, TTM_DELTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
- }
- --ptb->iNumButtons;
- pOut = ptb->Buttons + uIndex;
- fRecalc = (pOut->fsState & TBSTATE_WRAP);
- for (pIn = pOut + 1; uIndex<(UINT)ptb->iNumButtons; ++uIndex, ++pIn, ++pOut)
- {
- fRecalc |= (pIn->fsState & TBSTATE_WRAP);
- *pOut = *pIn;
- }
- // We need to completely recalc or redraw the toolbar at this point.
- if ((ptb->ci.style & TBSTYLE_WRAPABLE) && fRecalc)
- {
- RECT rc;
- HWND hwnd = ptb->ci.hwnd;
- if (!(ptb->ci.style & CCS_NORESIZE) && !(ptb->ci.style & CCS_NOPARENTALIGN))
- hwnd = GetParent(hwnd);
- GetWindowRect(hwnd, &rc);
- WrapToolbar(ptb, rc.right - rc.left, &rc, NULL);
- FlushToolTipsMgr(ptb);
- }
- InvalidateRect(ptb->ci.hwnd, NULL, TRUE);
- FlushToolTipsMgr(ptb);
- return TRUE;
- }
- // deal with old TBBUTON structs for compatibility
- void FAR PASCAL TBInputStruct(PTBSTATE ptb, LPTBBUTTON pButtonInt, LPTBBUTTON pButtonExt)
- {
- if (ptb->uStructSize >= sizeof(TBBUTTON))
- {
- *pButtonInt = *pButtonExt;
- }
- else
- /* It is assumed the only other possibility is the OLDBUTTON struct */
- {
- *(LPOLDTBBUTTON)pButtonInt = *(LPOLDTBBUTTON)pButtonExt;
- /* We don't care about dwData */
- pButtonInt->dwData = 0;
- pButtonInt->iString = -1;
- }
- }
- void NEAR PASCAL TBOutputStruct(PTBSTATE ptb, LPTBBUTTON pButtonInt, LPTBBUTTON pButtonExt)
- {
- if (ptb->uStructSize >= sizeof(TBBUTTON))
- {
- LPBYTE pOut;
- int i;
- /* Fill the part we know about and fill the rest with 0's
- */
- *pButtonExt = *pButtonInt;
- for (i = ptb->uStructSize - sizeof(TBBUTTON), pOut = (LPBYTE)(pButtonExt + 1);
- i > 0; --i, ++pOut)
- {
- *pOut = 0;
- }
- }
- else
- /* It is assumed the only other possibility is the OLDBUTTON struct */
- {
- *(LPOLDTBBUTTON)pButtonExt = *(LPOLDTBBUTTON)pButtonInt;
- }
- }
- void NEAR PASCAL TBOnButtonStructSize(PTBSTATE ptb, UINT uStructSize)
- {
- /* You are not allowed to change this after adding buttons.
- */
- if (ptb && !ptb->iNumButtons)
- {
- ptb->uStructSize = uStructSize;
- }
- }
- void TBAutoSize(PTBSTATE ptb)
- {
- if (ptb)
- {
- HWND hwndParent;
- RECT rc;
- hwndParent = GetParent(ptb->ci.hwnd);
- if (!hwndParent)
- return;
- if (ptb->ci.style & TBSTYLE_WRAPABLE)
- {
- RECT rcNew;
- if ((ptb->ci.style & CCS_NORESIZE) || (ptb->ci.style & CCS_NOPARENTALIGN)) {
- GetWindowRect(ptb->ci.hwnd, &rc);
- } else {
- GetWindowRect(hwndParent, &rc);
- }
- WrapToolbar(ptb, rc.right - rc.left, &rcNew, NULL);
- FlushToolTipsMgr(ptb);
- }
- GetWindowRect(ptb->ci.hwnd, &rc);
- MapWindowPoints(HWND_DESKTOP, hwndParent, (LPPOINT)&rc, 2);
- NewSize(ptb->ci.hwnd, ptb->iButHeight * CountRows(ptb) + g_cxEdge * 2, ptb->ci.style,
- rc.left, rc.top, rc.right, rc.bottom);
- }
- }
- void TBSetStyle(PTBSTATE ptb, DWORD dwStyle)
- {
- if (ptb)
- {
- BOOL fSizeChanged = FALSE;
- if ((BOOL)(ptb->ci.style & TBSTYLE_WRAPABLE) != (BOOL)(dwStyle & TBSTYLE_WRAPABLE))
- {
- int i;
- fSizeChanged = TRUE;
- for (i=0; i<ptb->iNumButtons; i++)
- ptb->Buttons[i].fsState &= ~TBSTATE_WRAP;
- }
- ptb->ci.style = dwStyle;
- if (fSizeChanged)
- TBRecalc(ptb);
- TBAutoSize(ptb);
- #ifndef WINNT
- DebugMsg(DM_TRACE, TEXT("toolbar window style changed %x"), ptb->ci.style);
- #endif
- }
- }
- LRESULT TB_OnSetImage(PTBSTATE ptb, PTBBUTTON ptbButton, int iImage)
- {
- if (!ptb->fHimlNative) {
- if (ptb->fHimlValid) {
- if (!ptb->himl ||
- iImage >= ImageList_GetImageCount(ptb->himl))
- return FALSE;
- } else {
- PTBBMINFO pTemp;
- int nBitmap;
- UINT nTot;
- // we're not natively himl and we've got some invalid
- // image state, so we need to count the bitmaps ourselvesa
- pTemp = ptb->pBitmaps;
- nTot = 0;
- for (nBitmap=0; nBitmap < ptb->nBitmaps; nBitmap++) {
- nTot += pTemp->nButtons;
- pTemp++;
- }
- if (iImage >= (int)nTot)
- return FALSE;
- }
- }
- ptbButton->iBitmap = iImage;
- InvalidateButton(ptb, ptbButton, FALSE);
- return TRUE;
- }
- void TB_OnDestroy(PTBSTATE ptb)
- {
- if (ptb)
- {
- HWND hwnd = ptb->ci.hwnd;
- int i;
- for (i = 0; i < ptb->iNumButtons; i++) {
- if (TBISSTRINGPTR(ptb->Buttons[i].iString))
- Str_Set((LPTSTR*)&ptb->Buttons[i].iString, NULL);
- }
- //
- // If the toolbar created tooltips, then destroy them.
- //
- if ((ptb->ci.style & TBSTYLE_TOOLTIPS) && IsWindow(ptb->hwndToolTips)) {
- DestroyWindow (ptb->hwndToolTips);
- ptb->hwndToolTips = NULL;
- }
- if (ptb->hDragProxy)
- DestroyDragProxy(ptb->hDragProxy);
- if (ptb->hbmMono)
- DeleteObject(ptb->hbmMono);
- ReleaseMonoDC(ptb);
- if (ptb->nStrings > 0)
- DestroyStrings(ptb);
- if (ptb->hfontIcon && ptb->fFontCreated)
- DeleteObject(ptb->hfontIcon);
- // only do this destroy if pBitmaps exists..
- // this is our signal that it was from an old style toolba
- // and we created it ourselves.
- if (ptb->pBitmaps && ptb->himl)
- ImageList_Destroy(ptb->himl);
- if (ptb->pBitmaps)
- LocalFree(ptb->pBitmaps);
- LocalFree((HLOCAL)ptb);
- SetWindowInt(hwnd, 0, 0);
- }
- TerminateDitherBrush();
- }
- void TB_OnSetState(PTBSTATE ptb, PTBBUTTON ptbButton, BYTE bState, int iPos)
- {
- BYTE fsState;
- fsState = bState ^ ptbButton->fsState;
- ptbButton->fsState = bState;
- if (fsState)
- {
- if (fsState & TBSTATE_HIDDEN)
- InvalidateRect(ptb->ci.hwnd, NULL, TRUE);
- else
- InvalidateButton(ptb, ptbButton, TRUE);
- MyNotifyWinEvent(EVENT_OBJECT_STATECHANGE, ptb->ci.hwnd, OBJID_CLIENT,
- iPos+1);
- }
- }
- void TB_OnSetCmdID(PTBSTATE ptb, PTBBUTTON ptbButton, UINT idCommand)
- {
- UINT uiOldID;
- uiOldID = ptbButton->idCommand;
- ptbButton->idCommand = idCommand;
- //
- // If the app was using tooltips, then
- // we need to update the command id there also.
- //
- if(ptb->hwndToolTips) {
- TOOLINFO ti;
- //
- // Query the old information
- //
- ti.cbSize = sizeof(ti);
- ti.hwnd = ptb->ci.hwnd;
- ti.uId = uiOldID;
- SendMessage(ptb->hwndToolTips, TTM_GETTOOLINFO, 0,
- (LPARAM)(LPTOOLINFO)&ti);
- //
- // Delete the old tool since we can't just
- // change the command id.
- //
- SendMessage(ptb->hwndToolTips, TTM_DELTOOL, 0,
- (LPARAM)(LPTOOLINFO)&ti);
- //
- // Add the new tool with the new command id.
- //
- ti.uId = idCommand;
- SendMessage(ptb->hwndToolTips, TTM_ADDTOOL, 0,
- (LPARAM)(LPTOOLINFO)&ti);
- }
- }
- LRESULT TB_OnSetButtonInfo(PTBSTATE ptb, int idBtn, LPTBBUTTONINFO ptbbi)
- {
- int iPos;
- if (ptbbi->cbSize != SIZEOF(TBBUTTONINFO))
- return 0;
- iPos = PositionFromID(ptb, idBtn);
- if (iPos != -1)
- {
- PTBBUTTON ptbButton;
- BOOL fInvalidate = FALSE;
- ptbButton = ptb->Buttons + iPos;
- if (ptbbi->dwMask & TBIF_STYLE) {
- ptbbi->fsStyle = ptbbi->fsStyle;
- fInvalidate = TRUE;
- }
- if (ptbbi->dwMask & TBIF_STATE) {
- TB_OnSetState(ptb, ptbButton, ptbbi->fsState, iPos);
- }
- if (ptbbi->dwMask & TBIF_IMAGE) {
- TB_OnSetImage(ptb, ptbButton, ptbbi->iImage);
- }
- if (ptbbi->dwMask & TBIF_TEXT) {
- ptb->fNoStringPool = TRUE;
- if (!TBISSTRINGPTR(ptbButton->iString)) {
- ptbButton->iString = 0;
- }
- Str_Set((LPTSTR*)&ptbButton->iString, ptbbi->pszText);
- fInvalidate = TRUE;
- }
- if (ptbbi->dwMask & TBIF_LPARAM) {
- ptbButton->dwData = ptbbi->lParam;
- }
- if (ptbbi->dwMask & TBIF_COMMAND) {
- TB_OnSetCmdID(ptb, ptbButton, ptbbi->idCommand);
- }
- if (fInvalidate)
- InvalidateButton(ptb, ptbButton, FALSE);
- return TRUE;
- }
- return FALSE;
- }
- LRESULT TB_OnGetButtonInfo(PTBSTATE ptb, int idBtn, LPTBBUTTONINFO ptbbi)
- {
- int iPos;
- if (ptbbi->cbSize != SIZEOF(TBBUTTONINFO))
- return 0;
- iPos = PositionFromID(ptb, idBtn);
- if (iPos != -1)
- {
- PTBBUTTON ptbButton;
- ptbButton = ptb->Buttons + iPos;
- if (ptbbi->dwMask & TBIF_STYLE) {
- ptbbi->fsStyle = ptbButton->fsStyle;
- }
- if (ptbbi->dwMask & TBIF_STATE) {
- ptbbi->fsState = ptbButton->fsState;
- }
- if (ptbbi->dwMask & TBIF_IMAGE) {
- ptbbi->iImage = ptbButton->iBitmap;
- }
- if (ptbbi->dwMask & TBIF_TEXT) {
- if (TBISSTRINGPTR(ptbButton->iString)) {
- lstrcpyn(ptbbi->pszText, (LPCTSTR)ptbButton->iString, ptbbi->cchText);
- }
- }
- if (ptbbi->dwMask & TBIF_LPARAM) {
- ptbbi->lParam = ptbButton->dwData;
- }
- if (ptbbi->dwMask & TBIF_COMMAND) {
- ptbbi->idCommand = ptbButton->idCommand;
- }
- return TRUE;
- }
- return FALSE;
- }
- #ifdef UNICODE
- LRESULT TB_OnSetButtonInfoA(PTBSTATE ptb, int idBtn, LPTBBUTTONINFOA ptbbiA)
- {
- TBBUTTONINFO tbbi = *(LPTBBUTTONINFO)ptbbiA;
- WCHAR szText[256];
- if (ptbbiA->dwMask & TBIF_TEXT) {
- tbbi.pszText = szText;
- tbbi.cchText = ARRAYSIZE(szText);
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR) ptbbiA->pszText, -1,
- szText, ARRAYSIZE(szText));
- }
- return TB_OnSetButtonInfo(ptb, idBtn, (LPTBBUTTONINFO)&tbbi);
- }
- LRESULT TB_OnGetButtonInfoA(PTBSTATE ptb, int idBtn, LPTBBUTTONINFOA ptbbiA)
- {
- PTBBUTTON ptbButton;
- int iPos;
- DWORD dwMask = ptbbiA->dwMask;
- ptbbiA->dwMask &= ~TBIF_TEXT;
- if (!TB_OnGetButtonInfo(ptb, idBtn, (LPTBBUTTONINFO)ptbbiA))
- return 0;
- iPos = PositionFromID(ptb, (int)ptbbiA->idCommand);
- ptbButton = ptb->Buttons + iPos;
- ptbbiA->dwMask = dwMask;
- if (ptbbiA->dwMask & TBIF_TEXT) {
- if (TBISSTRINGPTR(ptbButton->iString)) {
- WideCharToMultiByte (CP_ACP, 0, (LPCTSTR)ptbButton->iString,
- -1, ptbbiA->pszText , ptbbiA->cchText, NULL, NULL);
- } else {
- ptbbiA->pszText[0] = 0;
- }
- }
- return 1;
- }
- #endif
- LRESULT CALLBACK ToolbarWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
- {
- BOOL fSameButton;
- PTBBUTTON ptbButton;
- int iPos;
- DWORD dw;
- PTBSTATE ptb = (PTBSTATE)GetWindowInt(hwnd, 0);
- if (!ptb && wMsg > WM_USER)
- goto DoDefault;
- switch (wMsg) {
- case WM_NCCREATE:
- #define lpcs ((LPCREATESTRUCT)lParam)
- InitDitherBrush();
- InitGlobalColors();
- /* create the state data for this toolbar */
- ptb = (PTBSTATE)LocalAlloc(LPTR, sizeof(TBSTATE) - sizeof(TBBUTTON));
- if (!ptb)
- return 0; // WM_NCCREATE failure is 0
- // note, zero init memory from above
- CIInitialize(&ptb->ci, hwnd, lpcs);
- ptb->xFirstButton = s_xFirstButton;
- ptb->nCurHTButton = -1;
- Assert(ptb->uStructSize == 0);
- Assert(ptb->hfontIcon == NULL); // initialize to null.
- Assert(ptb->iButMinWidth == 0);
- Assert(ptb->iButMaxWidth == 0);
- ptb->nTextRows = 1;
- ptb->fActive = TRUE;
- // IE 3 passes in TBSTYLE_FLAT, but they really
- // wanted TBSTYLE_TRANSPARENT also.
- //
- if (ptb->ci.style & TBSTYLE_FLAT) {
- ptb->ci.style |= TBSTYLE_TRANSPARENT;
- }
- #ifdef DEBUG
- if (IsFlagSet(g_dwPrototype, PTF_FLATLOOK))
- {
- TraceMsg(TF_GENERAL, "Using flat look for toolbars.");
- ptb->ci.style |= TBSTYLE_FLAT;
- }
- #endif
- // Now Initialize the hfont we will use.
- TBChangeFont(ptb, 0, NULL);
- // grow the button size to the appropriate girth
- if (!SetBitmapSize(ptb, DEFAULTBITMAPX, DEFAULTBITMAPX))
- {
- LocalFree((HLOCAL)ptb);
- return 0; // WM_NCCREATE failure is 0
- }
- SetWindowInt(hwnd, 0, (int)ptb);
- if (!(ptb->ci.style & (CCS_TOP | CCS_NOMOVEY | CCS_BOTTOM)))
- {
- ptb->ci.style |= CCS_TOP;
- SetWindowLong(hwnd, GWL_STYLE, ptb->ci.style);
- }
- if (ptb->ci.style & TBSTYLE_TOOLTIPS)
- {
- TOOLINFO ti;
- // don't bother setting the rect because we'll do it below
- // in FlushToolTipsMgr;
- ti.cbSize = sizeof(ti);
- ti.uFlags = TTF_IDISHWND;
- ti.hwnd = hwnd;
- ti.uId = (UINT)hwnd;
- ti.lpszText = 0;
- ptb->hwndToolTips = CreateWindow(c_szSToolTipsClass, NULL,
- WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- hwnd, NULL, lpcs->hInstance, NULL);
- SendMessage(ptb->hwndToolTips, TTM_ADDTOOL, 0,
- (LPARAM)(LPTOOLINFO)&ti);
- }
- return TRUE;
- case WM_CREATE:
- if (ptb->ci.style & TBSTYLE_REGISTERDROP)
- {
- ptb->hDragProxy = CreateDragProxy(ptb->ci.hwnd, ToolbarDragCallback, TRUE);
- }
- goto DoDefault;
- case WM_DESTROY:
- TB_OnDestroy(ptb);
- break;
- case WM_SETFONT:
- if (ptb)
- TBSetFont(ptb, (HFONT)wParam, (BOOL)lParam);
- return TRUE;
- case WM_NCCALCSIZE:
- // let defwindowproc handle the standard borders etc...
- dw = DefWindowProc(hwnd, wMsg, wParam, lParam ) ;
- // add the extra edge at the top of the toolbar to seperate from the menu bar
- if (ptb && !(ptb->ci.style & CCS_NODIVIDER))
- {
- ((NCCALCSIZE_PARAMS FAR *)lParam)->rgrc[0].top += g_cyEdge;
- }
- return dw;
- case WM_NCHITTEST:
- return HTCLIENT;
- case WM_NCACTIVATE:
- if (ptb && (ptb->fActive != (BOOL)wParam)) {
- int iButton;
- PTBBUTTON pButton;
- ptb->fActive = (BOOL) wParam;
- for (iButton = 0; iButton < ptb->iNumButtons; iButton++) {
- pButton = &ptb->Buttons[iButton];
- InvalidateButton(ptb, pButton, FALSE);
- }
- }
- // fall through...
- case WM_NCPAINT:
- // old-style toolbars are forced to be without dividers above
- if (ptb && !(ptb->ci.style & CCS_NODIVIDER))
- {
- RECT rc;
- HDC hdc = GetWindowDC(hwnd);
- GetWindowRect(hwnd, &rc);
- MapWindowRect(NULL, hwnd, &rc); // screen -> client
- rc.bottom = -rc.top; // bottom of NC area
- rc.top = rc.bottom - g_cyEdge;
- DrawEdge(hdc, &rc, BDR_SUNKENOUTER, BF_TOP | BF_BOTTOM);
- ReleaseDC(hwnd, hdc);
- }
- goto DoDefault;
- case WM_PRINTCLIENT:
- case WM_PAINT:
- if (ptb)
- ToolbarPaint(ptb, (HDC)wParam);
- break;
- case WM_ERASEBKGND:
- if (ptb)
- TB_OnEraseBkgnd(ptb, (HDC) wParam);
- return(TRUE);
- case WM_SYSCOLORCHANGE:
- if (ptb)
- {
- TB_OnSysColorChange(ptb);
- if (ptb->hwndToolTips)
- SendMessage(ptb->hwndToolTips, wMsg, wParam, lParam);
- }
- break;
- case TB_GETROWS:
- if (ptb)
- return CountRows(ptb);
- break;
- case TB_SETROWS:
- if (ptb)
- {
- RECT rc;
- if (BoxIt(ptb, LOWORD(wParam), HIWORD(wParam), &rc))
- {
- FlushToolTipsMgr(ptb);
- SetWindowPos(hwnd, NULL, 0, 0, rc.right, rc.bottom,
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
- InvalidateRect(hwnd, NULL, TRUE);
- }
- if (lParam)
- *((RECT FAR *)lParam) = rc;
- }
- break;
- case WM_WINDOWPOSCHANGING:
- if (ptb && (ptb->ci.style & TBSTYLE_FLAT))
- {
- LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam;
- RECT rc;
- HWND hwndParent;
- if (!(lpwp->flags & SWP_NOMOVE) && (hwndParent = GetParent(hwnd)))
- {
- GetWindowRect(hwnd, &rc);
- MapWindowPoints(HWND_DESKTOP, hwndParent, (LPPOINT)&rc, 1);
- if ((rc.left != lpwp->x) || (rc.top != lpwp->y))
- lpwp->flags |= SWP_NOREDRAW;
- }
- }
- goto DoDefault;
- case WM_MOVE:
- // JJK TODO: This needs to be double buffered to get rid of the flicker
- if (ptb && (ptb->ci.style & TBSTYLE_FLAT))
- InvalidateRect(hwnd, NULL, TRUE);
- goto DoDefault;
- case TB_AUTOSIZE:
- case WM_SIZE:
- TBAutoSize(ptb);
- break;
- case WM_COMMAND:
- case WM_DRAWITEM:
- case WM_MEASUREITEM:
- case WM_VKEYTOITEM:
- case WM_CHARTOITEM:
- if (ptb)
- SendMessage(ptb->ci.hwndParent, wMsg, wParam, lParam);
- break;
- case WM_RBUTTONDBLCLK:
- if (ptb && !CCSendNotify(&ptb->ci, NM_RDBLCLK, NULL))
- goto DoDefault;
- break;
- case WM_RBUTTONUP:
- if (ptb) {
- NMTBRCLICK nm;
- HWND hwndParent = NULL;
- nm.uiIndex = TBHitTest(ptb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- if (nm.uiIndex >= 0)
- nm.uiCmd = ptb->Buttons[nm.uiIndex].idCommand;
- else
- nm.uiCmd = (UINT) -1;
- LPARAM_TO_POINT(lParam, nm.ptMouse);
- if (hwndParent = GetParent(hwnd))
- MapWindowPoints(hwndParent, HWND_DESKTOP, &nm.ptMouse, 1);
- if (!CCSendNotify(&ptb->ci, NM_RCLICK, (LPNMHDR )&nm))
- goto DoDefault;
- }
- break;
- case WM_LBUTTONDBLCLK:
- if (!ptb) {
- break;
- }
- iPos = TBHitTest(ptb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- if (iPos < 0 && (ptb->ci.style & CCS_ADJUSTABLE))
- {
- iPos = -1 - iPos;
- CustomizeTB(ptb, iPos);
- } else {
- goto HandleLButtonDown;
- }
- break;
- case WM_LBUTTONDOWN:
- if (!ptb) {
- break;
- }
- RelayToToolTips(ptb->hwndToolTips, hwnd, wMsg, wParam, lParam);
- iPos = TBHitTest(ptb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- if ((ptb->ci.style & CCS_ADJUSTABLE) &&
- (((wParam & MK_SHIFT) && !(ptb->ci.style & TBSTYLE_ALTDRAG)) ||
- ((GetKeyState(VK_MENU) & ~1) && (ptb->ci.style & TBSTYLE_ALTDRAG))))
- {
- MoveButton(ptb, iPos);
- }
- else {
- HandleLButtonDown:
- if (iPos >= 0 && iPos < ptb->iNumButtons)
- {
- // should this check for the size of the button struct?
- ptbButton = ptb->Buttons + iPos;
- if (ptbButton->fsStyle & TBSTYLE_DROPDOWN) {
- if (ptbButton->fsState & TBSTATE_ENABLED) {
- ptbButton->fsState ^= TBSTATE_PRESSED;
- InvalidateButton(ptb, ptbButton, TRUE);
- UpdateWindow(hwnd);
- MyNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd,
- OBJID_CLIENT, iPos+1);
- if (!SendItemNotify(ptb, ptbButton->idCommand, TBN_DROPDOWN)) {
- MSG msg;
- PeekMessage(&msg, ptb->ci.hwnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
- ptbButton->fsState ^= TBSTATE_PRESSED;
- InvalidateButton(ptb, ptbButton, TRUE);
- UpdateWindow(hwnd);
- MyNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd,
- OBJID_CLIENT, iPos+1);
- }
- }
- } else {
- ptb->pCaptureButton = ptbButton;
- SetCapture(hwnd);
- if (ptbButton->fsState & TBSTATE_ENABLED)
- {
- ptbButton->fsState |= TBSTATE_PRESSED;
- InvalidateButton(ptb, ptbButton, TRUE);
- UpdateWindow(hwnd); // imedeate feedback
- MyNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd,
- OBJID_CLIENT, iPos+1);
- }
- SendItemNotify(ptb, ptb->pCaptureButton->idCommand, TBN_BEGINDRAG);
- }
- }
- }
- break;
- case WM_MOUSELEAVE:
- if (ptb)
- {
- RECT rectButton;
- TRACKMOUSEEVENT tme;
- ASSERT(ptb->ci.style & TBSTYLE_FLAT);
- tme.cbSize = sizeof(TRACKMOUSEEVENT);
- tme.dwFlags = TME_CANCEL | TME_LEAVE;
- tme.hwndTrack = hwnd;
- TrackMouseEvent(&tme);
- ptb->fMouseTrack = FALSE;
- if (ptb->nCurHTButton != -1)
- if (GetItemRect(ptb, ptb->nCurHTButton, &rectButton) )
- InvalidateRect(hwnd, &rectButton, TRUE);
- ptb->nCurHTButton = -1;
- }
- break;
- case WM_MOUSEMOVE:
- if (ptb && ptb->fActive)
- {
- RECT rectButton;
- if ((ptb->ci.style & TBSTYLE_FLAT) )
- {
- iPos = TBHitTest(ptb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- if (!ptb->fMouseTrack)
- {
- TRACKMOUSEEVENT tme;
- tme.cbSize = sizeof(TRACKMOUSEEVENT);
- tme.dwFlags = TME_LEAVE;
- tme.hwndTrack = hwnd;
- ptb->fMouseTrack = TRUE;
- TrackMouseEvent(&tme);
- }
- if ((ptb->nCurHTButton != iPos) && (ptb->nCurHTButton != -1))
- {
- if (GetItemRect(ptb, ptb->nCurHTButton, &rectButton) )
- InvalidateRect(hwnd, &rectButton, TRUE);
- ptb->nCurHTButton = -1;
- }
- if ((iPos >= 0) && (ptb->nCurHTButton != iPos))
- {
- if ((ptb->Buttons[iPos].fsState & TBSTATE_ENABLED) )
- {
- ptb->nCurHTButton = iPos;
- if (GetItemRect(ptb, iPos, &rectButton) )
- InvalidateRect(hwnd, &rectButton, TRUE);
- }
- }
- }
- RelayToToolTips(ptb->hwndToolTips, hwnd, wMsg, wParam, lParam);
- // if the toolbar has lost the capture for some reason, stop
- if (ptb->pCaptureButton == NULL) {
- //DebugMsg(DM_TRACE, TEXT("Bail because pCaptureButton == NULL"));
- break;
- }
- if (hwnd != GetCapture())
- {
- //DebugMsg(DM_TRACE, TEXT("capture isn't us"));
- SendItemNotify(ptb, ptb->pCaptureButton->idCommand, TBN_ENDDRAG);
- // if the button is still pressed, unpress it.
- if (ptb->pCaptureButton->fsState & TBSTATE_PRESSED)
- SendMessage(hwnd, TB_PRESSBUTTON, ptb->pCaptureButton->idCommand, 0L);
- ptb->pCaptureButton = NULL;
- }
- else if (ptb->pCaptureButton->fsState & TBSTATE_ENABLED)
- {
- //DebugMsg(DM_TRACE, TEXT("capture IS us, and state is enabled"));
- iPos = TBHitTest(ptb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- fSameButton = (iPos >= 0 && ptb->pCaptureButton == ptb->Buttons + iPos);
- if (fSameButton == !(ptb->pCaptureButton->fsState & TBSTATE_PRESSED))
- {
- //DebugMsg(DM_TRACE, TEXT("capture IS us, and Button is different"));
- ptb->pCaptureButton->fsState ^= TBSTATE_PRESSED;
- InvalidateButton(ptb, ptb->pCaptureButton, TRUE);
- MyNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd,
- OBJID_CLIENT, (ptb->pCaptureButton - ptb->Buttons) + 1);
- }
- }
- }
- break;
- case WM_LBUTTONUP:
- if (!ptb) {
- break;
- }
- RelayToToolTips(ptb->hwndToolTips, hwnd, wMsg, wParam, lParam);
- if (ptb->pCaptureButton != NULL) {
- int idCommand = ptb->pCaptureButton->idCommand;
- ReleaseCapture();
- SendItemNotify(ptb, idCommand, TBN_ENDDRAG);
- iPos = TBHitTest(ptb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- if ((ptb->pCaptureButton->fsState & TBSTATE_ENABLED) && iPos >=0
- && (ptb->pCaptureButton == ptb->Buttons+iPos)) {
- ptb->pCaptureButton->fsState &= ~TBSTATE_PRESSED;
- if (ptb->pCaptureButton->fsStyle & TBSTYLE_CHECK) {
- if (ptb->pCaptureButton->fsStyle & TBSTYLE_GROUP) {
- // group buttons already checked can't be force
- // up by the user.
- if (ptb->pCaptureButton->fsState & TBSTATE_CHECKED) {
- ptb->pCaptureButton = NULL;
- break; // bail!
- }
- ptb->pCaptureButton->fsState |= TBSTATE_CHECKED;
- MakeGroupConsistant(ptb, idCommand);
- } else {
- ptb->pCaptureButton->fsState ^= TBSTATE_CHECKED; // toggle
- }
- }
- InvalidateButton(ptb, ptb->pCaptureButton, TRUE);
- ptb->pCaptureButton = NULL;
- MyNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_CLIENT,
- iPos+1);
- FORWARD_WM_COMMAND(ptb->ci.hwndParent, idCommand, hwnd, BN_CLICKED, SendMessage);
- }
- else {
- ptb->pCaptureButton = NULL;
- }
- }
- break;
- case WM_WININICHANGE:
- if (!ptb) {
- break;
- }
- InitGlobalMetrics(wParam);
- if (ptb->fFontCreated)
- TBChangeFont(ptb, wParam, NULL);
- if (ptb->hwndToolTips)
- SendMessage(ptb->hwndToolTips, wMsg, wParam, lParam);
- break;
- case WM_NOTIFYFORMAT:
- if (ptb)
- return CIHandleNotifyFormat(&ptb->ci, lParam);
- break;
- case WM_NOTIFY:
- #define lpNmhdr ((LPNMHDR)(lParam))
- if (ptb)
- {
- int i = PositionFromID(ptb, lpNmhdr->idFrom);
- BOOL fEllipsied = FALSE;
- //
- // We are just going to pass this on to the
- // real parent. Note that -1 is used as
- // the hwndFrom. This prevents SendNotifyEx
- // from updating the NMHDR structure.
- //
- LRESULT lres = SendNotifyEx(ptb->ci.hwndParent, (HWND) -1,
- lpNmhdr->code, lpNmhdr, ptb->ci.bUnicode);
- #define lpnmTT ((LPTOOLTIPTEXT) lParam)
- if (i != -1) {
- fEllipsied = (BOOL)(ptb->Buttons[i].fsState & TBSTATE_ELLIPSES);
- if ((lpNmhdr->code == TTN_NEEDTEXT) &&
- (!ptb->nTextRows || fEllipsied) &&
- lpnmTT->lpszText && !lpnmTT->lpszText[0])
- {
- LPCTSTR psz = TB_StrForButton(ptb, &ptb->Buttons[i]);
- if (psz)
- lpnmTT->lpszText = (LPTSTR)psz;
- }
- }
- return(lres);
- }
- break;
- case WM_STYLECHANGING:
- if (!ptb)
- break;
- if (wParam == GWL_STYLE)
- {
- LPSTYLESTRUCT lpStyle = (LPSTYLESTRUCT) lParam;
- if ((lpStyle->styleOld ^ lpStyle->styleNew) == WS_VISIBLE)
- // MFC can't hide a window to save their lives -- and they
- // think that flipping bits directly will actually give them
- // something -- don't let 'em yank the visible bit directly
- // ... morons ... jeffbog 9/13/96
- lpStyle->styleNew |= WS_VISIBLE;
- }
- break;
- case WM_STYLECHANGED:
- if (wParam == GWL_STYLE)
- {
- TBSetStyle(ptb, ((LPSTYLESTRUCT)lParam)->styleNew);
- }
- return 0;
- case TB_SETSTYLE:
- TBSetStyle(ptb, lParam);
- break;
- case TB_GETSTYLE:
- return (ptb->ci.style);
- case TB_GETBUTTONSIZE:
- return (MAKELONG(ptb->iButWidth,ptb->iButHeight));
- case TB_SETBUTTONWIDTH:
- ptb->iButMinWidth = LOWORD(lParam);
- ptb->iButMaxWidth = HIWORD(lParam);
- ptb->iButWidth = 0;
- TBRecalc(ptb);
- return TRUE;
- case TB_SETSTATE:
- iPos = PositionFromID(ptb, (int)wParam);
- if (iPos < 0)
- return FALSE;
- ptbButton = ptb->Buttons + iPos;
- TB_OnSetState(ptb, ptbButton, (BYTE)(LOWORD(lParam)), iPos);
- return TRUE;
- // set the cmd ID of a button based on its position
- case TB_SETCMDID:
- if (wParam >= (UINT)ptb->iNumButtons)
- return FALSE;
- TB_OnSetCmdID(ptb, &ptb->Buttons[wParam], (UINT)lParam);
- return TRUE;
- case TB_GETSTATE:
- iPos = PositionFromID(ptb, (int)wParam);
- if (iPos < 0)
- return -1L;
- return ptb->Buttons[iPos].fsState;
- case TB_ENABLEBUTTON:
- case TB_CHECKBUTTON:
- case TB_PRESSBUTTON:
- case TB_HIDEBUTTON:
- case TB_INDETERMINATE:
- case TB_HIGHLIGHTBUTTON:
- {
- BYTE fsState;
- iPos = PositionFromID(ptb, (int)wParam);
- if (iPos < 0)
- return FALSE;
- ptbButton = &ptb->Buttons[iPos];
- fsState = ptbButton->fsState;
- if (LOWORD(lParam))
- ptbButton->fsState |= wStateMasks[wMsg - TB_ENABLEBUTTON];
- else
- ptbButton->fsState &= ~wStateMasks[wMsg - TB_ENABLEBUTTON];
- // did this actually change the state?
- if (fsState != ptbButton->fsState) {
- // is this button a member of a group?
- if ((wMsg == TB_CHECKBUTTON) && (ptbButton->fsStyle & TBSTYLE_GROUP))
- MakeGroupConsistant(ptb, (int)wParam);
- if (wMsg == TB_HIDEBUTTON) {
- InvalidateRect(hwnd, NULL, TRUE);
- FlushToolTipsMgr(ptb);
- } else
- InvalidateButton(ptb, ptbButton, TRUE);
- MyNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_CLIENT, iPos+1);
- }
- return(TRUE);
- }
- case TB_ISBUTTONENABLED:
- case TB_ISBUTTONCHECKED:
- case TB_ISBUTTONPRESSED:
- case TB_ISBUTTONHIDDEN:
- case TB_ISBUTTONINDETERMINATE:
- case TB_ISBUTTONHIGHLIGHTED:
- iPos = PositionFromID(ptb, (int)wParam);
- if (iPos < 0)
- return(-1L);
- return (LRESULT)ptb->Buttons[iPos].fsState & wStateMasks[wMsg - TB_ISBUTTONENABLED];
- case TB_ADDBITMAP:
- #ifdef WIN32
- case TB_ADDBITMAP32: // only for compatibility with mail
- #define pab ((LPTBADDBITMAP)lParam)
- return AddBitmap(ptb, wParam, pab->hInst, pab->nID);
- #undef pab
- #else
- return AddBitmap(ptb, wParam, (HINSTANCE)LOWORD(lParam), HIWORD(lParam));
- #endif
- case TB_REPLACEBITMAP:
- return ReplaceBitmap(ptb, (LPTBREPLACEBITMAP)lParam);
- #ifdef UNICODE
- case TB_ADDSTRINGA:
- {
- LPWSTR lpStrings;
- UINT uiCount;
- LPSTR lpAnsiString = (LPSTR) lParam;
- int iResult;
- BOOL bAllocatedMem = FALSE;
- if (!wParam && lpAnsiString) {
- //
- // We have to figure out how many characters
- // are in this string.
- //
- uiCount = 0;
- while (uiCount < MAXSTRINGSIZE) {
- uiCount++;
- if ((*lpAnsiString == 0) && (*(lpAnsiString+1) == 0)) {
- uiCount++; // needed for double null
- break;
- }
- lpAnsiString++;
- }
- lpStrings = GlobalAlloc (GPTR, uiCount * sizeof(TCHAR));
- if (!lpStrings)
- return -1;
- bAllocatedMem = TRUE;
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR) lParam, uiCount,
- lpStrings, uiCount);
- } else {
- lpStrings = (LPWSTR)lParam;
- }
- iResult = AddStrings(ptb, wParam, (LPARAM)lpStrings);
- if (bAllocatedMem)
- GlobalFree(lpStrings);
- return iResult;
- }
- #endif
- case TB_ADDSTRING:
- return AddStrings(ptb, wParam, lParam);
- #ifdef UNICODE
- case TB_ADDBUTTONSA:
- return InsertButtons(ptb, (UINT)-1, wParam, (LPTBBUTTON)lParam, FALSE);
- case TB_INSERTBUTTONA:
- return InsertButtons(ptb, wParam, 1, (LPTBBUTTON)lParam, FALSE);
- #endif
- case TB_ADDBUTTONS:
- return InsertButtons(ptb, (UINT)-1, wParam, (LPTBBUTTON)lParam, TRUE);
- case TB_INSERTBUTTON:
- return InsertButtons(ptb, wParam, 1, (LPTBBUTTON)lParam, TRUE);
- case TB_DELETEBUTTON:
- return DeleteButton(ptb, wParam);
- case TB_GETBUTTON:
- if (wParam >= (UINT)ptb->iNumButtons)
- return(FALSE);
- TBOutputStruct(ptb, ptb->Buttons + wParam, (LPTBBUTTON)lParam);
- return TRUE;
- case TB_BUTTONCOUNT:
- return ptb->iNumButtons;
- case TB_COMMANDTOINDEX:
- return PositionFromID(ptb, (int)wParam);
- #ifdef UNICODE
- case TB_SAVERESTOREA:
- {
- LPWSTR lpSubKeyW, lpValueNameW;
- TBSAVEPARAMSA * lpSaveA = (TBSAVEPARAMSA *) lParam;
- BOOL bResult;
- lpSubKeyW = ProduceWFromA (CP_ACP, lpSaveA->pszSubKey);
- lpValueNameW = ProduceWFromA (CP_ACP, lpSaveA->pszValueName);
- bResult = SaveRestoreFromReg(ptb, wParam, lpSaveA->hkr, lpSubKeyW, lpValueNameW);
- FreeProducedString(lpSubKeyW);
- FreeProducedString(lpValueNameW);
- return bResult;
- }
- #endif
- case TB_SAVERESTORE:
- #ifdef WIN32
- #define psr ((TBSAVEPARAMS *)lParam)
- return SaveRestoreFromReg(ptb, wParam, psr->hkr, psr->pszSubKey, psr->pszValueName);
- #undef psr
- #else
- return SaveRestore(ptb, wParam, (LPTSTR FAR *)lParam);
- #endif
- case TB_CUSTOMIZE:
- CustomizeTB(ptb, ptb->iNumButtons);
- break;
- case TB_GETRECT:
- // PositionFromID() accepts NULL ptbs!
- wParam = PositionFromID(ptb, wParam);
- // fall through
- case TB_GETITEMRECT:
- if (!lParam)
- break;
- return GetItemRect(ptb, wParam, (LPRECT)lParam);
- case TB_BUTTONSTRUCTSIZE:
- TBOnButtonStructSize(ptb, wParam);
- break;
- case TB_SETBUTTONSIZE:
- return GrowToolbar(ptb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), FALSE);
- case TB_SETBITMAPSIZE:
- return SetBitmapSize(ptb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- case TB_SETIMAGELIST:
- {
- HIMAGELIST himl = ptb->himl;
- int cx, cy;
- ptb->himl = (HIMAGELIST)lParam;
- ptb->fHimlNative = TRUE;
- // Update the bitmap size based on this image list
- ImageList_GetIconSize(ptb->himl, &cx, &cy);
- SetBitmapSize(ptb, cx, cy);
- return (LRESULT)himl;
- }
- case TB_GETIMAGELIST:
- return (LRESULT)ptb->himl;
- case TB_SETHOTIMAGELIST:
- {
- HIMAGELIST himl = ptb->himlHot;
- ptb->himlHot = (HIMAGELIST)lParam;
- return (LRESULT)himl;
- }
- case TB_GETHOTIMAGELIST:
- return (LRESULT)ptb->himlHot;
- case TB_GETDISABLEDIMAGELIST:
- return (LRESULT)ptb->himlDisabled;
- case TB_SETDISABLEDIMAGELIST:
- {
- HIMAGELIST himl = ptb->himlDisabled;
- ptb->himlDisabled = (HIMAGELIST)lParam;
- return (LRESULT)himl;
- }
- case TB_GETOBJECT:
- if (IsEqualIID((IID *)wParam, &IID_IDropTarget))
- {
- // if we have not already registered create an unregistered target now
- if (ptb->hDragProxy == NULL)
- ptb->hDragProxy = CreateDragProxy(ptb->ci.hwnd, ToolbarDragCallback, FALSE);
- if (ptb->hDragProxy)
- return (LRESULT)GetDragProxyTarget(ptb->hDragProxy, (IDropTarget **)lParam);
- }
- return E_FAIL;
- case WM_GETFONT:
- return (LRESULT)(UINT)(ptb? ptb->hfontIcon : 0);
- case TB_LOADIMAGES:
- return TBLoadImages(ptb, wParam, (HINSTANCE)lParam);
- case TB_GETTOOLTIPS:
- return (LRESULT)(UINT)ptb->hwndToolTips;
- case TB_SETTOOLTIPS:
- ptb->hwndToolTips = (HWND)wParam;
- break;
- case TB_SETPARENT:
- {
- HWND hwndOld = ptb->ci.hwndParent;
- ptb->ci.hwndParent = (HWND)wParam;
- return (LRESULT)(UINT)hwndOld;
- }
- #ifdef UNICODE
- case TB_GETBUTTONINFOA:
- return TB_OnGetButtonInfoA(ptb, (int)wParam, (LPTBBUTTONINFOA)lParam);
- case TB_SETBUTTONINFOA:
- return TB_OnSetButtonInfoA(ptb, (int)wParam, (LPTBBUTTONINFOA)lParam);
- #endif
- case TB_GETBUTTONINFO:
- return TB_OnGetButtonInfo(ptb, (int)wParam, (LPTBBUTTONINFO)lParam);
- case TB_SETBUTTONINFO:
- return TB_OnSetButtonInfo(ptb, (int)wParam, (LPTBBUTTONINFO)lParam);
- case TB_CHANGEBITMAP:
- iPos = PositionFromID(ptb, (int)wParam);
- if (iPos < 0)
- return(FALSE);
- //
- // Check to see if the new bitmap ID is
- // valid.
- //
- ptbButton = &ptb->Buttons[iPos];
- return TB_OnSetImage(ptb, ptbButton, LOWORD(lParam));
- case TB_GETBITMAP:
- iPos = PositionFromID(ptb, (int)wParam);
- if (iPos < 0)
- return(FALSE);
- ptbButton = &ptb->Buttons[iPos];
- return ptbButton->iBitmap;
- #ifdef UNICODE
- case TB_GETBUTTONTEXTA:
- iPos = PositionFromID(ptb, (int)wParam);
- if (iPos >= 0) {
- LPTSTR psz;
- ptbButton = &ptb->Buttons[iPos];
- psz = TB_StrForButton(ptb, ptbButton);
- if (psz) {
- if (lParam) {
- WideCharToMultiByte (CP_ACP, 0, psz,
- -1,(LPSTR)lParam , INT_MAX, NULL, NULL);
- }
- return lstrlen(psz);
- }
- }
- return -1;
- #endif
- case TB_GETBUTTONTEXT:
- iPos = PositionFromID(ptb, (int)wParam);
- if (iPos >= 0) {
- LPCTSTR psz;
- ptbButton = &ptb->Buttons[iPos];
- psz = TB_StrForButton(ptb, ptbButton);
- if (psz) {
- if (lParam) {
- lstrcpy((LPTSTR)lParam, psz);
- }
- return lstrlen(psz);
- }
- }
- return -1;
- #ifdef WIN32
- case TB_GETBITMAPFLAGS:
- {
- DWORD fFlags = 0;
- HDC hdc = GetDC(NULL);
- if (GetDeviceCaps(hdc, LOGPIXELSY) >= 120)
- fFlags |= TBBF_LARGE;
- ReleaseDC(NULL, hdc);
- return fFlags;
- }
- #endif
- case TB_SETINDENT:
- ptb->xFirstButton = wParam;
- InvalidateRect (hwnd, NULL, TRUE);
- FlushToolTipsMgr(ptb);
- return 1;
- case TB_SETMAXTEXTROWS:
- ptb->nTextRows = wParam;
- TBRecalc(ptb);
- return 1;
- case TB_GETTEXTROWS:
- return ptb->nTextRows;
- case TB_HITTEST:
- return TBHitTest(ptb, ((LPPOINT)lParam)->x, ((LPPOINT)lParam)->y);
- default:
- DoDefault:
- return DefWindowProc(hwnd, wMsg, wParam, lParam);
- }
- return 0L;
- }