⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 popupmenu.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "PopupMenu.hpp"
#include "PopupMenuItem.hpp"
#include "MenuBar.hpp"
#include "Layout.hpp"
#include "PaintHelper.hpp"
#include "Debug.hpp"
#include "resource.h"
#include "Input.hpp"


/*------------------------------------------------------------------------------
    PopupMenuImpl_t::PopupMenuImpl_t

    Constructor
------------------------------------------------------------------------------*/
PopupMenuImpl_t::PopupMenuImpl_t(
    )
{
    TRACE(ZONE_COMMON_CTOR);

    m_HideMyselfOnly = false;
    m_IsInputMenu = false;

    m_hMenu = NULL;
    m_ParentPopup = NULL;
    m_ChildPopup = NULL;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::~PopupMenuImpl_t

    Desstructor
------------------------------------------------------------------------------*/
PopupMenuImpl_t::~PopupMenuImpl_t(
    )
{
    TRACE(ZONE_COMMON_CTOR);

    for (int i = 0; i < m_Items.size(); i++)
    {
        delete m_Items[i];
    }

    m_Items.clear();
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::ControlWindowProc

    WndProc for this control
------------------------------------------------------------------------------*/
LRESULT
PopupMenuImpl_t::ControlWindowProc(
    UINT Message,
    WPARAM wParam,
    LPARAM lParam,
    bool& Handled
    )
{
    Handled = true;

    switch (Message)
    {
    case WM_CREATE:
        return OnCreate(reinterpret_cast<CREATESTRUCT*>(lParam));

    case WM_ERASEBKGND:
        //pretend to handle this...
        return 1;

    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;

    case WM_KEYDOWN:
        return OnKeydown(wParam, lParam);

    case WM_KILLFOCUS:
        return OnKillFocus(wParam, lParam);

    case WM_LBUTTONDOWN:
        return OnLButtonDown(wParam, lParam);

    case WM_PAINT:
        return OnPaint(reinterpret_cast<HDC>(wParam));

    case WM_SETFOCUS:
        return OnSetFocus(wParam, lParam);

    case WM_COMMON_CALCULATE_DIMENSIONS:
        return OnCalculateDimensions(reinterpret_cast<SIZE*>(lParam));

    case WM_POPUPMENU_HIDEMENUS:
        HidePopupMenus();
        return 0;

    case WM_POPUPMENU_INSERTITEM:
        return OnInsertItem(reinterpret_cast<PopupMenuItem_t*>(lParam));

    case WM_POPUPMENU_SETFLYOUTPARENT:
        return OnSetFlyoutParent(reinterpret_cast<HWND>(lParam));

    case WM_POPUPMENU_SETVISIBLEITEMS:
        m_MaxNumberOfVisibleItems = wParam;
        return 0;

    default:
        Handled = false;
        return 0;
    }
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::GetVisibleItems

    Returns maximum number of visible items
------------------------------------------------------------------------------*/
int
PopupMenuImpl_t::GetVisibleItems(
    void
    )
{
    if (m_MaxNumberOfVisibleItems == -1)
    {
        return m_Items.size();
    }
    return m_MaxNumberOfVisibleItems;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::OnCreate

    Handle WM_CREATE (the MenuBar Helper should be the create parameter)
------------------------------------------------------------------------------*/
LRESULT
PopupMenuImpl_t::OnCreate(
    CREATESTRUCT* pCreateStruct
    )
{
    if (pCreateStruct)
    {
        m_MenuBar = (HWND)pCreateStruct->lpCreateParams;
        m_IsInputMenu = (pCreateStruct->style & VPMS_INPUT) ? true : false;
    }

    m_TopItem = 0;
    m_SelectedItem = 0;
    m_MaxNumberOfVisibleItems = -1;

    return 0;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::OnInsertItem

    Handle WM_POPUPMENU_INSERTITEM
------------------------------------------------------------------------------*/
LRESULT
PopupMenuImpl_t::OnInsertItem(
    PopupMenuItem_t* pItem
    )
{
    if (! pItem)
    {
        ASSERT(FALSE);
        return 0;
    }

    return (m_Items.push_back(pItem) ? 1 : 0);
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::OnCalculateDimensions

    Calculate the dimensions of this object - for now
    we have a static width
------------------------------------------------------------------------------*/
LRESULT
PopupMenuImpl_t::OnCalculateDimensions(
    SIZE* pDimensions
    )
{
    if (! pDimensions)
    {
        ASSERT(FALSE);
        return 0;
    }

    pDimensions->cx = 0;

    for (int Index = 0; Index < m_Items.size(); Index++)
    {
        RECT ItemRect = {0};

        PaintHelper_t::CalculateTextDimensions(
            m_Items[Index]->GetText(),
            -1,
            Fonts_t::StandardText(),
            &ItemRect,
            DT_LEFT | DT_SINGLELINE
            );
        pDimensions->cx = max(pDimensions->cx, ItemRect.right);
    }

    HRESULT hr;

    Bitmap_t CascadeArrow;
    hr = CascadeArrow.Attach(
        GlobalData_t::s_GDICacheObject.LoadCachedBitmap(IDB_POPUPMENU_RIGHT_ARROW)
        );
    ASSERT(SUCCEEDED(hr));

    pDimensions->cx += 2*Layout_t::PopupTextMargin() +
        CascadeArrow.Width() +
        Layout_t::PopupRightArrowRightMargin();

    if (Layout_t::PopupItemWidth() > pDimensions->cx)
    {
        pDimensions->cx = Layout_t::PopupItemWidth();
    }

    pDimensions->cy = GetVisibleItems() * Layout_t::PopupItemHeight();
    return 1;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::OnSetFocus

    Handle us gaining focus
------------------------------------------------------------------------------*/
LRESULT
PopupMenuImpl_t::OnSetFocus(
    WPARAM wParam,
    LPARAM lParam
    )
{
    //set a default selection
    if (m_SelectedItem == -1)
    {
        m_SelectedItem = m_TopItem;
    }

    //reset popup hierarchy
    m_ChildPopup = (HWND)NULL;
    m_HideMyselfOnly = false;

    return DefWindowProc(WM_SETFOCUS, wParam, lParam);
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::OnKillFocus

    Handle us losing focus. If we lose focus unintentionally, we should hide our window
------------------------------------------------------------------------------*/
LRESULT
PopupMenuImpl_t::OnKillFocus(
    WPARAM wParam,
    LPARAM lParam
    )
{
    LRESULT Result = DefWindowProc(WM_KILLFOCUS, wParam, lParam);

    HWND NewFocus = reinterpret_cast<HWND>(wParam);

    //if we lost focus to our child window - or are just hiding ourself, we don't
    //need to hide our parent as well
    if (NewFocus && (NewFocus == m_ChildPopup || m_HideMyselfOnly))
    {
        return Result;
    }

    //otherwise, we need to hide and inform our parent of why we are hiding
    HidePopupMenus();
    return Result;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::OnLButtonDown

    Handle a mouse click in our client area
------------------------------------------------------------------------------*/
LRESULT
PopupMenuImpl_t::OnLButtonDown(
    WPARAM wParam,
    LPARAM lParam
    )
{
    //give ourself focus back!
    SetFocus(m_hwnd);

    WORD yPos = HIWORD(lParam);

    //based on the y-position, figure out the index of the item that was
    //pressed on
    int IndexPressed = m_TopItem + yPos/Layout_t::PopupItemHeight();

    //set the pressed item to be the selected item
    if (! SetCurrentSelection(IndexPressed))
    {
        return 0;
    }

    //force a quick redraw (and sleep for a tiny bit, so the user sees an update)
    UpdateWindow(m_hwnd);
    Sleep(150);

    OnItemActivated();
    return 0;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::OnSetFlyoutParent

    Handle WM_POPUPMENU_SETFLYOUTPARENT
------------------------------------------------------------------------------*/
LRESULT
PopupMenuImpl_t::OnSetFlyoutParent(
    HWND FlyoutParent
    )
{
    m_ParentPopup = FlyoutParent;
    return 0;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::SetCurrentSelection

    Set a new current selection and redraw part of the window
------------------------------------------------------------------------------*/
bool
PopupMenuImpl_t::SetCurrentSelection(
    int NewSelection
    )
{
    //validate the new selection
    if (NewSelection < 0 || NewSelection > m_Items.size())
    {
        return false;
    }

    //has the selection changed?
    if (NewSelection == m_SelectedItem)
    {
        return true;
    }

    int MaxVisibleIndex = GetVisibleItems() - 1;
    bool NeedToUpdateTopItem = false;

    if (NewSelection < m_TopItem)
    {
        NeedToUpdateTopItem = true;
        m_TopItem = NewSelection;
    }
    else if (NewSelection > (m_TopItem + MaxVisibleIndex))
    {
        NeedToUpdateTopItem = true;
        m_TopItem = NewSelection - MaxVisibleIndex;
    }

    if (NeedToUpdateTopItem)
    {
        m_SelectedItem = NewSelection;

        InvalidateRect(m_hwnd, NULL, TRUE);
        return true;
    }

    //invalidate the rects of the old item and new item
    RECT ItemRect = {0};
    GetItemRect(NewSelection, &ItemRect);
    InvalidateRect(m_hwnd, &ItemRect, TRUE);

    GetItemRect(m_SelectedItem, &ItemRect);
    InvalidateRect(m_hwnd, &ItemRect, TRUE);

    m_SelectedItem = NewSelection;

    return true;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::GetItemRect

    Get the drawing rectangle for a specific item
------------------------------------------------------------------------------*/
void
PopupMenuImpl_t::GetItemRect(
    int Index,
    RECT* pRect
    )
{
    ASSERT(pRect);

    GetClientRect(m_hwnd, pRect);

    // Adjust index to be based on top item
    Index -= m_TopItem;

    pRect->top = Index*Layout_t::PopupItemHeight();
    pRect->bottom = (Index+1)*Layout_t::PopupItemHeight() - 1;
    return;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::OnKeydown

    Handle a WM_KEYDOWN event while we have keyboard focus
------------------------------------------------------------------------------*/
LRESULT
PopupMenuImpl_t::OnKeydown(
    WPARAM wParam,
    LPARAM lParam
    )
{
    int Keycode = static_cast<int>(wParam);

    switch (Keycode)
    {
    case VK_UP:
        if (m_SelectedItem)
        {
            SetCurrentSelection(m_SelectedItem - 1);
        }
        else
        {
            SetCurrentSelection(m_Items.size() - 1);
        }
        break;

    case VK_DOWN:
        if (m_SelectedItem == (m_Items.size()-1))
        {
            SetCurrentSelection(0);
        }
        else
        {
            SetCurrentSelection(m_SelectedItem + 1);
        }
        break;

    case VK_LEFT:
        HideMyselfOnly();
        break;

    case VK_RIGHT:
        //right means dig in deeper (if the selected item has a popup menu)
        if (m_SelectedItem >= 0 && m_SelectedItem < m_Items.size())
        {
            if (m_Items[m_SelectedItem]->GetPopupMenu() != NULL)
            {
                OnItemActivated();
            }
        }
        break;

    case VK_RETURN:
        OnItemActivated();
        break;

    default:
        break;
    }

    return 0;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::HideMyselfOnly

    Hide ourself only
------------------------------------------------------------------------------*/
void
PopupMenuImpl_t::HideMyselfOnly(
    )
{
    m_HideMyselfOnly = true;

    ShowWindow(m_hwnd, SW_HIDE);
    m_TopItem = 0;
    m_SelectedItem = -1;

    if (IsWindow((HWND)m_ParentPopup))
    {
        SetFocus((HWND)m_ParentPopup);
    }

    return;
}

/*------------------------------------------------------------------------------
    PopupMenuImpl_t::HidePopupMenus

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -