Hide

SftTree/OCX 7.5 - ActiveX Tree Control

Display
Print

BookTable Sample (C++)

This sample illustrates sorting, column reordering, responding to column header clicks, context menus, controlling expand/collapse buttons and plus/minus graphics.

The source code is located at C:\Program Files (x86)\Softelvdm\SftTree OCX 7.5\Samples\VC++\BookTable\BookTableDlg.cpp or C:\Program Files\Softelvdm\SftTree OCX 7.5\Samples\VC++\BookTable\BookTableDlg.cpp (on 32-bit Windows versions).

// BookTableDlg.cpp : implementation file
//

#include "stdafx.h"
#include "BookTable.h"
#include "BookTableDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CBookTableDlg dialog

CBookTableDlg::CBookTableDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CBookTableDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CBookTableDlg)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

    // load all bitmaps
    m_BookClosed.LoadBitmap(IDB_EXPANDABLE);
    m_BookOpen.LoadBitmap(IDB_EXPANDED);
    m_Topic.LoadBitmap(IDB_LEAF);
    m_Plus.LoadBitmap(IDB_PLUS);
    m_Minus.LoadBitmap(IDB_MINUS);
    m_Plain.LoadBitmap(IDB_PLAIN);
}

void CBookTableDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CBookTableDlg)
    DDX_Control(pDX, IDC_CHECKUSEPLAIN, m_CheckUsePlain);
    DDX_Control(pDX, IDC_CHECKSHOWPLUSMIN, m_CheckPlusMin);
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CBookTableDlg, CDialog)
    ON_COMMAND(ITEMMENU_ENTRY, OnMenu_ItemMenu_Entry)
    ON_COMMAND(HEADERMENU_SHOWALL, OnMenu_HeaderMenu_ShowAll)
    ON_COMMAND_RANGE(HEADERMENU_IDS+0, HEADERMENU_IDS+99, OnMenu_HeaderMenu_Entry)
    //{{AFX_MSG_MAP(CBookTableDlg)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_CHECKSHOWPLUSMIN, OnCheckShowPlusMinClicked)
    ON_BN_CLICKED(IDC_CHECKUSEPLAIN, OnCheckUsePlainClicked)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBookTableDlg message handlers

BOOL CBookTableDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    m_vTree = GetDlgItem(IDC_SFTTREE1)->GetControlUnknown();
    ASSERT(m_vTree != NULL);

#if 0
    // This shows how to dynamically create a tree control.  If created dynamically,
    // all properties must also be set dynamically.
    CWnd* pTree = new CWnd();
    pTree->CreateControl(_T("SftTreeOCX75.SftTree.1"), _T(""), WS_CHILD|WS_VISIBLE, CRect(0,0,300,300),
                this, 123, NULL, FALSE, NULL);
    m_vTree = pTree->GetControlUnknown();
    ASSERT(m_vTree != NULL);
#endif

    // random numbers
    srand(0);

    m_vTree->BulkUpdate = VARIANT_TRUE; // Mass update

    // set default item graphic.  This can also be done at design time
    m_vTree->Items->ItemImageExpandable->PutBitmapHandle((OLE_HANDLE)(HBITMAP)m_BookClosed);
    m_vTree->Items->ItemImageExpanded->PutBitmapHandle((OLE_HANDLE)(HBITMAP)m_BookOpen);
    m_vTree->Items->ItemImageLeaf->PutBitmapHandle((OLE_HANDLE)(HBITMAP)m_Topic);

    // set the column header sort indicators
	m_vTree->Headers->SortIndicators = headerSortIndicatorsSftTreeAuto;
    m_vTree->Header[0]->SortIndicator = sortIndicatorSftTreeAscending;

    // make a copy of the tree control's font and make a bold
    // font for certain cells
    IFontPtr pFont = m_vTree->GetFont();
    IFontPtr pCellFont;
    HRESULT hr = pFont->Clone(&pCellFont);
    ASSERT(SUCCEEDED(hr));
    pCellFont->put_Bold(TRUE);

    // Add all available options
    for (int bk = 1 ; bk <= 4 ; ++bk) {
        // add a book
        CString str;
        str.Format(_T("Book %d"), bk);
        long BookIndex = m_vTree->Items->Add(_bstr_t(str));

        str.Format(_T("Description for book %d"), bk);
        m_vTree->Cell[BookIndex][1]->Text = (_bstr_t)str;

        int size = (rand() % 999) + 1;
        str.Format(_T("%d"), size);
        m_vTree->Cell[BookIndex][2]->Text = (_bstr_t)str;
        m_vTree->Item[BookIndex]->Data = size;

        // add chapters
        for (int ch = 1 ; ch <= 2 ; ++ch) {
            str.Format(_T("Chapter %d"), ch);
            long Index = m_vTree->Items->Add((_bstr_t)str);
            m_vTree->Item[Index]->Level = 1;
            // add sections
            for (int sect = 1 ; sect <= 2 ; ++sect) {
                str.Format(_T("Section %d"), sect);
                Index = m_vTree->Items->Add((_bstr_t)str);
                m_vTree->Item[Index]->Level = 2;
            }
        }
        // after adding the book and all dependent items, we
        // collapse the item, so it's up to the user to expand it
        m_vTree->Item[BookIndex]->Collapse(VARIANT_FALSE);
        // set font
        IFontDispPtr pFontDisp = pCellFont;
        m_vTree->Cell[BookIndex][0]->PutFont(pFontDisp);
    }

    // End of Mass-Update
    m_vTree->BulkUpdate = VARIANT_FALSE;

    // Make columns optimal
    m_vTree->ColumnsObj->MakeOptimal();
    // allow horizontal scrolling
    m_vTree->Items->RecalcHorizontalExtent();

    return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CBookTableDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CBookTableDlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}

