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

📄 listbox.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    {
        hr = CreateMainBackBuffer(paint);
        ASSERT(SUCCEEDED(hr));
    }

    if ((HDC)m_BackBuffer)
    {
        // Draw the fill color over the entire non-item part of the list view
        SetRect(
            &NonItemsArea,
            ClientRect.left,
            ItemsArea.bottom,
            ClientRect.right,
            ClientRect.bottom
            );


        //Dump the back buffer into the real hdc
        BitBlt(
            paint,
            NonItemsArea.left,
            NonItemsArea.top,
            RECTWIDTH(NonItemsArea),
            RECTHEIGHT(NonItemsArea),
            m_BackBuffer,
            NonItemsArea.left,  //copy from the same location in the cached dc
            NonItemsArea.top,
            SRCCOPY
            );
    }

    paint.End();

    if (ItemCount > 0)
    {
        // Reinvalidate the invalid part of the window (let the base class handle the drawing)
        InvalidateRect(m_hwnd, &UpdateRect, TRUE);
    }

paint_items:
    return 0;
}

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

    The background of the listview is always the same,
    this function caches the entire DC for the background,
    so drawing in the future is extremely fast.

    Parameters:
        : HDC a compatible device context to build a backbuffer for

    Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
ListBoxImpl_t::CreateMainBackBuffer(
    HDC hdc
    )
{
    ce::auto_hbrush BackgroundBrush = CreateSolidBrush(Colors_t::ListBoxBackgroundColor());
    ce::auto_hpen BorderPen = CreatePen(PS_SOLID, -1, Colors_t::DisplayItemBorderColor());

    if (!BackgroundBrush || !BorderPen)
    {
        return HRESULT_FROM_WIN32(GetLastError());
    }

    HRESULT hr;

    RECT ClientRect;
    GetClientRect(m_hwnd, &ClientRect);

    //Create a bitmap of the right dimensions for the background.
    hr = m_BackBuffer.CreateCanvas(
        m_hwnd,
        ClientRect.right,
        ClientRect.bottom
        );
    if (FAILED(hr))
    {
        return hr;
    }

    m_BackBuffer.SetBrush(BackgroundBrush);
    m_BackBuffer.SetPen(BorderPen);

    Rectangle(
        m_BackBuffer,
        ClientRect.left,
        ClientRect.top,
        ClientRect.right,
        ClientRect.bottom
        );

    //Restore the pen/brush
    m_BackBuffer.SetBrush(NULL);
    m_BackBuffer.SetPen(NULL);

    return hr;
}

/*------------------------------------------------------------------------------
    ListBoxImpl_t::Reposition subcontrols

    During a paint, if our items need to position controls over our client area
    (e.g. edit controls, sliders etc). We need to update the items with
    their new rectangles (and whether or not they are visible)

    Notifies the IVoIPDisplayItems to positions its controls
    and notifies which are onscreen and offscreen
------------------------------------------------------------------------------*/
HRESULT
ListBoxImpl_t::RepositionSubcontrols(
    void
    )
{
    //If the displayitems don't need to position controls
    //short-circuit this function
    if (!m_PositionControlNotification)
    {
        return S_FALSE;
    }

    //Reposition all the items -
    //include whether or not they are on-screen or off-screen
    RECT ClientRect = {0};
    GetClientRect(m_hwnd, &ClientRect);

    RECT ItemRect;

    int Index;
    int ItemCount = OnGetCount();
    int TopItem = OnGetTopIndex();
    HRESULT hr = S_OK;

    if (ItemCount == 0)
    {
        return S_FALSE;
    }

    bool IsPastBottomOfScreen = false;

    //Position each subcontrol with its appropriate rect
    for (Index = 0; Index < ItemCount; Index++)
    {
        //Get the data from the parent
        IVoIPDisplayItem* pItem = reinterpret_cast<IVoIPDisplayItem*>(
            OnGetItemData(Index)
            );
        if (pItem == NULL)
        {
            ASSERT(FALSE);
            continue;
        }

        IVoIPDisplayControl* pControl;
        if (FAILED(
            pItem->QueryInterface(
                IID_IVoIPDisplayControl,
                reinterpret_cast<void**>(&pControl)
                )
            ))
        {
            continue;
        }

        //An item is visible if we have not already iterated past the bottom of the screen
        // AND we are after the top visible index
        bool IsItemVisible = (Index >= TopItem) && (! IsPastBottomOfScreen);

        //Even if its visible, we need to do a sanity check and ensure that
        //it is not past the bottom of our screen.
        if (IsItemVisible)
        {
            OnGetItemRect(Index, &ItemRect);

            //If the top of the item is LOWER than the bottom of our client
            //the item (and all items after it) are NOT visible
            if  (ItemRect.top > ClientRect.bottom)
            {
                IsPastBottomOfScreen = true;
                IsItemVisible = false;
            }
        }

        if (IsItemVisible)
        {
            //Notify the item to position its controls
            hr = pControl->PositionControls(
                m_hwnd,
                &ItemRect
                );
        }
        if (SUCCEEDED(hr))
        {
            hr = pControl->ShowControls(IsItemVisible);
        }
    }

    ASSERT(SUCCEEDED(hr));
    return hr;
}

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

    Notify the parent that there are items above or below the display area

    Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
