root / trunk / win / Flatbar.cpp

Revision 654, 16.9 kB (checked in by leo, 2 years ago)

Added precompiled headers to all source files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1////////////////////////////////////////////////////////////////
2// CFlatToolBar 1997 Microsoft Systems Journal.
3// If this code works, it was written by Paul DiLascia.
4// If not, I don't know who wrote it.
5//
6#include "lc_global.h"
7#include "FlatBar.h"
8#include "BarCmdUI.h"
9#include "resource.h"
10#include <shlwapi.h>
11
12#ifdef _DEBUG
13#define new DEBUG_NEW
14#undef THIS_FILE
15static char THIS_FILE[] = __FILE__;
16#endif
17
18// Get version of COMCTL32.DLL installed
19static int GetComCtlVersion()
20{
21    DWORD dwMajor, dwMinor;
22    HINSTANCE hComCtl = LoadLibrary(TEXT("comctl32.dll"));
23    if(hComCtl)
24    {
25        HRESULT hr = S_OK;
26        DLLGETVERSIONPROC pDllGetVersion;
27
28        pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hComCtl, TEXT("DllGetVersion"));
29        if(pDllGetVersion)
30        {
31            DLLVERSIONINFO dvi;
32            ZeroMemory(&dvi, sizeof(dvi));
33            dvi.cbSize = sizeof(dvi);
34            hr = (*pDllGetVersion)(&dvi);
35            if(SUCCEEDED(hr))
36            {
37                dwMajor = dvi.dwMajorVersion;
38                dwMinor = dvi.dwMinorVersion;
39            }
40            else
41            {
42                hr = E_FAIL;
43            }
44        }
45        else
46        {
47            dwMajor = 4;
48            dwMinor = 0;
49        }
50        FreeLibrary(hComCtl);
51        return dwMajor*100 + dwMinor;
52    }
53    return 0;
54}
55
56////////////////////////////////////////////////////////////////
57// CFlatToolBar--does flat tool bar in MFC.
58//
59IMPLEMENT_DYNAMIC(CFlatToolBar, CToolBar)
60
61BEGIN_MESSAGE_MAP(CFlatToolBar, CToolBar)
62    //{{AFX_MSG_MAP(CFlatToolBar)
63    ON_WM_WINDOWPOSCHANGING()
64    ON_WM_WINDOWPOSCHANGED()
65    ON_WM_NCCALCSIZE()
66    ON_WM_NCPAINT()
67    ON_WM_PAINT()
68    ON_WM_RBUTTONDOWN()
69    //}}AFX_MSG_MAP
70END_MESSAGE_MAP()
71
72int CFlatToolBar::iVerComCtl32 = GetComCtlVersion();
73
74////////////////
75// Load override modifies the style after loading toolbar.
76//
77BOOL CFlatToolBar::LoadToolBar(LPCTSTR lpszResourceName)
78{
79    if (!CToolBar::LoadToolBar(lpszResourceName))
80        return FALSE;
81    ModifyStyle(0, TBSTYLE_FLAT); // make it flat
82    return TRUE;
83}
84
85//////////////////
86// MFC doesn't handle moving a TBSTYLE_FLAT toolbar correctly.
87// The simplest way to fix it is to repaint the old rectangle and
88// toolbar itself whenever the toolbar moves.
89//
90void CFlatToolBar::OnWindowPosChanging(LPWINDOWPOS lpwp)
91{
92    CToolBar::OnWindowPosChanging(lpwp);
93
94    if (!(lpwp->flags & SWP_NOMOVE)) {  // if moved:
95        CRect rc;                       // Fill rectangle with..
96        GetWindowRect(&rc);             // ..my (toolbar) rectangle.
97        CWnd* pParent = GetParent();    // get parent (dock bar/frame) win..
98        pParent->ScreenToClient(&rc);   // .. and convert to parent coords
99
100        // Ask parent window to paint the area beneath my old location.
101        // Typically, this is just solid grey. The area won't get painted until
102        // I send WM_NCPAINT after the move, in OnWindowPosChanged below.
103        pParent->InvalidateRect(&rc);        // paint old rectangle
104    }
105}
106
107//////////////////
108// Now toolbar has moved: repaint old area
109//
110void CFlatToolBar::OnWindowPosChanged(LPWINDOWPOS lpwp)
111{
112    CToolBar::OnWindowPosChanged(lpwp);
113
114#ifndef ILLUSTRATE_DISPLAY_BUG
115    if (!(lpwp->flags & SWP_NOMOVE)) {   // if moved:
116        // Now paint my non-client area at the new location.
117        // This is the extra bit of border space surrounding the buttons.
118        // Without this, you will still have a partial display bug (try it!)
119        //
120        SendMessage(WM_NCPAINT);
121    }
122#endif
123}
124
125//////////////////
126// This function is mostly copied from CToolBar/BARTOOL.CPP. The only thing
127// that's different is I instantiated a CFlatOrCoolBarCmdUI instead of
128// CToolCmdUI.
129//
130void CFlatToolBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
131{
132    // We don't need this.
133    return;
134
135    CFlatOrCoolBarCmdUI state; // <<<< This is the only line that's different--PD
136    state.m_pOther = this;
137
138    state.m_nIndexMax = (UINT)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
139    for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; state.m_nIndex++)
140    {
141        // get button state
142        TBBUTTON button;
143        VERIFY(DefWindowProc(TB_GETBUTTON, state.m_nIndex, (LPARAM)&button));
144        // TBSTATE_ENABLED == TBBS_DISABLED so invert it
145        button.fsState ^= TBSTATE_ENABLED;
146
147        state.m_nID = button.idCommand;
148
149        // ignore separators
150        if (!(button.fsStyle & TBSTYLE_SEP))
151        {
152            // allow the toolbar itself to have update handlers
153            if (CWnd::OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL))
154                continue;
155
156            // allow the owner to process the update
157            state.DoUpdate(pTarget, bDisableIfNoHndler);
158        }
159    }
160
161    // update the dialog controls added to the toolbar
162    UpdateDialogControls(pTarget, bDisableIfNoHndler);
163}
164
165//////////////////
166// **PD**
167// This is the all-important function that gets the true size of a button,
168// instead of using m_sizeButton. And it's virtual, so you can override if
169// my algorithm doesn't work, as will surely be the case in some circumstances.
170//
171CSize CFlatToolBar::GetButtonSize(TBBUTTON* pData, int iButton)
172{
173    // Get the actual size of the button, not what's in m_sizeButton.
174    // Make sure to do SendMessage instead of calling MFC's GetItemRect,
175    // which has all sorts of bad side-effects! (Go ahead, take a look at it.)
176    //
177    CRect rc;
178    SendMessage(TB_GETITEMRECT, iButton, (LPARAM)&rc);
179    CSize sz = rc.Size();
180
181    ////////////////
182    // Now must do special case for various versions of comctl32.dll,
183    //
184    DWORD dwStyle = pData[iButton].fsStyle;
185    if ((pData[iButton].fsState & TBSTATE_WRAP)) {
186        if (dwStyle & TBSTYLE_SEP) {
187            // this is the last separator in the row (eg vertically docked)
188            // fudge the height, and ignore the width. TB_GETITEMRECT will return
189            // size = (8 x 22) even for a separator in vertical toolbar
190            //
191            if (iVerComCtl32 <= 470)
192                sz.cy -= 3;     // empircally good fudge factor
193            else if (iVerComCtl32 != 471)
194                sz.cy = sz.cx;
195            sz.cx = 0;          // separator takes no width if it's the last one
196
197        }
198//      else if (dwStyle & TBSTYLE_DROPDOWN &&
199//          !m_bShowDropdownArrowWhenVertical) {
200            // ignore width of dropdown
201//          sz.cx = 0;
202//      }
203    }
204    return sz;
205}
206
207////////////////////////////////////////////////////////////////
208// ******* Stuff below is copied from MFC; my mods marked **PD**
209
210#ifdef _MAC
211    #define CX_OVERLAP  1
212#else
213    #define CX_OVERLAP  0
214#endif
215
216CSize CFlatToolBar::CalcSize(TBBUTTON* pData, int nCount)
217{
218    ASSERT(pData != NULL && nCount > 0);
219
220    CPoint cur(0,0);
221    CSize sizeResult(0,0);
222    int cyTallestOnRow = 0;
223
224    for (int i = 0; i < nCount; i++)
225    {
226        if (pData[i].fsState & TBSTATE_HIDDEN)
227            continue;
228
229        // **PD** Load actual size of button into local var
230        // that obscures CToolBar::m_sizeButton.
231        CSize m_sizeButton = GetButtonSize(pData, i);
232
233        // **PD** I also changed the logic below to be more correct.
234        cyTallestOnRow = max(cyTallestOnRow, m_sizeButton.cy);
235        sizeResult.cx = max(cur.x + m_sizeButton.cx, sizeResult.cx);
236        sizeResult.cy = max(cur.y + m_sizeButton.cy, sizeResult.cy);
237
238        cur.x += m_sizeButton.cx - CX_OVERLAP;
239
240        if (pData[i].fsState & TBSTATE_WRAP)
241        {
242            cur.x = 0;
243            cur.y += cyTallestOnRow;
244            cyTallestOnRow = 0;
245            if (pData[i].fsStyle & TBSTYLE_SEP)
246                cur.y += m_sizeButton.cy;
247        }
248    }
249    return sizeResult;
250}
251
252int CFlatToolBar::WrapToolBar(TBBUTTON* pData, int nCount, int nWidth)
253{
254    ASSERT(pData != NULL && nCount > 0);
255
256    int nResult = 0;
257    int x = 0;
258    for (int i = 0; i < nCount; i++)
259    {
260        pData[i].fsState &= ~TBSTATE_WRAP;
261
262        if (pData[i].fsState & TBSTATE_HIDDEN)
263            continue;
264
265        int dx, dxNext;
266
267        // **PD** Load actual size of button into local var
268        // that obscures CToolBar::m_sizeButton.
269        CSize m_sizeButton = GetButtonSize(pData, i);
270
271        dx = m_sizeButton.cx;
272        dxNext = dx - CX_OVERLAP;
273
274        if (x + dx > nWidth)
275        {
276            BOOL bFound = FALSE;
277            for (int j = i; j >= 0  &&  !(pData[j].fsState & TBSTATE_WRAP); j--)
278            {
279                // Find last separator that isn't hidden
280                // a separator that has a command ID is not
281                // a separator, but a custom control.
282                if ((pData[j].fsStyle & TBSTYLE_SEP) &&
283                    (pData[j].idCommand == 0) &&
284                    !(pData[j].fsState & TBSTATE_HIDDEN))
285                {
286                    bFound = TRUE; i = j; x = 0;
287                    pData[j].fsState |= TBSTATE_WRAP;
288                    nResult++;
289                    break;
290                }
291            }
292            if (!bFound)
293            {
294                for (int j = i - 1; j >= 0 && !(pData[j].fsState & TBSTATE_WRAP); j--)
295                {
296                    // Never wrap anything that is hidden,
297                    // or any custom controls
298                    if ((pData[j].fsState & TBSTATE_HIDDEN) ||
299                        ((pData[j].fsStyle & TBSTYLE_SEP) &&
300                        (pData[j].idCommand != 0)))
301                        continue;
302
303                    bFound = TRUE; i = j; x = 0;
304                    pData[j].fsState |= TBSTATE_WRAP;
305                    nResult++;
306                    break;
307                }
308                if (!bFound)
309                    x += dxNext;
310            }
311        }
312        else
313            x += dxNext;
314    }
315    return nResult + 1;
316}
317
318//////////////////////////////////////////////////////////////////////////
319// **PD**
320// Functions below are NOT modified. They're only here because they
321// call the modified functions above, which are NOT virtual.
322//////////////////////////////////////////////////////////////////////////
323
324void  CFlatToolBar::SizeToolBar(TBBUTTON* pData, int nCount, int nLength, BOOL bVert)
325{
326    ASSERT(pData != NULL && nCount > 0);
327
328    if (!bVert)
329    {
330        int nMin, nMax, nTarget, nCurrent, nMid;
331
332        // Wrap ToolBar as specified
333        nMax = nLength;
334        nTarget = WrapToolBar(pData, nCount, nMax);
335
336        // Wrap ToolBar vertically
337        nMin = 0;
338        nCurrent = WrapToolBar(pData, nCount, nMin);
339
340        if (nCurrent != nTarget)
341        {
342            while (nMin < nMax)
343            {
344                nMid = (nMin + nMax) / 2;
345                nCurrent = WrapToolBar(pData, nCount, nMid);
346
347                if (nCurrent == nTarget)
348                    nMax = nMid;
349                else
350                {
351                    if (nMin == nMid)
352                    {
353                        WrapToolBar(pData, nCount, nMax);
354                        break;
355                    }
356                    nMin = nMid;
357                }
358            }
359        }
360        CSize size = CalcSize(pData, nCount);
361        WrapToolBar(pData, nCount, size.cx);
362    }
363    else
364    {
365        CSize sizeMax, sizeMin, sizeMid;
366
367        // Wrap ToolBar vertically
368        WrapToolBar(pData, nCount, 0);
369        sizeMin = CalcSize(pData, nCount);
370
371        // Wrap ToolBar horizontally
372        WrapToolBar(pData, nCount, 32767);
373        sizeMax = CalcSize(pData, nCount);
374
375        while (sizeMin.cx < sizeMax.cx)
376        {
377            sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
378            WrapToolBar(pData, nCount, sizeMid.cx);
379            sizeMid = CalcSize(pData, nCount);
380
381            if (nLength < sizeMid.cy)
382            {
383                if (sizeMin == sizeMid)
384                {
385                    WrapToolBar(pData, nCount, sizeMax.cx);
386                    return;
387                }
388                sizeMin = sizeMid;
389            }
390            else if (nLength > sizeMid.cy)
391                sizeMax = sizeMid;
392            else
393                return;
394        }
395    }
396}
397
398typedef struct
399{
400    int nIndex, nID;
401    CRect rectOldPos;
402} _AFX_CONTROLPOS;
403
404CSize CFlatToolBar::CalcLayout(DWORD dwMode, int nLength)
405{
406    ASSERT_VALID(this);
407    ASSERT(::IsWindow(m_hWnd));
408    if (dwMode & LM_HORZDOCK)
409        ASSERT(dwMode & LM_HORZ);
410
411    int nCount;
412    TBBUTTON* pData;
413    CSize sizeResult(0,0);
414
415    // Load Buttons
416    {
417        nCount = SendMessage(TB_BUTTONCOUNT, 0, 0);
418        if (nCount != 0)
419        {
420            int i;
421            pData = new TBBUTTON[nCount];
422            for (i = 0; i < nCount; i++)
423                GetButton(i, &pData[i]); // **PD** renamed from _GetButton
424        }
425    }
426
427    if (nCount > 0)
428    {
429        if (!(m_dwStyle & CBRS_SIZE_FIXED))
430        {
431            BOOL bDynamic = m_dwStyle & CBRS_SIZE_DYNAMIC;
432
433            if (bDynamic && (dwMode & LM_MRUWIDTH))
434                SizeToolBar(pData, nCount, m_nMRUWidth);
435            else if (bDynamic && (dwMode & LM_HORZDOCK))
436                SizeToolBar(pData, nCount, 32767);
437            else if (bDynamic && (dwMode & LM_VERTDOCK))
438                SizeToolBar(pData, nCount, 0);
439            else if (bDynamic && (nLength != -1))
440            {
441                CRect rect; rect.SetRectEmpty();
442                CalcInsideRect(rect, (dwMode & LM_HORZ));
443                BOOL bVert = (dwMode & LM_LENGTHY);
444                int nLen = nLength + (bVert ? rect.Height() : rect.Width());
445
446                SizeToolBar(pData, nCount, nLen, bVert);
447            }
448            else if (bDynamic && (m_dwStyle & CBRS_FLOATING))
449                SizeToolBar(pData, nCount, m_nMRUWidth);
450            else
451                SizeToolBar(pData, nCount, (dwMode & LM_HORZ) ? 32767 : 0);
452        }
453
454        sizeResult = CalcSize(pData, nCount);
455
456        if (dwMode & LM_COMMIT)
457        {
458            _AFX_CONTROLPOS* pControl = NULL;
459            int nControlCount = 0;
460            BOOL bIsDelayed = m_bDelayedButtonLayout;
461            m_bDelayedButtonLayout = FALSE;
462            int i;
463
464            for(i = 0; i < nCount; i++)
465                if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
466                    nControlCount++;
467
468            if (nControlCount > 0)
469            {
470                pControl = new _AFX_CONTROLPOS[nControlCount];
471                nControlCount = 0;
472
473                for(int i = 0; i < nCount; i++)
474                {
475                    if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
476                    {
477                        pControl[nControlCount].nIndex = i;
478                        pControl[nControlCount].nID = pData[i].idCommand;
479
480                        CRect rect;
481                        GetItemRect(i, &rect);
482                        ClientToScreen(&rect);
483                        pControl[nControlCount].rectOldPos = rect;
484
485                        nControlCount++;
486                    }
487                }
488            }
489
490            if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
491                m_nMRUWidth = sizeResult.cx;
492            for (i = 0; i < nCount; i++)
493                SetButton(i, &pData[i]); // **PD** renamed from _SetButton
494
495            if (nControlCount > 0)
496            {
497                for (int i = 0; i < nControlCount; i++)
498                {
499                    CWnd* pWnd = GetDlgItem(pControl[i].nID);
500                    if (pWnd != NULL)
501                    {
502                        CRect rect;
503                        pWnd->GetWindowRect(&rect);
504                        CPoint pt = rect.TopLeft() - pControl[i].rectOldPos.TopLeft();
505                        GetItemRect(pControl[i].nIndex, &rect);
506                        pt = rect.TopLeft() + pt;
507                        pWnd->SetWindowPos(NULL, pt.x, pt.y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
508                    }
509                }
510                delete[] pControl;
511            }
512            m_bDelayedButtonLayout = bIsDelayed;
513        }
514        delete[] pData;
515    }
516
517    //BLOCK: Adjust Margins
518    {
519        CRect rect; rect.SetRectEmpty();
520        CalcInsideRect(rect, (dwMode & LM_HORZ));
521        sizeResult.cy -= rect.Height();
522        sizeResult.cx -= rect.Width();
523
524        CSize size = CControlBar::CalcFixedLayout((dwMode & LM_STRETCH), (dwMode & LM_HORZ));
525        sizeResult.cx = max(sizeResult.cx, size.cx);
526        sizeResult.cy = max(sizeResult.cy, size.cy);
527    }
528    return sizeResult;
529}
530
531CSize CFlatToolBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
532{
533    DWORD dwMode = bStretch ? LM_STRETCH : 0;
534    dwMode |= bHorz ? LM_HORZ : 0;
535
536    return CalcLayout(dwMode);
537}
538
539CSize CFlatToolBar::CalcDynamicLayout(int nLength, DWORD dwMode)
540{
541    if ((nLength == -1) && !(dwMode & LM_MRUWIDTH) && !(dwMode & LM_COMMIT) &&
542        ((dwMode & LM_HORZDOCK) || (dwMode & LM_VERTDOCK)))
543    {
544        return CalcFixedLayout(dwMode & LM_STRETCH, dwMode & LM_HORZDOCK);
545    }
546    return CalcLayout(dwMode, nLength);
547}
548
549/////////////////////////////////////////////////////////////////////////////
550// CToolBar attribute access
551
552// **PD** I renamed this from _GetButton.
553//
554void CFlatToolBar::GetButton(int nIndex, TBBUTTON* pButton) const
555{
556    CToolBar* pBar = (CToolBar*)this;
557    VERIFY(pBar->SendMessage(TB_GETBUTTON, nIndex, (LPARAM)pButton));
558    // TBSTATE_ENABLED == TBBS_DISABLED so invert it
559    pButton->fsState ^= TBSTATE_ENABLED;
560}
561
562// **PD** I renamed this from _SetButton.
563//
564void CFlatToolBar::SetButton(int nIndex, TBBUTTON* pButton)
565{
566    // get original button state
567    TBBUTTON button;
568    VERIFY(SendMessage(TB_GETBUTTON, nIndex, (LPARAM)&button));
569
570    // prepare for old/new button comparsion
571    button.bReserved[0] = 0;
572    button.bReserved[1] = 0;
573    // TBSTATE_ENABLED == TBBS_DISABLED so invert it
574    pButton->fsState ^= TBSTATE_ENABLED;
575    pButton->bReserved[0] = 0;
576    pButton->bReserved[1] = 0;
577
578    // nothing to do if they are the same
579    if (memcmp(pButton, &button, sizeof(TBBUTTON)) != 0)
580    {
581        // don't redraw everything while setting the button
582        DWORD dwStyle = GetStyle();
583        ModifyStyle(WS_VISIBLE, 0);
584        VERIFY(SendMessage(TB_DELETEBUTTON, nIndex, 0));
585        VERIFY(SendMessage(TB_INSERTBUTTON, nIndex, (LPARAM)pButton));
586        ModifyStyle(0, dwStyle & WS_VISIBLE);
587
588        // invalidate appropriate parts
589        if (((pButton->fsStyle ^ button.fsStyle) & TBSTYLE_SEP) ||
590            ((pButton->fsStyle & TBSTYLE_SEP) && pButton->iBitmap != button.iBitmap))
591        {
592            // changing a separator
593            Invalidate(FALSE);
594        }
595        else
596        {
597            // invalidate just the button
598            CRect rect;
599            if (SendMessage(TB_GETITEMRECT, nIndex, (LPARAM)&rect))
600                InvalidateRect(rect, FALSE);    // don't erase background
601        }
602    }
603}
604
605void CFlatToolBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
606{
607    // adjust non-client area for gripper at left or top
608    if( m_dwStyle & CBRS_ORIENT_HORZ )
609    {
610        lpncsp->rgrc[0].left  += 4;
611        lpncsp->rgrc[0].right += 4;
612    }
613    else 
614    {
615        lpncsp->rgrc[0].top    += 6;
616        lpncsp->rgrc[0].bottom += 6;
617    }
618   
619    CToolBar::OnNcCalcSize(bCalcValidRects, lpncsp);
620}
621
622void CFlatToolBar::OnNcPaint()
623{
624    CControlBar::EraseNonClient();
625    CWindowDC dc(this);
626
627    // no gripper if floating
628    if (m_dwStyle & CBRS_FLOATING)
629        return;
630   
631    CRect gripper;
632    GetWindowRect (gripper);
633    ScreenToClient (gripper);
634    gripper.OffsetRect(-gripper.left, -gripper.top);
635   
636    if(m_dwStyle & CBRS_ORIENT_HORZ)
637    {
638        // gripper at left
639        gripper.DeflateRect(3, 3);
640        gripper.right = gripper.left+3;
641        dc.Draw3dRect (gripper, ::GetSysColor(COLOR_BTNHILIGHT),
642            ::GetSysColor(COLOR_BTNSHADOW));
643       
644        gripper.OffsetRect(3, 0);
645        dc.Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHILIGHT),
646            ::GetSysColor(COLOR_BTNSHADOW));
647    }
648    else 
649    {
650        // gripper at top
651        gripper.DeflateRect(4, 4);
652        gripper.bottom = gripper.top+3;
653        dc.Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHILIGHT),
654            ::GetSysColor(COLOR_BTNSHADOW));
655       
656        gripper.OffsetRect(0, 3);
657        dc.Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHILIGHT),
658            ::GetSysColor(COLOR_BTNSHADOW));
659    }
660   
661    CRect pRect;
662    GetClientRect (&pRect);
663    InvalidateRect (&pRect, TRUE);
664}
665
666void CFlatToolBar::OnRButtonDown(UINT nFlags, CPoint point)
667{
668    CMenu menuPopups;
669
670    if (GetCursorPos(&point) && menuPopups.LoadMenu(IDR_POPUPS))
671        menuPopups.GetSubMenu(4)->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,
672                point.x, point.y, AfxGetMainWnd());
673
674    CToolBar::OnRButtonDown(nFlags, point);
675}
Note: See TracBrowser for help on using the browser.