Как реализовать масштабирование списка с помощью Win32/WTL

Некоторое время назад я реализовал облегченную программу просмотра журналов на WTL/C++. Недавно решил расширить пользовательский интерфейс с возможностью увеличения/уменьшения масштаба. Я добавил вывод из CZoomScrollImpl, как показано ниже:

class CLogView
    : public CWindowImpl<CLogView, CListViewCtrl>
    , public CZoomScrollImpl<CLogView>
    , public CCustomDraw<CLogView>
{
    CLogReader m_logReader;

public:
    DECLARE_WND_SUPERCLASS(_T("ZoomWTL"), CListViewCtrl::GetWndClassName())

    CLogView(){}

    BOOL PreTranslateMessage(MSG* /*pMsg*/){return FALSE;}

    BEGIN_MSG_MAP(CLogView)
        MESSAGE_HANDLER(WM_CREATE, OnCreate)
        MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
        CHAIN_MSG_MAP_ALT(CCustomDraw<CLogView>, 1)
        CHAIN_MSG_MAP(CZoomScrollImpl<CLogView>);
    END_MSG_MAP()

    LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
    LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/);

    DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
    {        
        return CDRF_NOTIFYITEMDRAW;
    }

    void DoPaint(CDCHandle /*dc*/)
    {
/// TODO: Implement!
    }

    DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw);
    LRESULT OnGetdispinfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/);
};

И тут возник вопрос: как отрендерить listview? Раньше он рисовался на заказ, т.е. я указывал только текст и цвет элементов. Каков правильный способ вызвать рендеринг по умолчанию из DoPaint? Или я должен написать весь код рендеринга?

Вот фрагмент файла CPP:

// Columns definitions
LVCOLUMN SQLLOG_COLUMNS[] = {
    { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT, LVCFMT_LEFT, 100, L"Time", -1, 0,0,0 },
    { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT, LVCFMT_LEFT, 140, L"Type", -1, 1,0,0 },
    { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT, LVCFMT_LEFT, 500, L"Message", -1, 2,0,0 },
    { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT, LVCFMT_LEFT, 150, L"Application", -1, 3,0,0 },
};

const int SQLLOG_COLUMNS_CNT = _countof(SQLLOG_COLUMNS);

LRESULT CLogView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
    LRESULT lResult = DefWindowProc(uMsg, wParam, lParam);

    ModifyStyle(0, LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | LVS_ALIGNTOP | LVS_OWNERDATA);
    SetExtendedListViewStyle(LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT /*| LVS_EX_FLATSB | LVS_EX_TRACKSELECT | LVS_EX_GRIDLINES*/);

    while (DeleteColumn(0));

    int iCol = 0;
    for (int i = 0; i < SQLLOG_COLUMNS_CNT; i++)
    {
        LVCOLUMN lvc(SQLLOG_COLUMNS[i]);
        InsertColumn(iCol++, (LVCOLUMN*)&lvc);
    }

    //?not needed: SetScrollSize(1000, 10000, FALSE, false);

    return lResult;
}

LRESULT CLogView::OnGetdispinfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
{
    LV_ITEM* pItem = &((LV_DISPINFO*)pnmh)->item;

    if (pItem->mask & LVIF_TEXT)
    {
        const LOG_MESSAGE* msg = m_logReader.GetMessageData(pItem->iItem);
        switch (pItem->iSubItem)
        {
        case 0:
            switch (msg->msgType)
            {
            default:
            case 0:
                wcscpy(pItem->pszText, L"Normal");
                break;
            case 1:
                wcscpy(pItem->pszText, L"Error");
                break;
            case 2:
                wcscpy(pItem->pszText, L"Notification");
                break;
            case 3:
                wcscpy(pItem->pszText, L"Alert");
                break;
            case 4:
                wcscpy(pItem->pszText, L"Comment");
                break;
            }
            break;
        case 1:
        {
            SYSTEMTIME sysTime, locTime;
            FileTimeToSystemTime((FILETIME*)&msg->timestamp, &sysTime);
            SystemTimeToTzSpecificLocalTime(NULL, &sysTime, &locTime);
            swprintf(pItem->pszText, _CVTBUFSIZE, L"%04d/%02d/%02d %02d:%02d:%02d.%03d", locTime.wYear, locTime.wMonth, locTime.wDay, locTime.wHour, locTime.wMinute, locTime.wSecond, locTime.wMilliseconds);
            break;
        }
        case 2:
            wcscpy(pItem->pszText, msg->message);
            break;
        case 3:
            wcscpy(pItem->pszText, msg->source);
            break;
        }
    }

    return 0;
}

DWORD CLogView::OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
{
    NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(lpNMCustomDraw);

    const LOG_MESSAGE* msg = m_logReader.GetMessageData((size_t)pLVCD->nmcd.dwItemSpec);

    switch (msg->msgType)
    {
    default:
    case 0: pLVCD->clrTextBk = 0xFFFFFF/*White*/; break;
    case 1: pLVCD->clrTextBk = 0x0045FF/*OrangeRed*/; break;
    case 2: pLVCD->clrTextBk = 0xFFFF00/*Cyan*/; break;
    case 3: pLVCD->clrTextBk = 0x00FFFF/*Yellow*/; break;
    case 4: pLVCD->clrTextBk = 0xD3D3D3/*LightGray*/; break;
    }

    // Tell Windows to paint the control itself.
    return CDRF_DODEFAULT;
}

// Returns TRUE if number of messages changed in the ListView; otherwise - FALSE.
BOOL CLogView::ShowMessages()
{
    BOOL msgCountChanged = FALSE;

    size_t numMessages = m_logReader.GetNumMessages();
    if (m_numMessages == numMessages)
    {   // number of messages haven't changed - nothing to do.
        return FALSE;
    }

    if (numMessages == 0)
    {   // messages were cleared
        m_numMessages = 0;
        DeleteAllItems();
        return TRUE;
    }

    int nItemLast = GetItemCount() + numMessages - m_numMessages;
    SetItemCountEx(nItemLast, LVSICF_NOINVALIDATEALL | LVSICF_NOSCROLL);

    m_numMessages = numMessages;

    if (nItemLast > 0)
        EnsureVisible(nItemLast-1, FALSE);

    return TRUE;
}

LRESULT CLogView::OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
    if (MK_CONTROL & wParam)
    {
        int zDelta = (int)GET_WHEEL_DELTA_WPARAM(wParam);
        float scale = this->GetZoomScale();
        if (zDelta < 0)
            scale *= 0.91f;
        else
            scale *= 1.1f;

        this->Zoom(0, 0, scale);

        return 0;
    }

    bHandled = FALSE;
    return 1;
}

person Terry    schedule 12.12.2014    source источник
comment
CZoomScrollImpl предназначен для контекста устройства, а не CListViewCtrl.   -  person Jan S    schedule 17.12.2014
comment
Есть ли пример контекста устройства с CZoomScrollImpl?   -  person Terry    schedule 24.12.2014


Ответы (1)


Ответ пришел неожиданно от родственника, который не является программистом. Она сказала мне изменить шрифт списка!!! Просто и легко... почему я не подумал об этом с самого начала?

person Terry    schedule 29.12.2014