ListBoxImpl_t::NotifyParentOfOffscreenItems(
    void
    )
{
    RECT ClientRect;
    RECT BottomItemRect = {0};

    DWORD Notification = 0;
    int TopItem = OnGetTopIndex();
    int ItemCount = OnGetCount();

    if ((ItemCount == 0) || (TopItem == LB_ERR))
    {
        goto do_notify;
    }

    if (OnGetItemRect(ItemCount - 1, &BottomItemRect) == LB_ERR)
    {
        goto do_notify;
    }

    GetClientRect(m_hwnd, &ClientRect);

    if (TopItem > 0)
    {
        Notification |= VLBN_ITEMS_ABOVE_DISPLAY;
    }

    //notify of partial items below the display
    if (BottomItemRect.bottom > ClientRect.bottom)
    {
        Notification |= VLBN_ITEMS_BELOW_DISPLAY;
    }

do_notify:
    NotifyParent(
        Notification
        );
    return S_OK;
}

LRESULT
ListBoxImpl_t::OnNotify(
    int ControlId,
    NMHDR* pNotificationHeader
    )
{
    if (!pNotificationHeader)
    {
        return 0;
    }

    CommonUtilities_t::ControlType_e ControlType =
        CommonUtilities_t::GetControlType(pNotificationHeader->hwndFrom);

    switch (pNotificationHeader->code)
    {
    case VNM_SETFOCUS:
        if ((CommonUtilities_t::ControlTypeEdit == ControlType) ||
            (CommonUtilities_t::ControlTypeTrackbar == ControlType))
        {
            // EN_SETFOCUS handler
            // Notification from a child control that it (e.g. edit box) was given focus

            //Get the INT_PTR representing the displayitem - find the item and select its index
            IVoIPDisplayItem* pItem = (IVoIPDisplayItem*)SendMessage(
                pNotificationHeader->hwndFrom,
                WM_COMMON_GETCALLBACK_PTR,
                0,
                0
                );
            if (!pItem)
            {
                return E_POINTER;
            }

            //See if we can find the item in the list
            int Index = OnFindItem(pItem);
            if (Index == LB_ERR)
            {
                return E_INVALIDARG;
            }

            //If we did find the item, set the current selection to be that item
            return OnSetCurSel(Index);
        }
        break;

    case EN_UPDATE:
        if (CommonUtilities_t::ControlTypeEdit == ControlType)
        {
            //Forward to the parent as WM_COMMAND (because edit control sends
            //notifications in this form)
            ForwardMessageToParent(
                WM_COMMAND,
                MAKEWPARAM(
                    GetWindowLong((pNotificationHeader->hwndFrom), GWL_ID),
                    pNotificationHeader->code
                    ),
                (LPARAM)pNotificationHeader->hwndFrom
                );
        }
        break;

    case NM_CUSTOMDRAW:
        if (CommonUtilities_t::ControlTypeTrackbar == ControlType)
        {
            // Reflect the notification back to the control itself
            return SendMessage(
                pNotificationHeader->hwndFrom,
                WM_NOTIFY,
                ControlId,
                (LPARAM)pNotificationHeader
                );
        }
        break;

    default:
        break;
    }

    return 0;
}

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

    Handles LB_INSERTSTRING by ensuring there is a selected item
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::OnAddItem(
    int Index,
    IVoIPDisplayItem* pItem
    )
{
#ifdef VIRTUAL_LISTBOX
    if (!pItem || (Index < -1) || (Index > m_Items.size()))
    {
        return LB_ERR;
    }

    bool Success;
    if ((Index == -1) || (Index == m_Items.size()))
    {
        Index = m_Items.size();
        Success = m_Items.push_back(pItem);
    }
    else
    {
        ASSERT(IsValidIndex(Index));
        Success = m_Items.insert(m_Items[Index], 1, pItem);
    }

    if (!Success)
    {
        return LB_ERRSPACE;
    }

    ASSERT(m_Items[Index] == (void*)pItem);

    // Force a selection if this is the first item in the list
    if (m_Items.size() == 1)
    {
        OnSetCurSel(0);
    }
    return Index;
#else
    LRESULT Result = DefWindowProc(LB_INSERTSTRING, Index, (LPARAM)pItem);

    INT cItems = OnGetCount();

    // Force a selection if this is the first item in the list
    if(cItems == 1)
    {
        OnSetCurSel(0);
    }
    return (LRESULT)Result;

#endif
}

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

    Handles LB_DELETESTRING and ensures there is a selected item
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::OnDeleteItem(
    int Index
    )
{
#ifdef VIRTUAL_LISTBOX
    if (!IsValidIndex(Index))
    {
        return LB_ERR;
    }

    if (m_Items.size() == 1)
    {
        // When the item count is 0, we just do a resetcontent message so that
        // we can reclaim our data storage space.
        OnResetContent();
    }

    // Send a WM_DELETEITEM message for this item
    DeleteItem(Index);

    m_Items.erase(&m_Items[Index]);
    m_VariableHeight.erase(&m_VariableHeight[Index])

    //Make sure an item is still selected

    //if there was no selection, select the top index
    if (m_SelectedItem == LB_ERR)
    {
        OnSetCurSel(m_TopItem);
    }
    //if we deleted the selected index, select the item immediately below it
    else if (m_SelectedItem == Index)
    {
        OnSetCurSel((Index == 0) ? 0 : Index-1);
    }
    else if (m_SelectedItem > Index)
    {
        m_SelectedItem--;
    }

    //EnsureVisible(m_TopItem);

    return m_Items.size();
#else
    int PreviousSelection = OnGetCurSel();
    bool DeletedSelectedItem = (PreviousSelection == Index);

    LRESULT Result = DefWindowProc(LB_DELETESTRING, Index, 0);

    //Make sure an item is still selected

    //if there was no selection, select the top index
    if (PreviousSelection == LB_ERR)
    {
        OnSetCurSel(OnGetTopIndex());
    }
    //if we deleted the selected index, select the item immediately below it
    else if (DeletedSelectedItem && (OnGetCurSel() == LB_ERR))
    {
        OnSetCurSel((Index == 0) ? 0 : Index-1);
    }

    return Result;
#endif
}

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

    Handles WM_DELETEITEM by deleting the IVoIPDisplayItem
    at the specified index and removing the item from the listview

    NOTE: The parent must reflect this if the listbox is to delete the item
          pointer