void CBookTableDlg::OnCancel()
{
    CDialog::OnCancel();
}

void CBookTableDlg::OnCheckShowPlusMinClicked()
{
    if (m_CheckPlusMin.GetCheck()) {
        m_vTree->Items->PlusMinusImageExpandable->PutBitmapHandle((OLE_HANDLE)(HBITMAP)m_Plus);
        m_vTree->Items->PlusMinusImageExpanded->PutBitmapHandle((OLE_HANDLE)(HBITMAP)m_Minus);
    } else {
        m_vTree->Items->PlusMinusImageExpandable->Clear();
        m_vTree->Items->PlusMinusImageExpanded->Clear();
    }
}

void CBookTableDlg::OnCheckUsePlainClicked()
{
    if (m_CheckUsePlain.GetCheck())
        m_vTree->PutButtonPictureH((OLE_HANDLE)(HBITMAP)m_Plain);
    else
        m_vTree->PutButtonPictureH(NULL);
}

void CBookTableDlg::SortHeader(short colIndex)
{
	// get the new, sorted column
    int sortedColumn = m_vTree->Headers->SortedColumn;

    // Sort the data based on the sort indicator
    // Note that column 2 is sorted by Item.Data, which is an integer value (book size in pages)
    if (m_vTree->Header[sortedColumn]->SortIndicator == sortIndicatorSftTreeAscending) {
        if (sortedColumn == 2)
            m_vTree->Items->SortDependents(-1, sortedColumn, sortSftTreeAscItemData);
        else
            m_vTree->Items->SortDependents(-1, sortedColumn, sortSftTreeAscending);
    } else {
        if (sortedColumn == 2)
            m_vTree->Items->SortDependents(-1, sortedColumn, sortSftTreeDscItemData);
        else
            m_vTree->Items->SortDependents(-1, sortedColumn, sortSftTreeDescending);
    }
}

void CBookTableDlg::HeaderMenu(CPoint pt)
{
    m_HeaderMenu.DestroyMenu();
    m_HeaderMenu.CreatePopupMenu();

    int count = 0;
    for (short c = 0 ; c < m_vTree->ColumnsObj->Count ; ++c) {

        m_HeaderMenu.AppendMenu(MF_STRING, HEADERMENU_IDS + c, m_vTree->Header[c]->Text);

        if (m_vTree->Column[c]->WidthPix > 0) {
            m_HeaderMenu.CheckMenuItem(HEADERMENU_IDS + c, MF_CHECKED|MF_BYCOMMAND);
            ++count;
        } else
            m_HeaderMenu.CheckMenuItem(HEADERMENU_IDS + c, MF_UNCHECKED|MF_BYCOMMAND);
    }

    if (count <= 1) {
        for (short c = 0 ; c < m_vTree->ColumnsObj->Count ; ++c) {
            if (m_HeaderMenu.GetMenuState(HEADERMENU_IDS + c, MF_CHECKED))
                m_HeaderMenu.EnableMenuItem(HEADERMENU_IDS + c, MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);
            else
                m_HeaderMenu.EnableMenuItem(HEADERMENU_IDS + c, MF_ENABLED|MF_BYCOMMAND);
        }
    }

    m_HeaderMenu.AppendMenu(MF_SEPARATOR);

    m_HeaderMenu.AppendMenu(MF_STRING, HEADERMENU_SHOWALL, _T("&Show All"));
    if (count < m_vTree->ColumnsObj->Count)
        m_HeaderMenu.EnableMenuItem(HEADERMENU_SHOWALL, MF_ENABLED|MF_BYCOMMAND);
    else
        m_HeaderMenu.EnableMenuItem(HEADERMENU_SHOWALL, MF_DISABLED|MF_GRAYED|MF_BYCOMMAND);

    m_vTree->CancelMode();

    m_HeaderMenu.TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, this);
}

