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

📄 listbox.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// 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 "ListBox.h"
#include "DisplayItem.hpp"
#include <commctrl.h>
#include <sipapi.h>
#include "Input.hpp"
#include <winuserm.h>
#include "PaintHelper.hpp"
#include "Layout.hpp"
#include "Common.hpp"
#include "Debug.hpp"


const UINT c_cmsToolTipLag = 1500;

/*------------------------------------------------------------------------------
    Helper function to get the new top index

------------------------------------------------------------------------------*/
int GetNewTopIndex(
    HWND hwndLB,
    int LastVisibleItem,
    int HeightLimit
    )
{
    if ((LastVisibleItem < 0) || (HeightLimit < 0))
    {
        ASSERT(FALSE);
        return -1;
    }

    int NewTopItem = LastVisibleItem;
    int TotalHeight = SendMessage(hwndLB, LB_GETITEMHEIGHT, (WPARAM)NewTopItem, 0);

    while (NewTopItem > 0)
    {
        NewTopItem--;
        TotalHeight += SendMessage(hwndLB, LB_GETITEMHEIGHT, (WPARAM)NewTopItem, 0);
        if (TotalHeight > HeightLimit)
        {
            NewTopItem ++;
            break;
        }
    }

    NewTopItem = max(NewTopItem, 0);

    return NewTopItem;
}


/*------------------------------------------------------------------------------
    ListBoxImpl_t::ListBoxImpl_t

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

    m_PositionControlNotification = true;
    m_RedrawingEnabled = false;
    m_ListBoxHeightChanged  = false;

    m_CheckToolTip = false;
    m_dwToolTipTimer = 0;

    m_OriginalHeight = 0;

#ifdef VIRTUAL_LISTBOX
    m_SelectedItem = LB_ERR;
#endif
}

/*------------------------------------------------------------------------------
    ListBoxImpl_t::~ListBoxImpl_t

    Destructor
------------------------------------------------------------------------------*/
ListBoxImpl_t::~ListBoxImpl_t()
{
    TRACE(ZONE_COMMON_CTOR);
}