------------------------------------------------------------------------------*/
LRESULT
ListBoxImpl_t::DeleteItem(
    DELETEITEMSTRUCT* pDeleteStruct
    )
{
    if (!pDeleteStruct)
    {
        return FALSE;
    }

    //Get the item
    IVoIPDisplayItem* pItem = reinterpret_cast<IVoIPDisplayItem*>(
        pDeleteStruct->itemData
        );
    if (!pItem)
    {
        ASSERT(0);
        return FALSE;
    }

    //Have the item remove its controls (if they exist),
    //since this ListView is the parent of those controls.
    IVoIPDisplayControl* pControl;
    if (SUCCEEDED(pItem->QueryInterface(
        IID_IVoIPDisplayControl,
        reinterpret_cast<void**>(&pControl)
        )))
    {
        pControl->RemoveControls();
    }

    //Delete the actual item
    delete pItem;

    OnSetItemData(pDeleteStruct->itemID, NULL);

    return TRUE;
}

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

    Handles WM_DRAWITEM reflected from the parent.

    NOTE: This message has to be reflected from the parent if the listbox
    is to trigger the drawing of the children

    Prompts the IVoIPDisplayItem in the requested item to draw itself
------------------------------------------------------------------------------*/
HRESULT
ListBoxImpl_t::DrawItem(
    DRAWITEMSTRUCT* pDrawStruct
    )
{
#ifdef VIRTUAL_LISTBOX
    IVoIPDisplayItem* pItem = reinterpret_cast<IVoIPDisplayItem*>(
        OnGetItemData(Index)
        );
    if (!pItem)
    {
        ASSERT(0);
        return TRUE;
    }

    RECT ItemRect;
    OnGetItemRect(Index, &ItemRect);
#else
    if (!pDrawStruct)
    {
        return FALSE;
    }

    if (pDrawStruct->itemAction == ODA_FOCUS)

⌨️ 快捷键说明

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