void CBookTableDlg::ItemMenu(CPoint pt)
{
    m_ItemMenu.DestroyMenu();
    m_ItemMenu.CreatePopupMenu();

    m_ItemMenu.AppendMenu(MF_STRING, ITEMMENU_ENTRY, _T("Edit"));
    m_ItemMenu.AppendMenu(MF_STRING, ITEMMENU_ENTRY, _T("Insert"));
    m_ItemMenu.AppendMenu(MF_STRING, ITEMMENU_ENTRY, _T("Append"));
    m_ItemMenu.AppendMenu(MF_STRING, ITEMMENU_ENTRY, _T("Delete"));

    m_vTree->CancelMode();

    m_ItemMenu.TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, this);
}

void CBookTableDlg::OnContextMenuSftTree1(short Button, short Shift, long x, long y)
{
    CPoint pt(x, y);
    ::MapWindowPoints((HWND) m_vTree->hWnd, NULL, &pt, 1);

    // Determine click context menu for header or item
    long l, t, w, h;
    m_vTree->Headers->GetPositionPix(&l, &t, &w, &h);
    if (x >= l && x < l + w && y >= t && y <= t + h) {
        HeaderMenu(pt);
        return;
    }

    // determine item right-clicked
    long ItemIndex;
    ItemIndex = m_vTree->Items->HitTestPix(x, y);
    if (ItemIndex >= 0 && ItemIndex < m_vTree->Items->Count) {
        m_vTree->Items->Current = ItemIndex;
        m_vTree->Item[ItemIndex]->Selected = VARIANT_TRUE;
        ItemMenu(pt);
        return;
    }
}

void CBookTableDlg::OnItemClickSftTree1(long ItemIndex, short ColIndex, short AreaType, short Button, short Shift)
{
    if (AreaType == constSftTreeColumn && Button == constSftTreeLeftButton)
        SortHeader(ColIndex);
    else if (AreaType == constSftTreeExpandAll)
        m_vTree->Item[ItemIndex]->Expand(VARIANT_FALSE, VARIANT_TRUE);
}

void CBookTableDlg::OnItemDblClickSftTree1(long ItemIndex, short ColIndex, short AreaType, short Button, short Shift)
{
    if (AreaType == constSftTreeColumnRes && Button == constSftTreeLeftButton) {
        m_vTree->Column[ColIndex]->MakeOptimal();
        m_vTree->Items->RecalcHorizontalExtent();
    } else if (AreaType == constSftTreeColumn && Button == constSftTreeLeftButton)
        SortHeader(ColIndex);
}

afx_msg void CBookTableDlg::OnMenu_ItemMenu_Entry()
{
    AfxMessageBox(_T("This sample doesn't implement any actions for the item menu.  Try the column headers instead."));
}

afx_msg void CBookTableDlg::OnMenu_HeaderMenu_ShowAll()
{
    m_vTree->ColumnsObj->MakeOptimal();
}

afx_msg void CBookTableDlg::OnMenu_HeaderMenu_Entry(UINT nID)
{
    short colIndex = (short) (nID - HEADERMENU_IDS);
    if (m_HeaderMenu.GetMenuState(nID, MF_CHECKED))
        m_vTree->Column[colIndex]->WidthPix = 0;
    else
        m_vTree->Column[colIndex]->MakeOptimal();
    m_vTree->Items->RecalcHorizontalExtent();
}

BEGIN_EVENTSINK_MAP(CBookTableDlg, CDialog)
    //{{AFX_EVENTSINK_MAP(CBookTableDlg)
    ON_EVENT(CBookTableDlg, IDC_SFTTREE1, 35 /* ContextMenu */, OnContextMenuSftTree1, VTS_I2 VTS_I2 VTS_I4 VTS_I4)
    ON_EVENT(CBookTableDlg, IDC_SFTTREE1, 4 /* ItemClick */, OnItemClickSftTree1, VTS_I4 VTS_I2 VTS_I2 VTS_I2 VTS_I2)
    ON_EVENT(CBookTableDlg, IDC_SFTTREE1, 5 /* ItemDblClick */, OnItemDblClickSftTree1, VTS_I4 VTS_I2 VTS_I2 VTS_I2 VTS_I2)
	//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

Last Updated 08/13/2020 - (email)
© 2024 Softel vdm, Inc.