/*------------------------------------------------------------------------------
    ListBoxImpl_t::ControlWindowProc

    Handle messages
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::ControlWindowProc(
    UINT Message,
    WPARAM wParam,
    LPARAM lParam,
    bool& Handled
    )
{
    LRESULT Result;

    //by default assume we handled the message
    Handled = true;

    switch (Message)
    {
#ifdef VIRTUAL_LISTBOX
    case LB_GETITEMDATA:
        return OnGetItemData(wParam);

    case LB_SETITEMDATA:
        return OnSetItemData(wParam, reinterpret_cast<IVoIPDisplayItem*>(lParam));

    case LB_GETITEMRECT:
        return OnGetItemRect(wParam, reinterpret_cast<RECT*>(lParam));

    case LB_GETITEMHEIGHT:
        return OnGetItemHeight(wParam);

    case LB_GETCOUNT:
        return OnGetCount();

    case LB_GETCURSEL:
        return OnGetCurSel();

    case LB_GETTOPINDEX:
        return OnGetTopIndex();

    case LB_SETTOPINDEX:
        return OnSetTopIndex(wParam);

    case LB_FINDSTRING:
        return OnFindItem(reinterpret_cast<IVoIPDisplayItem*>(lParam));

    case LB_ITEMFROMPOINT:
        return OnItemFromPoint(LOWORD(lParam), HIWORD(lParam));

    case LB_RESETCONTENT:
        return OnResetContent();
#endif

    case WM_DELETEITEM:
        return DeleteItem(
            reinterpret_cast<DELETEITEMSTRUCT*>(lParam)
            );

    case WM_DRAWITEM:
        return DrawItem(
            reinterpret_cast<DRAWITEMSTRUCT*>(lParam)
            );

    case WM_MEASUREITEM:
        return MeasureItem(
            reinterpret_cast<MEASUREITEMSTRUCT*>(lParam)
            );

#ifdef AUTOMATION
    case LB_GETTEXT:
        return OnGetText(
            wParam,
            reinterpret_cast<WCHAR*>(lParam)
            );

    case LB_GETTEXTLEN:
        return OnGetTextLen(wParam);
#endif

    case LB_ADDSTRING:
        return OnAddItem(-1, reinterpret_cast<IVoIPDisplayItem*>(lParam));

    case LB_INSERTSTRING:
        return OnAddItem(wParam, reinterpret_cast<IVoIPDisplayItem*>(lParam));

    case LB_DELETESTRING:
        return OnDeleteItem(wParam);

    case LB_SETCURSEL:
        return OnSetCurSel(wParam);

    case WM_CLOSE:
        Handled = ForwardMessageToParent(Message, wParam, lParam, &Result);
        return Result;

    case WM_CREATE:
        return OnCreate(reinterpret_cast<const CREATESTRUCT*>(lParam));

    case WM_DESTROY:
        Handled = false;
        return OnDestroy();

    case WM_CTLCOLOREDIT:
    case WM_CTLCOLORSTATIC:
        return OnSetControlBackground(
            Message,
            reinterpret_cast<HDC>(wParam),
            reinterpret_cast<HWND>(lParam)
            );

    case WM_ERASEBKGND:
        // Pretend that the background was erased
        return 1;

    case WM_KEYDOWN:
        return OnKeydown(wParam, lParam);

    case WM_LBUTTONDBLCLK:
    case WM_LBUTTONDOWN:
    case WM_RBUTTONDBLCLK:
    case WM_RBUTTONDOWN:
        return OnMouseButton(wParam, lParam);

    case WM_NOTIFY:
        return OnNotify(wParam, reinterpret_cast<NMHDR*>(lParam));

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

    case WM_SETFOCUS:
        return OnSetFocus(reinterpret_cast<HWND>(wParam));

    case WM_SETREDRAW:
        return OnSetRedraw(wParam);

    case WM_SETTINGCHANGE:
        return OnSettingChange(wParam);

    case WM_TIMER:
        return OnTimer();

    case WM_HSCROLL:
    case WM_VSCROLL:
        //trackbar's notify in the WM_HSCROLL or WM_VSCROLL messages
        switch(LOWORD(wParam))
        {
        case TB_PAGEUP:
        case TB_PAGEDOWN:
        case TB_THUMBPOSITION:
            Handled = ForwardMessageToParent(Message, wParam, lParam, &Result);
            return Result;
        }
        Handled = false;
        return 0;

    default:
        Handled = false;
        return 0;
    }
}

bool
ListBoxImpl_t::IsValidIndex(
    int Index
    )
{
#ifdef VIRTUAL_LISTBOX
    return ((Index >= 0) && (Index < m_Items.size()));
#else
    return ((Index >= 0) && (Index < OnGetCount()));
#endif
}

/*------------------------------------------------------------------------------
    ListBoxImpl_t::OnCreate

    Handles WM_CREATE.
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::OnCreate(
    const CREATESTRUCT* pCreateStruct
    )
{
    LRESULT Result;
    RECT ClientRect;

    if (!pCreateStruct)
    {
        ASSERT(0);
        return -1;
    }

    //Styles not supported by virtual listbox
    if (pCreateStruct->style & (
        LBS_SORT |
        LBS_NOREDRAW |
        LBS_MULTIPLESEL |
        LBS_USETABSTOPS |
        LBS_NOINTEGRALHEIGHT |
        LBS_MULTICOLUMN |
        LBS_NODATA |
        LBS_EXTENDEDSEL |
        LBS_NOSEL
        ))
    {
        ASSERT(0);
    }

    // Set default input mode to numbers
    Input_SetInputMode(m_hwnd, EIM_NUMBERS);

    Result = 0;

    // Create the tool tip window
    if (FAILED(
        m_ToolTip.Create(
            ToolTip_t::GetWindowClassName(),
            L"Tool Tip",
            WS_CHILD,
            0,
            m_hwnd,
            0,
            0,
            0,
            0
            )
        ))
    {
        ASSERT(FALSE);
        Result = -1;
    }

    //remember the original height of the listbox, so when we stretch/shrink the box
    //we have the proper restore size
    GetClientRect(m_hwnd, &ClientRect);
    m_OriginalHeight = ClientRect.bottom;

    return Result;
}

/*------------------------------------------------------------------------------
    ListBoxImpl_t::OnDestroy

    Handles WM_DESTROY by deleting all exisiting IVoIPDisplayItems in the
    listbox
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::OnDestroy(
    void
    )
{
    OnResetContent();
    return 0;
}

LRESULT
ListBoxImpl_t::OnResetContent(
    void
    )
{
    return DefWindowProc(LB_RESETCONTENT, 0, 0);
}

/*------------------------------------------------------------------------------
    ListBoxImpl_t::OnItemFromPoint

    Retrieve the zero-based index of the item nearest the specified point.
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::OnItemFromPoint(
    unsigned short xCoordinate,
    unsigned short yCoordinate
    )
{
#ifdef VIRTUAL_LISTBOX
    bool IsOutsideClientArea =  false;
    int Index;
    RECT ClientRect;

    GetClientRect(m_hwnd, &ClientRect);

    if (yCoordinate < 0)
    {
        IsOutsideClientArea = true;
        yCoordinate = 0;
    }
    else if (yCoordinate > ClientRect.bottom)
    {
        IsOutsideClientArea = true;
        yCoordinate = ClientRect.bottom;
    }

    if (xCoordinate < 0)
    {
        IsOutsideClientArea = true;
        xCoordinate = 0;
    }
    else if (xCoordinate > ClientRect.right)
    {
        IsOutsideClientArea = 1;
        xCoordinate = ClientRect.right;
    }

    if (m_OwnerDraw != OWNERDRAWVAR)
    {
        Index = m_TopItem + (yCoordinate / m_FixedItemHeight);
    }
    else
    {
        POINT Position;
        // Hit test anywhere inside the listbox
        Position.x = xCoordinate;
        Position.y = yCoordinate;

        for (Index = m_TopItem; Index < m_VariableHeight.size(); Index++)
        {
            RECT ItemRect;

            OnGetItemRect(Index, &ItemRect);
            if (PtInRect(&ItemRect, Position))
            {
                break;
            }
        }
    }

    // The point might be on the blank area at the bottom of a not full list.
    if (Index >= m_Items.size())
    {
        IsOutsideClientArea = true;
        Index = max(m_Items.size() - 1, 0);
    }

    return MAKELONG(Index, IsOutsideClientArea ? 1 : 0);
#else
    return DefWindowProc(LB_ITEMFROMPOINT, 0, MAKELONG(xCoordinate, yCoordinate));
#endif
}

LRESULT
ListBoxImpl_t::OnGetItemData(
    int Index
    )
{
#ifdef VIRTUAL_LISTBOX
    if (!IsValidIndex(Index))
    {
        return LB_ERR;
    }

    return reinterpret_cast<LRESULT>(m_Items[Index]);
#else
    LRESULT Result = DefWindowProc(LB_GETITEMDATA, (WPARAM)Index, 0);
    return (Result == LB_ERR) ? NULL : Result;
#endif
}

LRESULT
ListBoxImpl_t::OnSetItemData(
    int Index,
    IVoIPDisplayItem* pItem
    )
{
#ifdef VIRTUAL_LISTBOX
    if (!IsValidIndex(Index))
    {
        return LB_ERR;
    }

    m_Items[Index] = pItem;
    return 0;
#else
    return DefWindowProc(LB_SETITEMDATA, (WPARAM)Index, (LPARAM)pItem);
#endif
}

#ifdef VIRTUAL_LISTBOX
LRESULT
ListBoxImpl_t::OnGetItemHeight(
    int Index
    )
{
    if (m_OwnerDraw != OWNERDRAWVAR)
    {
        return m_FixedItemHeight;
    }

    if (!IsValidIndex(Index))
    {
        return LB_ERR;
    }

    return m_VariableHeight[Index];
}
#endif

LRESULT
ListBoxImpl_t::OnGetItemRect(
    int Index,
    RECT* pRectangle
    )
{
#ifdef VIRTUAL_LISTBOX
    if (!pRectangle)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return LB_ERR;
    }

    if (Index && !IsValidIndex(Index))
    {
        SetRectEmpty(pRectangle);
        return LB_ERR;
    }

    GetClientRect(m_hwnd, pRectangle);

    if (m_OwnerDraw == OWNERDRAWVAR)
    {
        int i;

        if (Index >= m_TopItem)
        {
            for (i = m_TopItem; i < Index; i++)
            {
                pRectangle->top += OnGetItemHeight(i);
            }

            // If item number is 0, it may be we are asking for the rect
            // associated with a nonexistant item so that we can draw a caret
            // indicating focus on an empty listbox.
            pRectangle->bottom = pRectangle->top +
                (i < m_Items.size() ? OnGetItemHeight(i) : m_FixedItemHeight);
        }
        else
        {
            // Item we want the rect of is before TopItem.  Thus, negative
            // offsets for the rect and it is never visible.
            for (i = Index; i < m_TopItem; i++)
                {
                pRectangle->top -= OnGetItemHeight(i);
                }

            pRectangle->bottom = pRectangle->top + OnGetItemHeight(i);
        }
    }
    else
    {
        // For fixed height listboxes

⌨️ 快捷键说明

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