home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- // dropmenu.cpp
- // Implements a popup menu in which you can drag and drop
-
- #include "stdafx.h"
- #include "dropmenu.h"
- #include "cxicon.h"
-
- #define nIMG_SPACE 4
- #define MAX_DROPMENU_ITEM_LENGTH 45
-
-
- //////////////////////////////////////////////////////////////////////////
- // Class CDropMenuButton
- //////////////////////////////////////////////////////////////////////////
- CDropMenuButton::CDropMenuButton(void)
- {
-
- m_bButtonPressed = FALSE;
- m_bMenuShowing = FALSE;
- m_bFirstTime = FALSE;
- }
- //////////////////////////////////////////////////////////////////////////
- // Messages for CDropMenuButton
- //////////////////////////////////////////////////////////////////////////
-
- BEGIN_MESSAGE_MAP(CDropMenuButton, CStationaryToolbarButton)
- //{{AFX_MSG_MAP(CWnd)
- ON_WM_LBUTTONDOWN()
- ON_WM_LBUTTONUP()
- ON_WM_MOUSEMOVE()
- ON_MESSAGE(DM_MENUCLOSED, OnMenuClosed)
-
- //}}AFX_MSG_MAP
-
- END_MESSAGE_MAP()
-
- void CDropMenuButton::OnLButtonDown(UINT nFlags, CPoint point)
- {
- CStationaryToolbarButton::OnLButtonDown(nFlags, point);
-
- m_bButtonPressed = TRUE;
- }
-
- void CDropMenuButton::OnMouseMove(UINT nFlags, CPoint point)
- {
- if(m_bMenuShowing)
- {
- if(m_bFirstTime)
- {
- ReleaseCapture();
- m_eState = eBUTTON_DOWN;
- RedrawWindow();
- m_bFirstTime = FALSE;
- }
- }
- else
- {
- CStationaryToolbarButton::OnMouseMove(nFlags, point);
- }
- }
-
- void CDropMenuButton::OnLButtonUp(UINT nFlags, CPoint point)
- {
- if(m_bButtonPressed && m_bEnabled && m_bHaveFocus)
- {
- OnAction();
- m_bMenuShowing = TRUE;
- m_bFirstTime = TRUE;
- }
- else
- {
- CStationaryToolbarButton::OnLButtonUp(nFlags, point);
- m_bMenuShowing = FALSE;
- }
- m_bButtonPressed = FALSE;
- }
-
- LRESULT CDropMenuButton::OnMenuClosed(WPARAM wParam, LPARAM lParam)
- {
-
- m_bMenuShowing = FALSE;
- m_eState = eNORMAL;
- RedrawWindow();
-
- return 1;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Class CDropMenuItem
- //////////////////////////////////////////////////////////////////////////
-
- CDropMenuItem::CDropMenuItem(UINT nFlags, CString szText, UINT nCommandID,
- HBITMAP hUnselectedBitmap, HBITMAP hSelectedBitmap,
- BOOL bShowFeedback, void *pUserData)
- {
- m_nIconType = BUILTIN_BITMAP;
-
- if(nFlags & MF_SEPARATOR)
- {
- m_bIsSeparator = TRUE;
- }
- else if(nFlags == MF_STRING)
- {
- m_bIsSeparator = FALSE;
- char *pCutText = fe_MiddleCutString(szText.GetBuffer(szText.GetLength() + 1), MAX_DROPMENU_ITEM_LENGTH);
- m_szText = pCutText;
- szText.ReleaseBuffer();
- free(pCutText);
- m_hUnselectedBitmap = hUnselectedBitmap;
-
- m_hSelectedBitmap = (hSelectedBitmap == NULL) ? hUnselectedBitmap : hSelectedBitmap;
-
- m_nCommandID = nCommandID;
- m_pSubMenu = NULL;
- }
- m_bIsEmpty = TRUE;
- m_unselectedBitmapSize.cx = m_unselectedBitmapSize.cy = 0;
- m_selectedBitmapSize.cx = m_selectedBitmapSize.cy = 0;
- m_textSize.cx = m_textSize.cy = 0;
- m_totalSize.cx = m_totalSize.cy = 0;
- m_menuItemRect.SetRectEmpty();
- m_bShowFeedback = bShowFeedback;
- m_pUserData = pUserData;
-
- }
-
- CDropMenuItem::CDropMenuItem(UINT nFlags, CString szText, UINT nCommandID, CDropMenu *pSubMenu, BOOL bIsEmpty,
- HBITMAP hUnselectedBitmap, HBITMAP hSelectedBitmap, BOOL bShowFeedback, void *pUserData)
- {
- if(nFlags & MF_POPUP)
- {
- m_bIsSeparator = FALSE;
- char *pCutText = fe_MiddleCutString(szText.GetBuffer(szText.GetLength() + 1), MAX_DROPMENU_ITEM_LENGTH);
- m_szText = pCutText;
- szText.ReleaseBuffer();
-
- free(pCutText);
-
- m_hUnselectedBitmap = hUnselectedBitmap;
- m_hSelectedBitmap = (hSelectedBitmap == NULL) ? hUnselectedBitmap : hSelectedBitmap;
-
- m_nCommandID = nCommandID;
- m_pSubMenu = pSubMenu;
- }
- m_bIsEmpty = bIsEmpty;
- m_unselectedBitmapSize.cx = m_unselectedBitmapSize.cy = 0;
- m_selectedBitmapSize.cx = m_selectedBitmapSize.cy = 0;
- m_textSize.cx = m_textSize.cy = 0;
- m_totalSize.cx = m_totalSize.cy = 0;
- m_menuItemRect.SetRectEmpty();
- m_bShowFeedback = bShowFeedback;
- m_pUserData = pUserData;
- }
-
- CDropMenuItem::~CDropMenuItem()
- {
-
- if(IsSubMenu())
- {
- CDropMenu *pSubMenu = GetSubMenu();
- pSubMenu->DestroyDropMenu();
- delete pSubMenu;
- }
- }
- void CDropMenuItem::GetMenuItemRect(LPRECT rect)
- {
- rect->left = m_menuItemRect.left;
- rect->right = m_menuItemRect.right;
- rect->top = m_menuItemRect.top;
- rect->bottom = m_menuItemRect.bottom;
-
- }
-
- void CDropMenuItem::SetMenuItemRect(LPRECT rect)
- {
- m_menuItemRect.left = rect->left;
- m_menuItemRect.right = rect->right;
- m_menuItemRect.top = rect->top;
- m_menuItemRect.bottom = rect->bottom;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Class CDropMenuDropTarget
- ///////////////////////////////////////////////////////////////////////////
-
- CDropMenuDropTarget::CDropMenuDropTarget(CWnd *pOwner)
- {
- m_pOwner = pOwner;
-
- }
-
-
- DROPEFFECT CDropMenuDropTarget::OnDragEnter(CWnd * pWnd, COleDataObject * pDataObject,
- DWORD dwKeyState, CPoint point)
- {
- return OnDragOver(pWnd, pDataObject, dwKeyState, point);
-
- }
-
- DROPEFFECT CDropMenuDropTarget::OnDragOver(CWnd * pWnd, COleDataObject * pDataObject,
- DWORD dwKeyState, CPoint point )
- {
- CDropMenuDragData dragData(pDataObject, point);
- m_pOwner->SendMessage(DT_DRAGGINGOCCURRED, (WPARAM) 0, (LPARAM)(&dragData));
-
- return dragData.m_DropEffect;
- }
-
- BOOL CDropMenuDropTarget::OnDrop(CWnd * pWnd, COleDataObject * pDataObject,
- DROPEFFECT dropEffect, CPoint point)
- {
- CDropMenuDragData* dragData = new CDropMenuDragData(pDataObject, point);
- m_pOwner->SendMessage(DT_DROPOCCURRED, (WPARAM) 0, (LPARAM)(dragData));
-
- return TRUE;
- }
-
- // End CDropMenuDropTarget implementation
-
- // CDropMenuColumn
- CDropMenuColumn::CDropMenuColumn(int nFirstItem, int nLastItem, int nWidth, int nHeight)
- {
- m_nFirstItem = nFirstItem;
- m_nLastItem = nLastItem;
- m_nWidth = nWidth;
- m_nHeight = nHeight;
- m_bHasSubMenu = FALSE;
- }
-
-
- #define NOSELECTION -1
- #define MENU_BORDER_SIZE 3
-
- #define SUBMENU_WIDTH 9
- #define SUBMENU_HEIGHT 11
-
- #define SUBMENU_LEFT_MARGIN 3
- #define SUBMENU_RIGHT_MARGIN 7
-
- #define IDT_SUBMENU_OFF 16384
- #define SUBMENU_DELAY_OFF_MS 400
-
- #define IDT_SUBMENU_ON 16385
- #define SUBMENU_DELAY_ON_MS 400
-
- #define IDT_HAVE_FOCUS 16386
- #define HAVE_FOCUS_DELAY 400
-
- #define IDT_UNHOOK 16387
- #define UNHOOK_DELAY 100
-
- #define SEPARATOR_SPACE 2
- #define SEPARATOR_HEIGHT 2
- #define SEPARATOR_WIDTH 2
- #define SPACE_BETWEEN_ITEMS 2
-
- static HHOOK currentMouseHook;
- static HHOOK currentKeyboardHook;
- static CDropMenu * currentMenu = NULL; //This refers to a submenu of the current dropmenu
- static CDropMenu * gLastMenu = NULL; //This refers to the most recent complete dropmenu
- static LONG oldFrameProc;
- static UINT gUnhookTimer = 0;
-
- CDropMenu* CDropMenu::GetLastDropMenu()
- {
- return gLastMenu;
- }
-
- void CDropMenu::SetLastDropMenu(CDropMenu* menu)
- {
- gLastMenu = menu;
- }
-
- CDropMenu::CDropMenu()
- {
-
- m_pMenuItemArray.SetSize(0, 10);
-
- m_WidestImage = 0;
- m_WidestText = 0;
-
- m_nSelectedItem = -1;
- m_eSelectedItemSelType = eNONE;
- m_bShowing = FALSE;
- m_pDropTarget = NULL;
-
-
- m_pUnselectedItem = NULL;
- m_pSelectedItem = NULL;
-
- m_nSelectTimer = 0;
- m_nUnselectTimer = 0;
-
- m_pMenuParent = NULL;
- m_pShowingSubmenu = NULL;
-
- m_bDropOccurring = FALSE;
- m_bDragging = FALSE;
- m_bRight = TRUE;
- m_bMouseUsed = TRUE;
- m_bIsOpen = FALSE;
- m_pOverflowMenuItem = NULL;
- m_bAboutToShow = FALSE;
- m_pParentMenuItem = NULL;
- m_hSubmenuUnselectedBitmap = NULL;
- m_hSubmenuSelectedBitmap = NULL;
- m_pUserData = NULL;
- }
-
- CDropMenu::~CDropMenu()
- {
- // Clear out any dangling pointers.
- if(currentMenu == this) {
- currentMenu = NULL;
- }
- if(gLastMenu == this) {
- gLastMenu = NULL;
- }
-
- int nCount = m_pMenuItemArray.GetSize();
-
- for(int i = 0; i < nCount; i++)
- {
- CDropMenuItem *pItem = (CDropMenuItem *)m_pMenuItemArray[i];
- if(pItem != m_pOverflowMenuItem)
- delete pItem;
- }
-
- int nColumnCount = m_pColumnArray.GetSize();
-
- for(int j = 0 ; j < nColumnCount; j++)
- delete (CDropMenuColumn*)m_pColumnArray[j];
-
- if(m_pDropTarget)
- delete m_pDropTarget;
-
- if(m_pOverflowMenuItem != NULL)
- delete m_pOverflowMenuItem;
-
- m_pMenuItemArray.RemoveAll();
-
- if(m_pMenuParent == NULL)
- {
- if(m_hSubmenuSelectedBitmap != NULL)
- {
- ::DeleteObject(m_hSubmenuSelectedBitmap);
- m_hSubmenuSelectedBitmap = NULL;
- }
-
- if(m_hSubmenuUnselectedBitmap != NULL)
- {
- ::DeleteObject(m_hSubmenuUnselectedBitmap);
- m_hSubmenuUnselectedBitmap = NULL;
- }
- }
-
- if(m_pMenuParent != NULL && m_pMenuParent->m_pShowingSubmenu == this)
- m_pMenuParent->m_pShowingSubmenu = NULL;
-
- m_pMenuParent = NULL;
- m_bShowing = FALSE;
-
-
- }
-
- UINT CDropMenu::GetMenuItemCount(void)
- {
- return m_pMenuItemArray.GetSize();
- }
-
- void CDropMenu::AppendMenu(UINT nFlags, UINT nIDNewItem, CString szText, BOOL bShowFeedback,
- HBITMAP hUnselectedBitmap, HBITMAP hSelectedBitmap,
- void* icon, IconType iconType, void *pUserData)
- {
-
- CDropMenuItem *pMenuItem = new CDropMenuItem(nFlags, szText, nIDNewItem,
- hUnselectedBitmap, hSelectedBitmap, bShowFeedback, pUserData);
-
- pMenuItem->SetIcon(icon, iconType);
- m_pMenuItemArray.Add(pMenuItem);
- }
-
- void CDropMenu::AppendMenu(UINT nFlags, UINT nIDNewItem, CDropMenu *pSubMenu, BOOL bIsEmpty, CString szText,
- BOOL bShowFeedback, HBITMAP hUnselectedBitmap, HBITMAP hSelectedBitmap,
- void* icon, IconType iconType, void *pUserData)
- {
- CDropMenuItem *pMenuItem = new CDropMenuItem(nFlags, szText, nIDNewItem, pSubMenu, bIsEmpty,
- hUnselectedBitmap, hSelectedBitmap, bShowFeedback, pUserData);
- pMenuItem->SetIcon(icon, iconType);
- m_pMenuItemArray.Add(pMenuItem);
- }
-
- void CDropMenu::DeleteMenu(UINT nPosition, UINT nFlags)
- {
- CDropMenuItem *pItem;
-
- if(nFlags == MF_BYPOSITION)
- {
- UINT nCount = m_pMenuItemArray.GetSize();
-
- if(nPosition >= 0 && nPosition < nCount)
- {
- pItem = (CDropMenuItem *)m_pMenuItemArray[nPosition];
- m_pMenuItemArray.RemoveAt(nPosition, 1);
- }
- }
- else if(nFlags == MF_BYCOMMAND)
- {
- int nCommandPosition = FindCommand(nPosition);
- if(nCommandPosition != -1)
- {
- pItem = (CDropMenuItem *)m_pMenuItemArray[nCommandPosition];
- m_pMenuItemArray.RemoveAt(nCommandPosition, 1);
- }
- }
-
- if(pItem != m_pOverflowMenuItem)
- delete pItem;
-
- }
-
- void CDropMenu::CreateOverflowMenuItem(UINT nCommand, CString szText, HBITMAP hUnselectedBitmap, HBITMAP hSelectedBitmap)
- {
-
- m_pOverflowMenuItem = new CDropMenuItem(MF_STRING, szText, nCommand, hUnselectedBitmap,
- hSelectedBitmap, FALSE);
-
- }
-
- LRESULT CALLBACK EXPORT HandleMouseEvents(int nCode, WPARAM wParam, LPARAM lParam)
- {
- if(nCode < 0)
- return CallNextHookEx(currentMouseHook, nCode, wParam, lParam);
-
- MOUSEHOOKSTRUCT *mouseHook = (MOUSEHOOKSTRUCT*)lParam;
-
- if(currentMenu != NULL)
- {
- //only want to deactivate if point is not in our menu or in our parent or children
- if(nCode >= 0 && (wParam == WM_NCLBUTTONDOWN || wParam == WM_LBUTTONDOWN ||
- ((wParam == WM_LBUTTONUP || wParam == WM_NCLBUTTONUP) && currentMenu->IsDragging())))
- {
-
- if(currentMenu != NULL && !currentMenu->PointInMenus(mouseHook->pt))
- {
- currentMenu->Deactivate();
- }
- }
- }
- return CallNextHookEx(currentMouseHook, nCode, wParam, lParam);
-
- }
-
- LRESULT CALLBACK EXPORT HandleKeyboardEvents(int nCode, WPARAM wParam, LPARAM lParam)
- {
-
- if(nCode < 0)
- {
- return CallNextHookEx(currentKeyboardHook, nCode, wParam, lParam);
- }
-
- //only want to handle on a keydown
- if(!(HIWORD(lParam) & KF_UP) && currentMenu != NULL)
- {
- currentMenu->HandleKeystroke(wParam);
- }
-
- //we don't want to pass the keyboard event onwards
- return 1;
- }
-
- LRESULT CALLBACK EXPORT FrameProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- if(uMsg == WM_ACTIVATE)
- {
- if(LOWORD(wParam) == WA_INACTIVE && !currentMenu->IsShowingMenu((HWND)lParam))
- {
- currentMenu->Deactivate();
- }
-
- }
-
- return CallWindowProc((WNDPROC)oldFrameProc, hWnd, uMsg, wParam, lParam);
- }
-
- // oppX and oppY refer to the x and y coordinates if the menu has to open in the opposite direction. Default is to not use them
- void CDropMenu::TrackDropMenu(CWnd *pParent, int x, int y, BOOL bDragging, CDropMenuDropTarget *pDropTarget, BOOL bShowFeedback, int oppX, int oppY)
- {
- if(!m_bShowing)
- {
- m_bShowFeedback = bShowFeedback;
- m_bDragging = bDragging;
- m_bHasSubMenu = FALSE;
- m_pParent = pParent;
- m_bFirstPaint =TRUE;
- if(m_pMenuParent != NULL)
- {
- m_bRight = m_pMenuParent->m_bRight;
- }
-
- // m_bNotDestroyed = TRUE;
- if(GetMenuItemCount() == 0)
- GetTopLevelParent()->SendMessage(DM_FILLINMENU, 0, (LPARAM)this);
-
-
-
- m_bShowing = TRUE;
- m_bAboutToShow = FALSE;
- m_bIsOpen = TRUE;
-
- if(m_hSubmenuUnselectedBitmap == NULL)
- m_hSubmenuUnselectedBitmap = ::LoadBitmap(AfxGetResourceHandle(), MAKEINTRESOURCE(IDB_SUBMENU1));
-
- if(m_hSubmenuSelectedBitmap == NULL)
- m_hSubmenuSelectedBitmap = ::LoadBitmap(AfxGetResourceHandle(), MAKEINTRESOURCE(IDB_SUBMENU2));
-
- if(!::IsWindow(m_hWnd))
- {
- CWnd::CreateEx(0, AfxRegisterWndClass( CS_SAVEBITS ,
- theApp.LoadStandardCursor(IDC_ARROW),
- (HBRUSH)(COLOR_MENU + 1), NULL),"test", WS_POPUP , 0, 0, 0,0, pParent->m_hWnd, NULL, NULL);
-
- SetDropMenuTarget(pDropTarget);
- }
- else delete pDropTarget;
-
- CSize size = GetMenuSize();
-
- CPoint startPoint = FindStartPoint(x, y, size, oppX, oppY);
-
- if(m_pMenuParent == NULL)
- {
- if(gLastMenu !=NULL)
- {
- //we only want one drop menu open at a time, so close the last one if one is
- //still open. This will probably only happen on drag and drop.
- gLastMenu->Deactivate();
- }
-
- oldFrameProc = SetWindowLong(GetParentFrame()->m_hWnd, GWL_WNDPROC, (LONG)FrameProc);
- #ifdef _WIN32
- currentMouseHook = SetWindowsHookEx(WH_MOUSE, HandleMouseEvents, AfxGetInstanceHandle(), GetCurrentThreadId());
- currentKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, HandleKeyboardEvents, AfxGetInstanceHandle(),GetCurrentThreadId());
- #else
- currentMouseHook = SetWindowsHookEx(WH_MOUSE, HandleMouseEvents, AfxGetInstanceHandle(), GetCurrentTask());
- currentKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, HandleKeyboardEvents, AfxGetInstanceHandle(), GetCurrentTask());
- #endif
- gLastMenu = this;
- }
-
- SetWindowPos(NULL, startPoint.x, startPoint.y,
- size.cx + (2*MENU_BORDER_SIZE), size.cy + (2 * MENU_BORDER_SIZE),
- SWP_NOZORDER | SWP_NOACTIVATE);
- ShowWindow(SW_SHOWNA);
- //SetActiveWindow();
- }
- else delete pDropTarget;
- }
-
- void CDropMenu::SetDropMenuTarget(CDropMenuDropTarget *pDropTarget)
- {
-
- m_pDropTarget = pDropTarget;
-
- DragAcceptFiles();
- m_pDropTarget->Register(this);
-
- }
-
- BOOL CDropMenu::PointInMenus(POINT pt)
- {
-
- CRect rect;
-
- GetWindowRect(&rect);
-
- if(rect.PtInRect(pt))
- {
- return TRUE;
- }
- else
- {
- CDropMenu *menu = m_pMenuParent;
-
- while(menu != NULL && IsWindow(menu->m_hWnd))
- {
- menu->GetWindowRect(&rect);
- if(rect.PtInRect(pt))
- {
- return TRUE;
- }
- menu=menu->m_pMenuParent;
- }
-
- menu = m_pShowingSubmenu;
-
- while(menu !=NULL && IsWindow(menu->m_hWnd))
- {
- menu->GetWindowRect(&rect);
- if(rect.PtInRect(pt))
- {
- return TRUE;
- }
- menu = menu->m_pShowingSubmenu;
- }
-
- }
- return FALSE;
- }
-
- void CDropMenu::HandleKeystroke(WPARAM key)
- {
- //Make all open windows know that we are in keyboard mode still
- CDropMenu *pMenu = this;
-
- while(pMenu != NULL)
- {
- pMenu->m_bMouseUsed = FALSE;
- pMenu = pMenu->m_pMenuParent;
- }
-
- if(key == VK_ESCAPE || !m_bDragging)
- {
- switch(key)
- {
- case VK_ESCAPE: currentMenu->Deactivate();
- break;
- case VK_UP: HandleUpArrow();
- break;
- case VK_DOWN: HandleDownArrow();
- break;
- case VK_LEFT: HandleLeftArrow();
- break;
- case VK_RIGHT: HandleRightArrow();
- break;
- case VK_RETURN: HandleReturnKey();
- }
- }
-
- }
-
- BOOL CDropMenu::OnCommand( WPARAM wParam, LPARAM lParam )
- {
- ShowWindow(SW_HIDE);
-
- m_pParent->SendMessage(WM_COMMAND, wParam, lParam);
-
- return 1;
- }
-
- BOOL CDropMenu::DestroyWindow(void)
- {
- return(CWnd::DestroyWindow());
- }
-
-
- void CDropMenu::Deactivate(void)
- {
- if(m_pMenuParent != NULL)
- {
- m_pMenuParent->SendMessage(DM_CLOSEALLMENUS, 0, 0);
-
- }
- ShowWindow(SW_HIDE);
- }
-
- BOOL CDropMenu::ShowWindow( int nCmdShow )
- {
- if(nCmdShow == SW_HIDE && IsWindowVisible())
- {
- m_bIsOpen = FALSE;
- if(m_pMenuParent != NULL)
- {
- //Turn on parent's focus timer
- m_pMenuParent->m_nHaveFocusTimer = m_pMenuParent->SetTimer(IDT_HAVE_FOCUS, HAVE_FOCUS_DELAY, NULL);
- // we only want the parent to be the current menu if the parent hasn't already
- // brought up a new submenu. Otherwise we have timing conflicts
- if(m_pMenuParent->m_bShowing &&
- (m_pMenuParent->m_pShowingSubmenu == this || m_pMenuParent->m_pShowingSubmenu == NULL))
- {
- currentMenu = m_pMenuParent;
- }
-
- }
- KillTimer(m_nHaveFocusTimer);
-
- //if this is the top level parent then the hook needs to be destroyed
- if(m_pMenuParent == NULL)
- {
- UnhookWindowsHookEx(currentMouseHook);
- UnhookWindowsHookEx(currentKeyboardHook);
- SetWindowLong(GetParentFrame()->m_hWnd, GWL_WNDPROC, (LONG)oldFrameProc);
- currentMenu = NULL;
- gLastMenu = NULL;
- }
- OnTimer(IDT_SUBMENU_OFF);
- m_bShowing = FALSE;
- m_nSelectedItem = -1;
-
- if(m_pShowingSubmenu)
- {
- //check to see if it's valid first because we may
- //want to deactivate before it was created due to
- //the timer never having been called to create it
- if(IsWindow(m_pShowingSubmenu->m_hWnd))
- {
- m_pShowingSubmenu->ShowWindow(SW_HIDE);
- }
- m_pShowingSubmenu = NULL;
- }
- if(m_pMenuParent == NULL)
- {
- m_pParent->PostMessage(DM_MENUCLOSED, 0, 0);
-
- }
- }
- else if(nCmdShow == SW_SHOWNA)
- {
- if(m_pMenuParent != NULL)
- {
- //since we are being shown, turn off parent's focus timer
- m_pMenuParent->KillTimer(m_nHaveFocusTimer);
- }
-
- m_nHaveFocusTimer = SetTimer(IDT_HAVE_FOCUS, HAVE_FOCUS_DELAY, NULL);
- currentMenu = this;
-
- }
-
- return CWnd::ShowWindow(nCmdShow);
-
-
- }
-
- void CDropMenu::PostNcDestroy(void )
- {
- CWnd::PostNcDestroy();
- }
-
- void CDropMenu::DestroyDropMenu(void)
- {
- DestroyWindow();
-
- }
- //////////////////////////////////////////////////////////////////////////
- // Messages for CDropMenu
- //////////////////////////////////////////////////////////////////////////
-
- BEGIN_MESSAGE_MAP(CDropMenu, CWnd)
- //{{AFX_MSG_MAP(CWnd)
- ON_WM_PAINT()
- ON_WM_LBUTTONDOWN()
- ON_WM_LBUTTONUP()
- ON_WM_RBUTTONDOWN()
- ON_WM_MOUSEMOVE()
- ON_WM_NCHITTEST()
- ON_MESSAGE(DT_DROPOCCURRED, OnDropTargetDropOccurred)
- ON_MESSAGE(DT_DRAGGINGOCCURRED, OnDropTargetDraggingOccurred)
- ON_MESSAGE(DM_CLOSEALLMENUS, OnCloseAllMenus)
- ON_WM_TIMER()
- ON_WM_ACTIVATE()
- ON_WM_DESTROY()
- //}}AFX_MSG_MAP
-
- END_MESSAGE_MAP()
-
- void CDropMenu::OnPaint()
- {
- CRect updateRect;
-
-
- if(GetUpdateRect(&updateRect))
- {
- CPaintDC dcPaint(this); // device context for painting
-
- CRect rcClient;
-
- GetClientRect(&rcClient);
-
- HDC hSrcDC = dcPaint.m_hDC;
-
- HDC hMemDC = ::CreateCompatibleDC(hSrcDC);
- HBITMAP hbmMem = CreateCompatibleBitmap(hSrcDC,
- rcClient.Width(),
- rcClient.Height());
-
- //
- // Select the bitmap into the off-screen DC.
- //
- COLORREF rgbOldBk = ::SetBkColor(hMemDC, sysInfo.m_clrMenu);
-
- HBITMAP hbmOld = (HBITMAP)::SelectObject(hMemDC, hbmMem);
-
- HBRUSH brFace = sysInfo.m_hbrMenu;
- ::FillRect(hMemDC, rcClient, brFace);
-
- CRect intersectRect;
- int nNumColumns = m_pColumnArray.GetSize();
- int nFirstItem, nLastItem;
- CDropMenuColumn *pColumn;
- int nStartX = 0;
-
- for(int j = 0; j <=m_nLastVisibleColumn; j++)
- {
- int y = MENU_BORDER_SIZE;
-
- pColumn = (CDropMenuColumn*)m_pColumnArray[j];
-
- nFirstItem = pColumn->GetFirstItem();
- nLastItem = pColumn->GetLastItem();
-
- for(int i = nFirstItem; i <= nLastItem; i++)
- {
- CDropMenuItem *item = (CDropMenuItem*)m_pMenuItemArray[i];
-
- if(m_bShowFeedback)
- y += SPACE_BETWEEN_ITEMS;
-
- if(item->IsSeparator())
- {
- CRect separatorRect(nStartX + MENU_BORDER_SIZE, y, nStartX + MENU_BORDER_SIZE + pColumn->GetWidth(), y + SEPARATOR_SPACE * 2 + SEPARATOR_HEIGHT);
-
- if(intersectRect.IntersectRect(separatorRect, updateRect))
- {
- DrawSeparator(hMemDC, separatorRect.left, y, separatorRect.Width() - (2 * MENU_BORDER_SIZE));
- }
- y += SEPARATOR_SPACE * 2 + SEPARATOR_HEIGHT;
- }
- else
- {
- CRect itemRect;
-
- item->GetMenuItemRect(itemRect);
- if(intersectRect.IntersectRect(itemRect, updateRect))
- {
- CRect rect(nStartX + MENU_BORDER_SIZE, y ,nStartX + MENU_BORDER_SIZE + pColumn->GetWidth(), y + itemRect.Height());
-
- DrawItem(pColumn, item, rect, hMemDC, i == m_nSelectedItem,
- (i == m_nSelectedItem) ? m_eSelectedItemSelType : eNONE);
- }
-
- y += itemRect.Height();
- }
-
- }
- nStartX += pColumn->GetWidth();
- if(j < m_nLastVisibleColumn)
- {
- DrawVerticalSeparator(hMemDC, nStartX, MENU_BORDER_SIZE, rcClient.Height() - (2 * MENU_BORDER_SIZE));
- nStartX += SEPARATOR_WIDTH;
- }
- }
- // need to make sure selection type shows up
- if(m_nSelectedItem != NOSELECTION && m_eSelectedItemSelType != eNONE)
- {
- CRect itemRect;
- CDropMenuItem *item = (CDropMenuItem*)m_pMenuItemArray[m_nSelectedItem];
-
- if(!item->IsSeparator())
- {
- item->GetMenuItemRect(itemRect);
-
- CRect rect(itemRect.left, itemRect.top ,itemRect.left + ((CDropMenuColumn*)m_pColumnArray[item->GetColumn()])->GetWidth(), itemRect.top + itemRect.Height());
-
- DrawItem((CDropMenuColumn*)m_pColumnArray[item->GetColumn()], item, rect, hMemDC, TRUE, m_eSelectedItemSelType );
- }
-
- }
- DrawBorders(hMemDC, rcClient);
-
- ::BitBlt(hSrcDC, 0, 0, rcClient.Width(), rcClient.Height(), hMemDC, 0, 0,
- SRCCOPY);
-
- ::SetBkColor(hMemDC, rgbOldBk);
-
- ::SelectObject(hMemDC, hbmOld);
- ::DeleteObject(hbmMem);
-
- ::DeleteDC(hMemDC);
- }
- if(m_bFirstPaint)
- {
- MSG msg;
-
- PeekMessage(&msg, this->m_hWnd, WM_LBUTTONUP, WM_LBUTTONUP, PM_REMOVE);
- m_bFirstPaint = FALSE;
- }
-
- }
-
- void CDropMenu::OnMouseMove(UINT nFlags, CPoint point)
- {
- if(!m_bMouseUsed)
- {
- m_bMouseUsed = TRUE;
- return;
- }
-
- m_bMouseUsed = TRUE;
-
- KeepMenuAroundIfClosing();
- ChangeSelection(point);
- }
-
- UINT CDropMenu::OnNcHitTest( CPoint point )
- {
- return CWnd::OnNcHitTest(point);
- }
-
- void CDropMenu::OnLButtonUp(UINT nFlags, CPoint point)
- {
- //if we haven't painted yet then the user hasn't had a chance to mouse up.
- if(m_bFirstPaint || m_nSelectedItem == NOSELECTION)
- return;
-
- MenuSelectionType eSelType;
- int nSelection = FindSelection(point, eSelType);
-
- if(nSelection != -1)
- {
- CDropMenuItem *pItem = (CDropMenuItem *)m_pMenuItemArray[nSelection];
-
- if(!pItem->IsSubMenu())
- {
- SendMessage(WM_COMMAND, (WPARAM) pItem->GetCommand(), (LPARAM) m_hWnd);
- }
- }
- }
-
- void CDropMenu::OnLButtonDown(UINT nFlags, CPoint point)
- {
- // we want our frame to stay the active window. Causes flicker
- GetParentFrame()->SetActiveWindow();
- }
-
- void CDropMenu::OnRButtonDown(UINT nFlags, CPoint point)
- {
- // we want our frame to stay the active window. Causes flicker
- GetParentFrame()->SetActiveWindow();
- }
-
-
- LRESULT CDropMenu::OnDropTargetDraggingOccurred(WPARAM wParam, LPARAM lParam)
- {
- if (wParam == 0)
- {
- CDropMenuDragData* pData = (CDropMenuDragData*)lParam;
- KeepMenuAroundIfClosing();
- ChangeSelection(pData->m_PointHit);
-
- // Ok, now we need to figure out what our drag feedback should be.
- // note that point is already in our coordinates since we got it from our drop target
- MenuSelectionType eSelType;
- int nSelection = FindSelection(pData->m_PointHit, eSelType);
-
- if(nSelection != -1)
- {
- CDropMenuItem *pItem = (CDropMenuItem *)m_pMenuItemArray[nSelection];
- pData->m_nCommand = pItem->GetCommand();
- pData->eSelType = eSelType;
- m_pParent->SendMessage(DT_DRAGGINGOCCURRED, 1, lParam);
- }
- }
- else
- {
- m_pParent->SendMessage(DT_DRAGGINGOCCURRED, 1, lParam);
- }
-
- return 1;
- }
-
- LRESULT CDropMenu::OnDropTargetDropOccurred(WPARAM wParam, LPARAM lParam)
- {
- if (wParam == 0)
- {
- CDropMenuDragData* pData = (CDropMenuDragData*)lParam;
-
- // Ok, now we need to figure out what our drag feedback should be.
- // note that point is already in our coordinates since we got it from our drop target
- MenuSelectionType eSelType;
- int nSelection = FindSelection(pData->m_PointHit, eSelType);
-
- if(nSelection != -1)
- {
- CDropMenuItem *pItem = (CDropMenuItem *)m_pMenuItemArray[nSelection];
- pData->m_nCommand = pItem->GetCommand();
- pData->eSelType = eSelType;
- m_pParent->SendMessage(DT_DROPOCCURRED, 1, lParam);
- }
- }
- else
- {
- m_pParent->SendMessage(DT_DROPOCCURRED, 1, lParam);
- }
-
- ShowWindow(SW_HIDE);
-
- return 1;
- }
-
- LRESULT CDropMenu::OnCloseAllMenus(WPARAM wParam, LPARAM lParam)
- {
-
- if(m_pMenuParent != NULL)
- {
- m_pMenuParent->PostMessage(DM_CLOSEALLMENUS, wParam, lParam);
- }
-
- ShowWindow(SW_HIDE);
-
- return 1;
- }
-
-
- void CDropMenu::OnTimer( UINT nIDEvent )
- {
- if(nIDEvent == IDT_SUBMENU_OFF)
- {
- KillTimer(m_nUnselectTimer);
-
- if(m_pUnselectedItem != NULL && m_pUnselectedItem->GetSubMenu()->m_bShowing==FALSE)
- {
- m_pUnselectedItem->GetSubMenu()->ShowWindow(SW_HIDE);
- }
- m_pUnselectedItem = NULL;
-
- }
- else if(nIDEvent == IDT_SUBMENU_ON)
- {
- KillTimer(m_nSelectTimer);
-
- if(m_bShowing)
- {
-
- if(m_pSelectedItem)
- {
- CDropMenu *pSubMenu = m_pSelectedItem->GetSubMenu();
- if(pSubMenu && pSubMenu->m_bAboutToShow)
- ShowSubmenu(m_pSelectedItem);
- else
- m_pSelectedItem = NULL;
-
- }
- m_nSelectTimer = 0;
- }
- }
- else if(nIDEvent == IDT_HAVE_FOCUS)
- {
- if(m_nSelectedItem != -1 && m_bMouseUsed)
- {
- CDropMenuItem *pItem = (CDropMenuItem*)m_pMenuItemArray[m_nSelectedItem];
-
- CPoint point;
-
- GetCursorPos(&point);
-
- ScreenToClient(&point);
-
- CRect rcClient, rect;
- GetClientRect(rcClient);
-
- if (!rcClient.PtInRect(point) && m_pShowingSubmenu == NULL )
- {
- pItem->GetMenuItemRect(rect);
- rect.left = 0;
- rect.right = rcClient.right;
-
- m_nSelectedItem = -1;
-
- InvalidateRect(&rect);
- }
- }
- }
-
- }
-
- void CDropMenu::OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized )
- {
- if(nState == WA_ACTIVE)
- {
- pWndOther->SetActiveWindow();
- }
- }
-
- void CDropMenu::OnDestroy( )
- {
- m_pDropTarget->Revoke();
- CWnd::OnDestroy();
- }
-
-
- //////////////////////////////////////////////////////////////////////////
- // Helpers for CDropMenu
- //////////////////////////////////////////////////////////////////////////
-
- void CDropMenu::DrawSeparator(HDC hDC, int x, int y, int nWidth)
- {
-
- HPEN pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
- HPEN pOldPen = (HPEN)::SelectObject(hDC, pen);
-
- #if defined (WIN32)
- ::MoveToEx(hDC, x, y + SEPARATOR_SPACE, NULL);
- #else
- ::MoveTo(hDC, x, y + SEPARATOR_SPACE);
- #endif
- ::LineTo(hDC, x + nWidth, y + SEPARATOR_SPACE);
-
- ::SelectObject(hDC, pOldPen);
- ::DeleteObject(pen);
-
- #if defined(WIN32)
- pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHILIGHT));
- #else
- pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
- #endif
-
- pOldPen = (HPEN)::SelectObject(hDC, pen);
-
- #if defined(WIN32)
- ::MoveToEx(hDC, x, y + SEPARATOR_SPACE + 1, NULL);
- #else
- ::MoveTo(hDC, x, y + SEPARATOR_SPACE + 1);
- #endif
-
- ::LineTo(hDC, x + nWidth, y + SEPARATOR_SPACE + 1);
-
- ::SelectObject(hDC, pOldPen);
- ::DeleteObject(pen);
-
- }
-
- void CDropMenu::DrawVerticalSeparator(HDC hDC, int x, int y, int nHeight)
- {
- HPEN pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
- HPEN pOldPen = (HPEN)::SelectObject(hDC, pen);
-
- #if defined (WIN32)
- ::MoveToEx(hDC, x + SEPARATOR_SPACE, y, NULL);
- #else
- ::MoveTo(hDC, x + SEPARATOR_SPACE, y);
- #endif
- ::LineTo(hDC, x + SEPARATOR_SPACE, y + nHeight);
-
- ::SelectObject(hDC, pOldPen);
- ::DeleteObject(pen);
-
- #if defined(WIN32)
- pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHILIGHT));
- #else
- pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
- #endif
-
- pOldPen = (HPEN)::SelectObject(hDC, pen);
-
- #if defined(WIN32)
- ::MoveToEx(hDC, x + SEPARATOR_SPACE + 1, y, NULL);
- #else
- ::MoveTo(hDC, x + SEPARATOR_SPACE + 1, y);
- #endif
-
- ::LineTo(hDC, x + SEPARATOR_SPACE + 1, y + nHeight);
-
- ::SelectObject(hDC, pOldPen);
- ::DeleteObject(pen);
- }
-
- void CDropMenu::DrawBorders(HDC hDC, CRect rcClient)
- {
-
- //Draw inner rect which is all BTN_FACE
- RECT rect;
- ::SetRect(&rect, rcClient.left + 2, rcClient.top + 2, rcClient.right - 2, rcClient.bottom - 2);
- ::FrameRect(hDC, &rect, sysInfo.m_hbrBtnFace);
-
- #if defined(WIN32)
- HPEN pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHILIGHT));
- #else
- HPEN pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
- #endif
-
- HPEN pOldPen = (HPEN)::SelectObject(hDC, pen);
-
- #if defined(WIN32)
- ::MoveToEx(hDC, rcClient.left + 1, rcClient.bottom - 1, NULL);
- #else
- ::MoveTo(hDC, rcClient.left + 1, rcClient.bottom - 1);
- #endif
- ::LineTo(hDC, rcClient.left + 1, rcClient.top + 1);
- ::LineTo(hDC, rcClient.right - 1, rcClient.top + 1);
-
- ::SelectObject(hDC, pOldPen);
- ::DeleteObject(pen);
-
- pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE));
-
- pOldPen = (HPEN)::SelectObject(hDC, pen);
-
- #if defined(WIN32)
- ::MoveToEx(hDC, rcClient.left, rcClient.bottom - 1, NULL);
- #else
- ::MoveTo(hDC, rcClient.left, rcClient.bottom - 1);
- #endif
-
- ::LineTo(hDC, rcClient.left, rcClient.top);
- ::LineTo(hDC, rcClient.right - 1, rcClient.top);
-
- ::SelectObject(hDC, pOldPen);
- ::DeleteObject(pen);
-
- pen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
-
- pOldPen = (HPEN)::SelectObject(hDC, pen);
-
- #if defined(WIN32)
- ::MoveToEx(hDC, rcClient.right - 1, rcClient.top, NULL);
- #else
- ::MoveTo(hDC, rcClient.right - 1, rcClient.top);
- #endif
-
- ::LineTo(hDC, rcClient.right - 1 , rcClient.bottom - 1);
- ::LineTo(hDC, rcClient.left - 1, rcClient.bottom - 1);
-
- ::SelectObject(hDC, pOldPen);
- ::DeleteObject(pen);
-
- pen = ::CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
-
- pOldPen = (HPEN)::SelectObject(hDC, pen);
-
- #if defined(WIN32)
- ::MoveToEx(hDC, rcClient.right - 2, rcClient.top + 1, NULL);
- #else
- ::MoveTo(hDC, rcClient.right - 2, rcClient.top + 1);
- #endif
- ::LineTo(hDC, rcClient.right - 2, rcClient.bottom - 2);
- ::LineTo(hDC, rcClient.left, rcClient.bottom -2);
-
- ::SelectObject(hDC, pOldPen);
- ::DeleteObject(pen);
-
- }
-
-
- void CDropMenu::DrawItem(CDropMenuColumn *pColumn, CDropMenuItem *pItem, CRect rc, HDC hDC, BOOL bIsSelected, MenuSelectionType eSelType)
- {
- // Extract the goods from lpDI
- ASSERT(pItem != NULL);
-
- // Get proper colors and paint the background first
- COLORREF rgbTxt;
- HBRUSH brFace;
- COLORREF rgbOldBk;
-
- if (bIsSelected && (eSelType == eNONE || eSelType == eON))
- {
- rgbOldBk = ::SetBkColor(hDC, sysInfo.m_clrHighlight);
-
- brFace = sysInfo.m_hbrHighlight;
- rgbTxt = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
- }
- else
- {
- rgbOldBk = ::SetBkColor(hDC, sysInfo.m_clrMenu);
-
- brFace = sysInfo.m_hbrMenu;
- rgbTxt = ::GetSysColor(COLOR_MENUTEXT);
- }
-
- ::FillRect(hDC, rc, brFace);
-
- if(eSelType == eABOVE)
- DrawSeparator(hDC, rc.left, rc.top - SEPARATOR_SPACE - 2, rc.Width() / 2);
- else if(eSelType == eBELOW)
- DrawSeparator(hDC, rc.left, rc.bottom - SEPARATOR_HEIGHT - SEPARATOR_SPACE + 2, rc.Width() / 2);
-
- CDC *pDC = CDC::FromHandle(hDC);
- // Now paint the bitmap, left side of menu
- rc.left += nIMG_SPACE;
- CSize imgSize = DrawImage(pDC, rc, pColumn, pItem, bIsSelected, eSelType);
-
- // And now the text
- HFONT MenuFont;
- #if defined(WIN32)
- NONCLIENTMETRICS ncm;
- ncm.cbSize = sizeof(NONCLIENTMETRICS);
- if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
- {
- MenuFont = theApp.CreateAppFont( ncm.lfMenuFont );
- }
- else
- {
- MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
- }
- #else // Win16
- MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
- #endif // WIN32
-
- HFONT pOldFont = (HFONT)::SelectObject(hDC, MenuFont);
- int nOldBkMode = ::SetBkMode(hDC, TRANSPARENT);
- COLORREF rgbOldTxt = ::SetTextColor(hDC, rgbTxt);
-
- //Figure out where text should go in relation to bitmaps
- rc.left += imgSize.cx + nIMG_SPACE + (pColumn->GetWidestImage()-imgSize.cx);
-
- //Deal with the case where there is a tab for an accelerator
- CString label=pItem->GetText();
-
- DrawText(hDC, (const char*)label, -1, &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE |DT_EXPANDTABS);
-
- ::SetBkMode(hDC, nOldBkMode);
- ::SetTextColor(hDC, rgbOldTxt);
- ::SelectObject(hDC, pOldFont);
-
- #if defined(WIN32)
- if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
- {
- theApp.ReleaseAppFont(MenuFont);
- }
- #endif
-
- // Draw submenu bitmap
- if(pItem->IsSubMenu() && !pItem->IsEmpty())
- {
- HBITMAP pSubmenuBitmap;
-
- if(bIsSelected && (eSelType == eNONE || eSelType == eON))
- {
- pSubmenuBitmap = m_hSubmenuSelectedBitmap;
- }
- else
- {
- pSubmenuBitmap = m_hSubmenuUnselectedBitmap;
- }
-
- // Create a scratch DC and select our bitmap into it.
- HDC pBmpDC = CreateCompatibleDC(hDC);
- HBITMAP pOldBmp = (HBITMAP)::SelectObject(pBmpDC, pSubmenuBitmap);
-
- // Center the image horizontally and vertically
- CPoint ptDst(rc.right - SUBMENU_WIDTH - SUBMENU_RIGHT_MARGIN, rc.top +
- (((rc.Height() - SUBMENU_HEIGHT) + 1) / 2));
-
- // Call the handy transparent blit function to paint the bitmap over
- // the background.
- ::FEU_TransBlt(hDC, ptDst.x, ptDst.y,SUBMENU_WIDTH, SUBMENU_HEIGHT,
- pBmpDC, 0, 0, WFE_GetUIPalette(GetParentFrame()),RGB(255, 0, 255) );
-
- // Cleanup
- ::SelectObject(pBmpDC, pOldBmp);
- ::DeleteDC(pBmpDC);
-
- }
- ::SetBkColor(hDC, rgbOldBk);
-
- } // END OF FUNCTION CDropMenu::DrawItem()
-
- /****************************************************************************
- *
- * CDropMenu::DrawImage
- *
- * PARAMETERS:
- * pDC - pointer to device context to draw on
- * rect - bounding rectangle to draw in
- * pItem - pointer to CDropMenuItem that contains the data
- * bIsSelected - whether this item is selected
- *
- * RETURNS:
- * width of the image, in pixels
- *
- * DESCRIPTION:
- * Protected helper function for drawing the bitmap image in a menu
- * item. We return the size of the painted image so the caller can
- * position the menu text after the image.
- *
- ****************************************************************************/
-
- CSize CDropMenu::DrawImage(CDC * pDC, const CRect & rect, CDropMenuColumn *pColumn, CDropMenuItem * pItem, BOOL bIsSelected,
- MenuSelectionType eSelType)
- {
- CSize sizeImg;
-
- sizeImg.cx = sizeImg.cy = 0;
-
- HBITMAP hImg = (bIsSelected && (!m_bShowFeedback || eSelType == eON || eSelType == eNONE)) ?
- pItem->GetSelectedBitmap() : pItem->GetUnselectedBitmap();
- if (hImg != NULL)
- {
- // Get image dimensions
- BITMAP bmp;
- GetObject(hImg, sizeof(bmp), &bmp);
-
- sizeImg.cx = bmp.bmWidth;
- sizeImg.cy = bmp.bmHeight;
-
- // Create a scratch DC and select our bitmap into it.
- HDC hBmpDC = ::CreateCompatibleDC(pDC->m_hDC);
- HBITMAP hOldBmp = (HBITMAP)SelectObject(hBmpDC, hImg);
-
- // Center the image horizontally and vertically
- CPoint ptDst(rect.left + (pColumn->GetWidestImage() - sizeImg.cx)/2, rect.top +
- (((rect.Height() - sizeImg.cy) + 1) / 2));
-
- // Call the handy transparent blit function to paint the bitmap over
- // the background.
-
- if (pItem->GetIconType() == LOCAL_FILE)
- {
- HICON hIcon = pItem->GetLocalFileIcon();
- DrawIconEx(pDC->m_hDC, ptDst.x, ptDst.y, hIcon, 0, 0, 0, NULL, DI_NORMAL);
- }
- else if (pItem->GetIconType() == ARBITRARY_URL)
- {
- NSNavCenterImage* pImage = pItem->GetCustomIcon();
- HDC hDC = pDC->m_hDC;
- int left = ptDst.x;
- int top = ptDst.y;
- int imageWidth = 16;
- int imageHeight = 16;
- COLORREF bkColor = (bIsSelected && (!m_bShowFeedback || eSelType == eON || eSelType == eNONE)) ?
- GetSysColor(COLOR_HIGHLIGHT) : GetSysColor(COLOR_MENU);
- if (pImage && pImage->CompletelyLoaded())
- {
- // Now we draw this bad boy.
- if (pImage->m_BadImage)
- {
- // display broken icon.
- HDC tempDC = ::CreateCompatibleDC(hDC);
- HBITMAP hOldBmp = (HBITMAP)::SelectObject(tempDC, NSNavCenterImage::m_hBadImageBitmap);
- ::StretchBlt(hDC,
- left, top,
- imageWidth, imageHeight,
- tempDC, 0, 0,
- imageWidth, imageHeight, SRCCOPY);
- ::SelectObject(tempDC, hOldBmp);
- ::DeleteDC(tempDC);
- }
- else if (pImage->bits )
- {
- // Center the image.
- long width = pImage->bmpInfo->bmiHeader.biWidth;
- long height = pImage->bmpInfo->bmiHeader.biHeight;
- int xoffset = (imageWidth-width)/2;
- int yoffset = (imageHeight-height)/2;
- if (xoffset < 0) xoffset = 0;
- if (yoffset < 0) yoffset = 0;
- if (width > imageWidth) width = imageWidth;
- if (height > imageHeight) height = imageHeight;
-
- HPALETTE hPal = WFE_GetUIPalette(NULL);
- HPALETTE hOldPal = ::SelectPalette(hDC, hPal, TRUE);
-
- ::RealizePalette(hDC);
-
- if (pImage->maskbits)
- {
- WFE_StretchDIBitsWithMask(hDC, TRUE, NULL,
- left+xoffset, top+xoffset,
- width, height,
- 0, 0, width, height,
- pImage->bits, pImage->bmpInfo,
- pImage->maskbits, FALSE, bkColor);
- }
- else
- {
- ::StretchDIBits(hDC,
- left+xoffset, top+xoffset,
- width, height,
- 0, 0, width, height, pImage->bits, pImage->bmpInfo, DIB_RGB_COLORS,
- SRCCOPY);
- }
-
- ::SelectPalette(hDC, hOldPal, TRUE);
- }
- }
- }
- else ::BitBlt(pDC->m_hDC, ptDst.x, ptDst.y, sizeImg.cx, sizeImg.cy, hBmpDC, 0, 0, SRCCOPY);
-
- // Cleanup
- ::SelectObject(hBmpDC, hOldBmp);
- ::DeleteDC(hBmpDC);
-
- }
-
- return(sizeImg);
-
- } // END OF FUNCTION CTreeMenu::DrawImage()
-
- CDropMenuDropTarget *CDropMenu::GetDropMenuDropTarget(CWnd *pOwner)
- {
-
- return new CDropMenuDropTarget(pOwner);
- }
-
- CSize CDropMenu::GetMenuSize(void)
- {
- CSize totalSize, itemSize;
-
- int nColumnHeight = MENU_BORDER_SIZE, nColumnWidth = 0;
-
-
- CalculateItemDimensions();
- int nCount = m_pMenuItemArray.GetSize();
-
- int nScreenLeft = 0;
- int nScreenRight = GetSystemMetrics(SM_CXFULLSCREEN);
- int nScreenTop = 0;
- int nScreenBottom = GetSystemMetrics(SM_CYFULLSCREEN);
- #ifdef XP_WIN32
- RECT rect;
- if(SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&rect,0))
- {
- nScreenLeft = rect.left;
- nScreenRight = rect.right;
- nScreenTop = rect.top;
- nScreenBottom = rect.bottom;
- }
- #endif
-
- int nStartX= MENU_BORDER_SIZE;
- int nOldStartX = MENU_BORDER_SIZE;
-
- int nMaxColumnHeight = 0;
-
- int nNumColumns = m_pColumnArray.GetSize();
- CSize columnSize;
- CDropMenuColumn *pColumn;
- m_nLastVisibleColumn = nNumColumns - 1;
-
- for(int i = 0; i < nNumColumns; i++)
- {
- pColumn = (CDropMenuColumn *)m_pColumnArray[i];
- if(pColumn->GetHasSubMenu())
- pColumn->SetWidth(pColumn->GetWidth() + SUBMENU_LEFT_MARGIN + SUBMENU_RIGHT_MARGIN + SUBMENU_WIDTH);
- else
- pColumn->SetWidth(pColumn->GetWidth() + SUBMENU_RIGHT_MARGIN);
-
- columnSize = CalculateColumn(pColumn, nStartX);
-
- if(nScreenLeft + nStartX + columnSize.cx >= nScreenRight)
- {
- //if we have more than one column, don't put in the last separator
- if(nNumColumns > 1)
- {
- if(m_pOverflowMenuItem != NULL)
- {
- if(i > 0)
- nStartX = AddOverflowItem(i - 1, nOldStartX);
- else
- nStartX = AddOverflowItem(i, nStartX - SEPARATOR_WIDTH);
- }
-
-
- }
- m_nLastVisibleColumn = i - 1;
- break;
- }
-
- if(columnSize.cy > nMaxColumnHeight)
- nMaxColumnHeight = columnSize.cy;
-
- nOldStartX = nStartX;
- nStartX += columnSize.cx;
- if(i + 1 < nNumColumns)
- nStartX += SEPARATOR_WIDTH;
- }
-
- totalSize.cy = nMaxColumnHeight;
- totalSize.cx = ((nNumColumns > 1) ? nStartX - SEPARATOR_WIDTH : nStartX);
- return totalSize;
- }
-
- CSize CDropMenu::CalculateColumn(CDropMenuColumn *pColumn, int nStartX)
- {
- int nStart = pColumn->GetFirstItem();
- int nEnd = pColumn->GetLastItem();
- int nColumnWidth = pColumn->GetWidth();
- int nItemHeight;
-
- CSize totalSize(0, MENU_BORDER_SIZE);
- CSize itemSize;
- for(int i = nStart; i <= nEnd; i++)
- {
- CDropMenuItem *item = (CDropMenuItem*)m_pMenuItemArray[i];
-
- if(m_bShowFeedback)
- totalSize.cy += SPACE_BETWEEN_ITEMS;
-
- if(item->IsSeparator())
- {
-
- CRect rect (nStartX, totalSize.cy, nStartX + nColumnWidth, totalSize.cy + SEPARATOR_SPACE * 2 + SEPARATOR_HEIGHT);
- item->SetMenuItemRect(rect);
-
- nItemHeight = SEPARATOR_SPACE * 2 + SEPARATOR_HEIGHT;
-
- }
- else
- {
- itemSize=MeasureItem(item);
- CRect rect(nStartX, totalSize.cy, nStartX + nColumnWidth, totalSize.cy + itemSize.cy);
-
- item->SetMenuItemRect(rect);
-
- nItemHeight = itemSize.cy;
-
- }
-
- totalSize.cy += nItemHeight;
-
- }
- return CSize(pColumn->GetWidth(), totalSize.cy);
- }
-
- //returns the x coordinate of the right side of this last column
- int CDropMenu::AddOverflowItem(int nColumn, int nStartX)
- {
- int nScreenTop = 0;
- int nScreenBottom = GetSystemMetrics(SM_CYFULLSCREEN);
- #ifdef XP_WIN32
- RECT rect;
- if(SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&rect,0))
- {
- nScreenTop = rect.top;
- nScreenBottom = rect.bottom;
- }
- #endif
-
- CDropMenuColumn *pColumn = (CDropMenuColumn *)m_pColumnArray[nColumn];
-
- int nPosition = pColumn->GetLastItem();
-
- CDropMenuItem *pLastItem = (CDropMenuItem*)m_pMenuItemArray[nPosition];
-
- if(pLastItem == m_pOverflowMenuItem)
- return pColumn->GetWidth();
-
- int nHeight = pColumn->GetHeight();
- CRect overflowRect;
- CRect itemRect;
- CDropMenuItem *pItem;
-
- CSize overflowSize = MeasureItem(m_pOverflowMenuItem);
- overflowSize.cx += pColumn->GetWidestImage();
-
- while(nScreenTop + nHeight + overflowSize.cy > nScreenBottom)
- {
- pItem = (CDropMenuItem*)m_pMenuItemArray[nPosition];
- pItem->GetMenuItemRect(&itemRect);
-
-
- nHeight -= itemRect.Height();
- nPosition--;
- }
-
- // add 1 since we've subtracted 1 away
- pColumn->SetLastItem(nPosition + 1);
- pColumn->SetHeight(nHeight + overflowSize.cy);
- m_pOverflowMenuItem->SetColumn(nColumn);
- if(overflowSize.cx > pColumn->GetWidth())
- pColumn->SetWidth(overflowSize.cx);
- m_pMenuItemArray.InsertAt(nPosition + 1, m_pOverflowMenuItem, 1);
- itemRect.SetRect(nStartX, nHeight, nStartX + pColumn->GetWidth(), nHeight + overflowSize.cy);
- m_pOverflowMenuItem->SetMenuItemRect(itemRect);
- return (nStartX + pColumn->GetWidth());
-
- }
-
- void CDropMenu::CalculateItemDimensions(void)
- {
-
- int numItems = m_pMenuItemArray.GetSize();
-
- int nScreenTop = 0;
- int nScreenBottom = GetSystemMetrics(SM_CYFULLSCREEN);
- #ifdef XP_WIN32
- RECT rect;
- if(SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&rect,0))
- {
- nScreenTop = rect.top;
- nScreenBottom = rect.bottom;
- }
- #endif
-
- int nNumCols = 0;
- int nColumnHeight = nScreenBottom + 1;
- int nColumnWidth = 0;
- CSize textSize, unselectedBitmapSize, selectedBitmapSize, itemSize;
- CDropMenuColumn *pColumn = NULL;
- int nMaxBitmapSize = 0, nMaxTextSize = 0;
-
- int nCount = m_pColumnArray.GetSize();
-
- //make sure column array is empty
- for(int j = 0 ; j < nCount; j++)
- delete (CDropMenuColumn*)m_pColumnArray[j];
-
- m_pColumnArray.RemoveAll();
-
- for(int i=0; i<numItems; i++)
- {
- CDropMenuItem *item = (CDropMenuItem*)m_pMenuItemArray[i];
-
- CalculateOneItemsDimensions(item);
-
- textSize = item->GetTextSize();
- selectedBitmapSize = item->GetSelectedBitmapSize();
- unselectedBitmapSize = item->GetUnselectedBitmapSize();
- itemSize = MeasureItem(item);
-
- if(nScreenTop + nColumnHeight + itemSize.cy > nScreenBottom)
- {
- pColumn = new CDropMenuColumn;
- pColumn->SetHasSubMenu(FALSE);
- pColumn->SetFirstItem(i);
-
- m_pColumnArray.Add(pColumn);
- nColumnHeight = nColumnWidth = 0;
- nMaxBitmapSize = 0, nMaxTextSize = 0;
- nNumCols++;
- }
-
- item->SetColumn(nNumCols - 1);
- pColumn->SetLastItem(i);
-
- if(unselectedBitmapSize.cx > nMaxBitmapSize)
- nMaxBitmapSize = unselectedBitmapSize.cx;
-
- if(selectedBitmapSize.cx > nMaxBitmapSize)
- nMaxBitmapSize= selectedBitmapSize.cx;
-
- if(textSize.cx > nMaxTextSize)
- nMaxTextSize = textSize.cx;
-
- if(item->IsSubMenu())
- pColumn->SetHasSubMenu(TRUE);
-
- nColumnHeight += itemSize.cy;
- if(m_bShowFeedback)
- nColumnHeight += SPACE_BETWEEN_ITEMS;
-
- pColumn->SetHeight(nColumnHeight);
-
- pColumn->SetWidth(nMaxBitmapSize + nMaxTextSize + ( nIMG_SPACE * 3));
- pColumn->SetWidestImage(nMaxBitmapSize);
- if(item == m_pOverflowMenuItem)
- return;
- }
-
- if(m_pOverflowMenuItem != NULL)
- CalculateOneItemsDimensions(m_pOverflowMenuItem);
-
- }
-
- void CDropMenu::CalculateOneItemsDimensions(CDropMenuItem* item)
- {
- CSize unselectedBitmapSize, selectedBitmapSize, textSize;
- CString text;
-
- if(!item->IsSeparator())
- {
- unselectedBitmapSize = MeasureBitmap(item->GetUnselectedBitmap());
- item->SetUnselectedBitmapSize(unselectedBitmapSize);
-
- selectedBitmapSize = MeasureBitmap(item->GetSelectedBitmap());
- item->SetSelectedBitmapSize(selectedBitmapSize);
-
- if(item->IsSubMenu())
- {
- m_bHasSubMenu = TRUE;
- }
-
-
- text = item->GetText();
-
- textSize = MeasureText(text);
-
-
- item->SetTextSize(textSize);
- }
-
-
- }
-
- /****************************************************************************
- *
- * CTreeMenu::MeasureBitmap
- *
- * PARAMETERS:
- * pBitmap: The bitmap to measure
- *
- * RETURNS:
- * The size of the bitmap
- *
- * DESCRIPTION:
- * Given a bitmap, this returns its dimensions
- *
- ****************************************************************************/
-
- CSize CDropMenu::MeasureBitmap(HBITMAP hBitmap)
- {
-
- CSize size;
-
- if (hBitmap != NULL)
- {
- BITMAP bmp;
- GetObject(hBitmap, sizeof(bmp), &bmp);
-
- size.cx = bmp.bmWidth;
- size.cy = bmp.bmHeight;
- }
- else
- size.cx = size.cy = 0;
-
- return size;
-
-
- }
-
-
- /****************************************************************************
- *
- * CTreeMenu::MeasureText
- *
- * PARAMETERS:
- * text: The CString text to be measured
- *
- * RETURNS:
- * Returns the size of the text in the current font
- *
- * DESCRIPTION:
- * Given a CString this returns the dimensions of that text
- *
- ****************************************************************************/
-
- CSize CDropMenu::MeasureText(CString text)
- {
-
- HFONT hMenuFont;
-
- #if defined(WIN32)
- NONCLIENTMETRICS ncm;
- ncm.cbSize = sizeof(NONCLIENTMETRICS);
- if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
- {
- hMenuFont = theApp.CreateAppFont( ncm.lfMenuFont );
- }
- else
- {
- hMenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
- }
- #else // Win16
- hMenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
- #endif // WIN32
-
- HDC hDC = ::GetDC(m_hWnd);
-
- HFONT hOldFont = (HFONT) ::SelectObject(hDC, hMenuFont);
- CSize sizeTxt = ::GetTabbedTextExtent(hDC, (LPCSTR)text, strlen(text), 0, NULL);
- ::SelectObject(hDC, hOldFont);
-
- #if defined(WIN32)
- if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
- {
- theApp.ReleaseAppFont(hMenuFont);
- }
- #endif
-
-
- ::ReleaseDC(m_hWnd, hDC);
-
- return sizeTxt;
-
- }
-
- /****************************************************************************
- *
- * CTreeMenu::MeasureItem
- *
- * PARAMETERS:
- * lpMI - pointer to LPMEASUREITEMSTRUCT
- *
- * RETURNS:
- * void
- *
- * DESCRIPTION:
- * We must override this function to inform the system of our menu
- * item dimensions, since we're owner draw style.
- *
- ****************************************************************************/
- //menu item and end of accelerator
-
- CSize CDropMenu::MeasureItem(CDropMenuItem *pItem)
- {
- ASSERT(pItem != NULL);
-
- CSize size;
-
- if(pItem->IsSeparator())
- {
- size.cx = 0;
- size.cy = SEPARATOR_SPACE * 2 + SEPARATOR_HEIGHT;
- }
- else
- {
- // First, get all of the dimensions
- CSize unselectedSizeImg=pItem->GetUnselectedBitmapSize();
- CSize selectedSizeImg = pItem->GetSelectedBitmapSize();
- CSize sizeText=pItem->GetTextSize();
-
- size.cx = sizeText.cx + (nIMG_SPACE * 2);
-
- int maxImageHeight = max(unselectedSizeImg.cy, selectedSizeImg.cy);
-
- size.cy = max(maxImageHeight, sizeText.cy) + 4;
- }
- return size;
-
- }
-
- void CDropMenu::ChangeSelection(CPoint point)
- {
- if(m_bShowing)
- {
- MenuSelectionType eSelType;
- int nSelection = FindSelection(point, eSelType);
-
- eSelType = m_bShowFeedback ? eSelType : eNONE;
-
- if(m_nSelectedItem != nSelection || m_eSelectedItemSelType != eSelType)
- {
- SelectMenuItem(m_nSelectedItem, FALSE, TRUE, m_eSelectedItemSelType);
- SelectMenuItem(nSelection, TRUE, TRUE, eSelType);
- }
- }
- }
-
- int CDropMenu::FindSelection(CPoint point, MenuSelectionType &eSelType)
- {
-
- eSelType = eNONE;
- int nNumColumns = m_pColumnArray.GetSize();
- CRect colRect;
- CDropMenuColumn *pColumn;
- int nStartX = MENU_BORDER_SIZE;
- int nColumnWidth;
-
- for(int i = 0; i < nNumColumns; i++)
- {
-
- pColumn = (CDropMenuColumn*)m_pColumnArray[i];
- nColumnWidth = pColumn->GetWidth();
-
- colRect.SetRect(nStartX, 0, nStartX + nColumnWidth, pColumn->GetHeight());
-
- if(colRect.PtInRect(point))
- {
-
- return (FindSelectionInColumn(pColumn, point, eSelType));
- }
- else
- {
- nStartX += nColumnWidth + SEPARATOR_WIDTH;
- }
-
- }
-
- return -1;
- }
-
- int CDropMenu::FindSelectionInColumn(CDropMenuColumn *pColumn, CPoint point, MenuSelectionType &eSelType)
- {
-
- int y = MENU_BORDER_SIZE;
-
- if(point.y >=0 && point.y <= MENU_BORDER_SIZE)
- return 0;
-
- int nFeedbackHeight = m_bShowFeedback ? SPACE_BETWEEN_ITEMS : 0;
- CDropMenuItem *item;
- int nFirstItem = pColumn->GetFirstItem();
- int nLastItem = pColumn->GetLastItem();
-
- for(int i = nFirstItem; i <= nLastItem; i++)
- {
- item = (CDropMenuItem*)m_pMenuItemArray[i];
-
- CRect rect;
-
- item->GetMenuItemRect(rect);
-
- if( point.y >= y && point.y < y + rect.Height() + nFeedbackHeight)
- {
- if(item->GetShowFeedback())
- eSelType = FindSelectionType(item, point.y - y, rect.Height() + nFeedbackHeight);
- return i;
- }
-
- y += rect.Height() + nFeedbackHeight;
- }
-
- //if we're in the border between the bottom and the last menu item
- if(point.y >= y && point.y <= y + 2*MENU_BORDER_SIZE)
- {
- if(item->GetShowFeedback())
- eSelType = eBELOW;
- return i - 1;
- }
-
-
-
- return -1;
-
- }
-
- MenuSelectionType CDropMenu::FindSelectionType(CDropMenuItem *pItem, int y, int nHeight)
- {
- if(pItem->IsSubMenu())
- {
- if (y >= 0 && y <= nHeight/4.0)
- return eABOVE;
- else if (y <= 3.0*nHeight/4.0)
- return eON;
- else return eBELOW;
- }
- else
- {
- if(y >= 0 && y <= nHeight / 2.0)
- return eABOVE;
- else
- return eBELOW;
- }
- }
-
- void CDropMenu::SelectMenuItem(int nItemIndex, BOOL bIsSelected, BOOL bHandleSubmenus, MenuSelectionType eSelType)
- {
-
- RECT rcClient;
-
- GetClientRect(&rcClient);
-
- if(nItemIndex != -1)
- {
- CDropMenuItem *item = (CDropMenuItem*)m_pMenuItemArray[nItemIndex];
-
- InvalidateMenuItemRect(item);
-
-
- if(!bIsSelected)
- {
-
- m_pShowingSubmenu = NULL;
-
- m_nSelectedItem = -1;
- m_eSelectedItemSelType = eNONE;
-
- if(bHandleSubmenus && item->IsSubMenu() && !item->IsEmpty() && item->GetSubMenu()->m_bShowing)
- {
- if(m_pUnselectedItem == NULL)
- {
- item->GetSubMenu()->m_bShowing = FALSE;
- m_pUnselectedItem = item;
- m_nUnselectTimer = SetTimer(IDT_SUBMENU_OFF ,SUBMENU_DELAY_OFF_MS, NULL);
- }
- }
-
- }
- else
- {
- m_nSelectedItem = nItemIndex;
- m_eSelectedItemSelType = eSelType;
- if(m_nSelectTimer != 0)
- {
- KillTimer(m_nSelectTimer);
- }
-
- if(bHandleSubmenus && item->IsSubMenu() && !item->IsEmpty() && (eSelType == eON || eSelType == eNONE))
- {
- m_pShowingSubmenu = item->GetSubMenu();
- m_pSelectedItem = item;
- m_pSelectedItem->GetSubMenu()->m_bAboutToShow = TRUE;
- m_nSelectTimer = SetTimer(IDT_SUBMENU_ON, SUBMENU_DELAY_ON_MS, NULL);
-
- }
-
- }
- }
- }
-
-
- BOOL CDropMenu::NoSubmenusShowing(void)
- {
- CWnd *child = GetWindow(GW_CHILD);
-
- if(child != NULL)
- {
- while(child != NULL)
- {
- if(child->IsWindowVisible())
- {
- return FALSE;
- }
-
- child = GetWindow(GW_HWNDNEXT);
- }
-
- }
-
- return TRUE;
- }
-
- CDropMenu *CDropMenu::GetMenuParent(void)
- {
-
- return m_pMenuParent;
- }
-
- BOOL CDropMenu::IsDescendant(CWnd *pDescendant)
- {
- CDropMenu *pSubmenu = m_pShowingSubmenu;
-
- while(pSubmenu != NULL)
- {
- if(pSubmenu == pDescendant)
- {
- return TRUE;
- }
-
- pSubmenu = pSubmenu->m_pShowingSubmenu;
- }
-
- return FALSE;
- }
-
- BOOL CDropMenu::IsAncestor(CWnd *pAncestor)
- {
-
- CDropMenu *pMenu = this;
-
- while(pMenu->m_pParent == pMenu->m_pMenuParent)
- {
- if(pMenu->m_pMenuParent == pAncestor)
- {
- return TRUE;
- }
-
-
- pMenu = pMenu->m_pMenuParent;
- }
-
- return FALSE;
- }
-
- //Sees if the hwnd is either this menu, an ancestor or a submenu
- BOOL CDropMenu::IsShowingMenu(HWND hwnd)
- {
-
- if(hwnd == m_hWnd)
- {
- return TRUE;
- }
- else
- {
- CDropMenu *menu = m_pMenuParent;
-
- while(menu != NULL)
- {
- if(hwnd == menu->m_hWnd)
- {
- return TRUE;
- }
- menu=menu->m_pMenuParent;
- }
-
- menu = m_pShowingSubmenu;
-
- while(menu !=NULL)
- {
- if(hwnd == menu->m_hWnd)
- {
- return TRUE;
- }
- menu = menu->m_pShowingSubmenu;
- }
-
- }
- return FALSE;
- }
-
- void CDropMenu::DropMenuTrackDropMenu(CDropMenu *pParent, int x, int y, BOOL bDragging, CDropMenuDropTarget *pDropTarget,
- BOOL bShowFeedback, int oppX, int oppY)
- {
- m_pMenuParent = pParent;
-
- pParent->m_pShowingSubmenu = this;
-
- TrackDropMenu(pParent, x, y, bDragging, pDropTarget, bShowFeedback, oppX, oppY);
- }
-
- int CDropMenu::FindCommand(UINT nCommand)
- {
-
- int nCount = m_pMenuItemArray.GetSize();
-
- for(int i = 0; i < nCount; i++)
- {
- CDropMenuItem * pItem = (CDropMenuItem*)m_pMenuItemArray[i];
- if(!pItem->IsSeparator())
- {
- if(pItem->GetCommand() == nCommand)
- {
- return i;
- }
- }
- }
-
- return -1;
-
- }
-
- CPoint CDropMenu::FindStartPoint(int x, int y, CSize size, int oppX, int oppY)
- {
-
- int nScreenLeft = 0;
- int nScreenRight = GetSystemMetrics(SM_CXFULLSCREEN);
- int nScreenTop = 0;
- int nScreenBottom = GetSystemMetrics(SM_CYFULLSCREEN);
- #ifdef XP_WIN32
- RECT rect;
- if(SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&rect,0))
- {
- nScreenLeft = rect.left;
- nScreenRight = rect.right;
- nScreenTop = rect.top;
- nScreenBottom = rect.bottom;
- }
- #endif
-
-
- if(oppX == -1)
- {
- CRect parentRect;
- m_pParent->GetWindowRect(&parentRect);
-
- oppX = m_bRight ? parentRect.left : parentRect.right;
- }
-
- int nRoomToRight = nScreenRight - (m_bRight ? x : oppX);
- int nRoomToLeft = (m_bRight ? oppX : x) - nScreenLeft;
-
- // if we are opening to the right we need to make sure we don't go off the right
- // side of the screen.
- if(m_bRight)
- {
- //if we will extend past the right
- if(x + size.cx > nScreenRight)
- {
- // if we can fit to the left
- if(oppX - size.cx > nScreenLeft)
- {
- if(m_pMenuParent != NULL)
- {
- x = oppX - size.cx;
- //if it's not the top level menu we want it to overlap its parent
- x -= 2;
- }
- else
- {
- x = oppX - size.cx;
- }
-
- m_bRight = FALSE;
- }
- else
- {
- //see where we have more space
- if(nRoomToRight >= nRoomToLeft)
- x = nScreenRight - size.cx;
- else
- {
- x = nScreenLeft;
- m_bRight = FALSE;
- }
- }
- }
- else if(m_pMenuParent != NULL)
- {
- // if we are a submenu we want to overlap our parent
- x -= 5;
- }
- }
- // if we are opening to the left we need to make sure we don't go off the left
- // side of the screen
- else
- {
- //if we will extend past the left
- if(x - size.cx < nScreenLeft)
- {
- // if we can fit to the right
- if(oppX + size.cx < nScreenRight)
- {
- x = oppX;
- //if it's not the top level menu we want it to overlap its parent
- if(m_pMenuParent != NULL)
- {
- x -= 5;
- }
- m_bRight = TRUE;
- }
- else
- {
- if(nRoomToRight >= nRoomToLeft)
- {
- x = nScreenRight - size.cx;
- m_bRight = TRUE;
- }
- else
- x = nScreenLeft;
- }
- }
- else if(m_pMenuParent != NULL)
- {
- x -= size.cx;
- // if we are a submenu we want to overlap our parent
- x -= 2;
- }
- }
-
- if(y + size.cy > nScreenBottom)
- {
- y -= ((y + size.cy) - nScreenBottom);
-
- }
-
- return CPoint(x, y);
- }
-
- void CDropMenu::HandleUpArrow(void)
- {
- int nSelection;
-
- // need to deal with separators
- if(m_nSelectedItem == NOSELECTION || m_nSelectedItem == 0)
- {
- nSelection = GetMenuItemCount() - 1;
- }
- else
- {
- nSelection = m_nSelectedItem - 1;
- }
-
- while(((CDropMenuItem *)m_pMenuItemArray[nSelection])->IsSeparator())
- {
- nSelection = (nSelection == 0) ? GetMenuItemCount() - 1 : nSelection - 1;
- }
-
- SelectMenuItem(m_nSelectedItem, FALSE, FALSE, eNONE);
- SelectMenuItem(nSelection, TRUE, FALSE, eNONE);
- }
-
- void CDropMenu::HandleDownArrow(void)
- {
- int nSelection;
- int nNumItems = GetMenuItemCount() - 1;
-
- // need to deal with separators
- if(m_nSelectedItem == NOSELECTION || m_nSelectedItem == nNumItems)
- {
- nSelection = 0;
- }
- else
- {
- nSelection = m_nSelectedItem + 1;
- }
-
- while(((CDropMenuItem *)m_pMenuItemArray[nSelection])->IsSeparator())
- {
- nSelection = (nSelection == nNumItems - 1) ? 0 : nSelection + 1;
- }
-
- SelectMenuItem(m_nSelectedItem, FALSE, FALSE, eNONE);
- SelectMenuItem(nSelection, TRUE, FALSE, eNONE);
- }
-
-
- void CDropMenu::HandleLeftArrow(void)
- {
-
- if(m_pMenuParent != NULL)
- {
- m_bShowing = FALSE;
-
- m_pMenuParent->m_bMouseUsed = FALSE;
- ShowWindow(SW_HIDE);
- }
-
-
- }
-
- void CDropMenu::HandleRightArrow(void)
- {
- if(m_nSelectedItem != NOSELECTION)
- {
- CDropMenuItem *pItem = (CDropMenuItem *)m_pMenuItemArray[m_nSelectedItem];
- if(pItem->IsSubMenu())
- {
- m_pShowingSubmenu = pItem->GetSubMenu();
- m_pShowingSubmenu->m_nSelectedItem = 0;
- m_pShowingSubmenu->m_bMouseUsed = FALSE;
- ShowSubmenu(pItem);
- }
- }
- }
-
- void CDropMenu::HandleReturnKey(void)
- {
- if(m_nSelectedItem != NOSELECTION)
- {
- CDropMenuItem *pItem = (CDropMenuItem *)m_pMenuItemArray[m_nSelectedItem];
-
- if(pItem->IsSubMenu())
- {
- HandleRightArrow();
- }
- else
- {
- #ifdef _WIN32
- SendMessage(WM_COMMAND, MAKEWPARAM(pItem->GetCommand(), 0), 0);
- #else
- SendMessage(WM_COMMAND, (WPARAM) pItem->GetCommand(), MAKELPARAM( m_hWnd, 0 ));
- #endif
- }
- }
- }
-
- void CDropMenu::ShowSubmenu(CDropMenuItem *pItem)
- {
-
- CRect rcClient, rect;
-
- GetClientRect(rcClient);
-
- pItem->GetMenuItemRect(rect);
-
- CDropMenuDropTarget *pDropTarget = GetDropMenuDropTarget(pItem->GetSubMenu());
- ClientToScreen(rect);
-
- m_pShowingSubmenu = pItem->GetSubMenu();
-
- pItem->GetSubMenu()->SetSubmenuBitmaps(m_hSubmenuSelectedBitmap, m_hSubmenuUnselectedBitmap);
-
- if(m_bRight)
- {
- pItem->GetSubMenu()->DropMenuTrackDropMenu(this, rect.right, rect.top - 2, m_bDragging, pDropTarget, m_bShowFeedback, rect.left);
- }
- else
- {
- pItem->GetSubMenu()->DropMenuTrackDropMenu(this, rect.left, rect.top - 2, m_bDragging, pDropTarget, m_bShowFeedback, rect.right);
- }
-
- pItem->GetSubMenu()->m_pParentMenuItem = pItem;
-
- }
-
- int CDropMenu::FindMenuItemPosition(CDropMenuItem* pMenuItem)
- {
- int nCount = m_pMenuItemArray.GetSize();
-
- for(int i = 0; i < nCount; i++)
- if(m_pMenuItemArray[i] == pMenuItem)
- return i;
-
- return -1;
-
- }
-
- void CDropMenu::SetSubmenuBitmaps(HBITMAP hSelectedBitmap, HBITMAP hUnselectedBitmap)
- {
-
- m_hSubmenuUnselectedBitmap = hUnselectedBitmap;
- m_hSubmenuSelectedBitmap = hSelectedBitmap;
-
- }
-
- void CDropMenu::InvalidateMenuItemRect(CDropMenuItem *pMenuItem)
- {
-
- CRect rcClient;
- CRect rect;
-
- GetClientRect(&rcClient);
-
- pMenuItem->GetMenuItemRect(rect);
- int nColumn = pMenuItem->GetColumn();
- CDropMenuColumn *pColumn= (CDropMenuColumn*)m_pColumnArray[nColumn];
-
- rect.right = rect.left + pColumn->GetWidth();
- rect.top -= 2;
- rect.bottom += 2;
- InvalidateRect(rect, TRUE);
- }
-
-
- void CDropMenu::KeepMenuAroundIfClosing(void)
- {
- // if there is movement on this menu, then it is showing even
- // if it's been told to go away before.
- m_bShowing = TRUE;
- if(m_pMenuParent)
- {
- CDropMenuItem *pSelectedItem = m_pMenuParent->m_nSelectedItem != -1 ? (CDropMenuItem*)m_pMenuParent->m_pMenuItemArray[m_pMenuParent->m_nSelectedItem] : NULL;
-
- CDropMenu *pSubMenu = pSelectedItem && pSelectedItem->IsSubMenu() ? pSelectedItem->GetSubMenu() : NULL;
- if((pSubMenu && pSubMenu != this) || !pSubMenu)
- {
-
- KillTimer(m_pMenuParent->m_nSelectTimer);
- KillTimer(m_pMenuParent->m_nUnselectTimer);
- m_pMenuParent->m_pUnselectedItem = NULL;
- m_pMenuParent->m_nSelectTimer = 0;
- m_pMenuParent->m_pShowingSubmenu = this;
-
- //We need to make the menu item this belongs to the selected menu item.
- int nPosition = m_pMenuParent->FindMenuItemPosition(m_pParentMenuItem);
-
- if(nPosition != -1)
- {
-
- if(pSelectedItem)
- {
- m_pMenuParent->InvalidateMenuItemRect(pSelectedItem);
- }
-
- m_pMenuParent->m_nSelectedItem = nPosition;
- m_pMenuParent->m_eSelectedItemSelType = eON;
- m_pMenuParent->m_pSelectedItem = m_pParentMenuItem;
-
- m_pMenuParent->InvalidateMenuItemRect(m_pParentMenuItem);
-
- }
-
- }
- }
- }
-
- CWnd *CDropMenu::GetTopLevelParent(void)
- {
-
- CDropMenu *pMenu = this;
-
- while(pMenu->m_pMenuParent != NULL)
- {
- pMenu = pMenu->m_pMenuParent;
- }
-
- return pMenu->m_pParent;
- }
-