Hide

SftTree/DLL 7.5 - Tree Control

Display
Print

Pictures Sample (C)

This sample illustrates various image types, progress bars, checkbox and radio button manipulation.

The source code is located at C:\Program Files (x86)\Softelvdm\SftTree DLL 7.5\Samples\C\Pictures\Pictures.c or C:\Program Files\Softelvdm\SftTree DLL 7.5\Samples\C\Pictures\Pictures.c (on 32-bit Windows versions).

/****************************************************************************/
/* SftTree/DLL 7.5 - Tree Control for C/C++                                 */
/* Copyright (C) 1995, 2016  Softel vdm, Inc. All Rights Reserved.          */
/****************************************************************************/

#include <windows.h>

#include "SftTree.h"                     /* SftTree/DLL Header File */

#include "resource.h"                    // resource IDs

/**********************************************************************/
/*                              Globals                               */
/**********************************************************************/

#define IDC_TREE                100     /* Tree control ID */
#define TIMERID                 10      /* Timer ID */

HINSTANCE g_hInst;                      // App Instance Handle
HWND g_hwndTree;                        /* Tree control */

// Miscellaneous bitmaps
SFT_PICTURE m_aThreeItemPictures[3];    /* Three default item pictures, see SetPictures in online help */
//SFT_PICTURE m_OtherItemPicture;       /* Another item picture, see SetItemPicture in online help */
HICON m_hIconSmall;                     /* a small icon */
HBITMAP m_hBitmapSmall;                 /* a small bitmap */
HBITMAP m_hBitmapLarge;                 /* a large bitmap */
HIMAGELIST m_hImgList;                  /* Imagelist control */

HBITMAP m_BitmapClosed = NULL;          // Folder images (if GDI+ is not available)
HBITMAP m_BitmapOpen = NULL;
HBITMAP m_BitmapLeaf = NULL;

// In this example, we are using GDI+ images.
// Even though this is a C application, we can embed the images as resources 
// and use SftTree's SftTree_LoadGDIPlusImageFromResource function to load them
// from a resource.
// GDI+ images CANNOT be added as BITMAP resources. They are always added with
// a custom resource type, in this example we use "PNG".
LPVOID m_ButtonExpanded = NULL;         // GDI+ images for expand/collapse buttons
LPVOID m_ButtonExpandedHot = NULL;      // These can simply be cast to (Gdiplus::Image*)
LPVOID m_ButtonCollapsed = NULL;
LPVOID m_ButtonCollapsedHot = NULL;
LPVOID m_FolderClosed = NULL;           // folder item image
LPVOID m_FolderOpen = NULL;
LPVOID m_FolderLeaf = NULL;

LPVOID m_PNGImage = NULL, m_PNGImage2 = NULL;

#define PIC_SIZEX               16      /* Width of most pictures */
#define PIC_SIZEY               16      /* Height of most pictures */
#define PIC_SIZEX_COLORSAMPLE   12      /* Width of color samples */
#define PIC_SIZEY_COLORSAMPLE   12      /* Height of color samples */
#define PIC_SIZEX_CHECKBOX      14      /* Width of checkbox */
#define PIC_SIZEY_CHECKBOX      14      /* Height of checkbox */
#define PIC_SIZEX_SORT           8      /* Width of sort direction indicator */
#define PIC_SIZEY_SORT           8      /* Height of sort direction indicator */

/**********************************************************************/
/*                         Helper Routines                            */
/**********************************************************************/

static void SetCellPicture(HWND hwndTree, int index, SFT_PICTURE* pPic, int align)
{
    SFTTREE_CELLINFOPARM CellInfo;
    CellInfo.version = 7;
    CellInfo.index = index;
    CellInfo.iCol = 0;
    SftTree_GetCellInfo(hwndTree, &CellInfo);
    Sft_ClearPicture(&CellInfo.Cell.CellPicture1);
    Sft_CopyPicture(&CellInfo.Cell.CellPicture1, pPic);
    CellInfo.Cell.flag = align;
    SftTree_SetCellInfo(hwndTree, &CellInfo);
}

static void SetItemPicture(HWND hwndTree, int index, SFT_PICTURE* pPic)
{
    SftTree_SetItemPicture(hwndTree, index, pPic);
}

static void SetItemLabelPicture(HWND hwndTree, int index, SFT_PICTURE* pPic)
{
    SftTree_SetItemLabelPicture(hwndTree, index, pPic);
}

static void SetRowPicture(HWND hwndTree, int index, SFT_PICTURE* pPic)
{
    SFTTREE_ROWINFOPARM RowInfo;
    RowInfo.version = 7;
    RowInfo.index = index;
    SftTree_GetRowInfo(hwndTree, &RowInfo);
    Sft_ClearPicture(&RowInfo.Row.RowPicture1);
    Sft_CopyPicture(&RowInfo.Row.RowPicture1, pPic);
    RowInfo.Row.flag = SFTTREE_BMP_RIGHT;
    SftTree_SetRowInfo(hwndTree, &RowInfo);
}

static void UpdatePictures(HWND hwndTree, int index, SFT_PICTURE* pPic, int align)
{
    int w, h;

    SetCellPicture(hwndTree, index, pPic, align);

    Sft_GetPictureSize(pPic, &w, &h);
    if (w <= PIC_SIZEX || h <= PIC_SIZEY)  { // don't use images that are too large
        SetItemPicture(hwndTree, index, pPic);
        SetItemLabelPicture(hwndTree, index, pPic);
        SetRowPicture(hwndTree, index, pPic);
    }
}

static void CopyPictureFromCurrentItem(HWND hwndTree)
{
    SFTTREE_CELLINFOPARM CellInfo;
    LPSFTTREE_COLUMN_EX lpCol;
    int nCols;
    int w, h;

    int index = SftTree_GetCurSel(hwndTree);

    if (index < 0) return;

    // retrieve current cell picture
    CellInfo.version = 7;
    CellInfo.index = index;
    CellInfo.iCol = 0;
    SftTree_GetCellInfo(hwndTree, &CellInfo);

    Sft_GetPictureSize(&CellInfo.Cell.CellPicture1, &w, &h);

    if (w <= PIC_SIZEX || h <= PIC_SIZEY)  { // don't use images that are too large for the header
        // copy it to row/column header and column header
        SftTree_SetRowColHeaderPicture(hwndTree, &CellInfo.Cell.CellPicture1);/* Row/column picture */

        nCols = SftTree_GetColumnsEx(hwndTree, &lpCol);/* Get column attributes */
        Sft_CopyPicture(&lpCol[1].Picture1, &CellInfo.Cell.CellPicture1); // second column
        SftTree_SetColumnsEx(hwndTree, nCols, lpCol);  /* Set new column attributes */
    } else {
        SftTree_SetRowColHeaderPicture(hwndTree, NULL);

        nCols = SftTree_GetColumnsEx(hwndTree, &lpCol);/* Get column attributes */
        Sft_ClearPicture(&lpCol[1].Picture1); // second column
        SftTree_SetColumnsEx(hwndTree, nCols, lpCol);  /* Set new column attributes */
    }
}

static BOOL TogglePicture(SFT_PICTURE* pPic)
{
    if (pPic->type == SFT_PICTURE_CB ||                   // check box
            pPic->type == SFT_PICTURE_CB3 ||              // 3 state check box
            pPic->type == SFT_PICTURE_RB ||               // radio button
            pPic->type == SFT_PICTURE_UPDOWN ||           // up/down button
            pPic->type == SFT_PICTURE_UPDOWNSORT)         // sort direction indicator
        pPic->Picture.CheckBox.state = pPic->Picture.CheckBox.state == 1 ? 0 : 1;
    else    
        return FALSE; // nothing to change
    return TRUE;
}

static void ToggleItemPicture(HWND hwndTree, int index)
{
    SFT_PICTURE Pic;
    Sft_InitPicture(&Pic);
    SftTree_GetItemPicture(hwndTree, index, &Pic);
    if (TogglePicture(&Pic))
        SftTree_SetItemPicture(hwndTree, index, &Pic);
}

static void ToggleCellPicture(HWND hwndTree, int index)
{
    SFTTREE_CELLINFOPARM CellInfo;
    CellInfo.version = 7;         
    CellInfo.index = index;
    CellInfo.iCol = 0;
    SftTree_GetCellInfo(hwndTree, &CellInfo);
    if (TogglePicture(&CellInfo.Cell.CellPicture1))
        SftTree_SetCellInfo(hwndTree, &CellInfo);
}

/**********************************************************************/
/*                        Column Header Sorting                       */
/**********************************************************************/

static BOOL g_fAscending = TRUE;

static void ShowSortDirection(HWND hwndTree, BOOL fAscending)
{
    LPSFTTREE_COLUMN_EX lpCol;
    int nCols;

    nCols = SftTree_GetColumnsEx(hwndTree, &lpCol);/* Get column attributes */
    Sft_SetPictureUpDownSort(&lpCol[0].Picture1, fAscending ? 1 : 0, PIC_SIZEX_SORT, PIC_SIZEY_SORT, TRUE);
    SftTree_SetColumnsEx(hwndTree, nCols, lpCol);  /* Set new column attributes */

    g_fAscending = fAscending;
}

int CALLBACK SortCallbackExAscending(HWND hwnd, LPCTSTR lpszString1, LPCTSTR lpszString2, 
                  SFTTREE_DWORD_PTR itemData1, SFTTREE_DWORD_PTR itemData2) 
{
    return lstrcmp(lpszString1, lpszString2); 
} 

int CALLBACK SortCallbackExDescending(HWND hwnd, LPCTSTR lpszString1, LPCTSTR lpszString2, 
                  SFTTREE_DWORD_PTR itemData1, SFTTREE_DWORD_PTR itemData2) 
{
    return lstrcmp(lpszString2, lpszString1); 
} 

static void SortItems(HWND hwndTree, int index, BOOL fAscending)
{
    int parentIndex;

    // sort this item's dependents
    SftTree_SortColDependentsEx(hwndTree, index, 0, fAscending ? SortCallbackExAscending : SortCallbackExDescending);
    // now visit all dependents and sort each dependent's child items.
    if (index < 0)
        parentIndex = 0;
    else
        parentIndex = SftTree_GetDependent(hwndTree, index, SFTTREE_DEPENDENT_FIRST);// start with first item
    for ( ; parentIndex >= 0 ; parentIndex = SftTree_GetSibling(hwndTree, parentIndex, SFTTREE_SIBLING_NEXT)) {
        SortItems(hwndTree, parentIndex, fAscending);
    }
}

static void SetSortDirection(HWND hwndTree, BOOL fAscending)
{
    ShowSortDirection(hwndTree, fAscending);
    SortItems(hwndTree, -1, fAscending);
}

/**********************************************************************/
/*                            Color Samples                           */
/**********************************************************************/

struct tagColorEntry {
    LPCTSTR lpszName;
    COLORREF color;
} aPropListColors[] = {
    { TEXT("Black"),      RGB(  0,  0,  0),  },
    { TEXT("Blue"),       RGB(  0,  0,255),  },
    { TEXT("Cyan"),       RGB(  0,255,255),  },
    { TEXT("Green"),      RGB(  0,255,  0),  },
    { TEXT("Magenta"),    RGB(255,  0,255),  },
    { TEXT("Red"),        RGB(255,  0,  0),  },
    { TEXT("White"),      RGB(255,255,255),  },
    { TEXT("Yellow"),     RGB(255,255,  0),  },
    { TEXT("Dk Blue"),    RGB(  0,  0,128),  },
    { TEXT("Dk Cyan"),    RGB(  0,128,128),  },
    { TEXT("Dk Green"),   RGB(  0,128,  0),  },
    { TEXT("Dk Magenta"), RGB(128,  0,128),  },
    { TEXT("Dk Red"),     RGB(128,  0,  0),  },
    { TEXT("Dk Yellow"),  RGB(128,128,  0),  },
    { TEXT("Dk Gray"),    RGB(128,128,128),  },
    { TEXT("Lt Gray"),    RGB(192,192,192),  },
    { TEXT("3DDKSHADOW - Dark shadow for 3D elements"), 0x80000000L | COLOR_3DDKSHADOW, },
    { TEXT("3DFACE - Face color for 3D elements"), 0x80000000L | COLOR_3DFACE, },
    { TEXT("3DHILIGHT - Edges facing the light source"), 0x80000000L | COLOR_3DHILIGHT, },
    { TEXT("3DLIGHT - Edges facing the light source"), 0x80000000L | COLOR_3DLIGHT, },
    { TEXT("3DSHADOW - Edges facing away from the light source"), 0x80000000L | COLOR_3DSHADOW, },
    { TEXT("INFOBK - Background color for tooltip controls"), 0x80000000L | COLOR_INFOBK, },
    { TEXT("INFOTEXT - Text color for tooltip controls"), 0x80000000L | COLOR_INFOTEXT, },
    { TEXT("MENUTEXT - Text in menus"), 0x80000000L | COLOR_MENUTEXT, },
    { TEXT("ACTIVEBORDER - Active window border"), 0x80000000L | COLOR_ACTIVEBORDER, },
    { TEXT("ACTIVECAPTION - Active window caption"), 0x80000000L | COLOR_ACTIVECAPTION, },
    { TEXT("APPWORKSPACE - Background color MDI applications"), 0x80000000L | COLOR_APPWORKSPACE, },
    { TEXT("BACKGROUND - Desktop"), 0x80000000L | COLOR_BACKGROUND, },
    { TEXT("BTNFACE - Face shading on push buttons"), 0x80000000L | COLOR_BTNFACE, },
    { TEXT("BTNHILIGHT - Highlight color for buttons"), 0x80000000L | COLOR_BTNHIGHLIGHT, },
    { TEXT("BTNSHADOW - Edge shading on push buttons"), 0x80000000L | COLOR_BTNSHADOW, },
    { TEXT("BTNTEXT - Text on push buttons"), 0x80000000L | COLOR_BTNTEXT, },
    { TEXT("CAPTIONTEXT - Text in caption"), 0x80000000L | COLOR_CAPTIONTEXT, },
    { TEXT("GRAYTEXT - Grayed (disabled) text"), 0x80000000L | COLOR_GRAYTEXT, },
    { TEXT("HIGHLIGHT - Selected Item(s)"), 0x80000000L | COLOR_HIGHLIGHT, },
    { TEXT("HIGHLIGHTTEXT - Text of selected item(s)"), 0x80000000L | COLOR_HIGHLIGHTTEXT, },
    { TEXT("INACTIVEBORDER - Inactive window border"), 0x80000000L | COLOR_INACTIVEBORDER, },
    { TEXT("INACTIVECAPTION - Inactive window caption"), 0x80000000L | COLOR_INACTIVECAPTION, },
    { TEXT("INACTIVECAPTIONTEXT - Inactive caption text color"), 0x80000000L | COLOR_INACTIVECAPTIONTEXT, },
    { TEXT("MENU - Menu background"), 0x80000000L | COLOR_MENU, },
    { TEXT("SCROLLBAR - Scroll bar gray area"), 0x80000000L | COLOR_SCROLLBAR, },
    { TEXT("WINDOW - Window background"), 0x80000000L | COLOR_WINDOW, },
    { TEXT("WINDOWFRAME - Window frame"), 0x80000000L | COLOR_WINDOWFRAME, },
    { TEXT("WINDOWTEXT - Text in windows"), 0x80000000L | COLOR_WINDOWTEXT, },
    { NULL, 0 },
};

LRESULT CALLBACK SDI_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg) {

    case WM_CREATE: {
        SFT_PICTURE Pic;                    /* A picture */

        g_hwndTree = CreateWindowEx(
            WS_EX_CLIENTEDGE,                
            TEXT(SFTTREE_CLASS),             /* Window class */
            TEXT(""),                        /* Caption (none) */
            SFTTREESTYLE_NOTIFY |            /* Notify parent window */
            SFTTREESTYLE_VARIABLE |          /* Variable height items */
            SFTTREESTYLE_LEFTBUTTONONLY |    /* Only respond to left mouse button */
            SFTTREESTYLE_SCROLL |            /* Honor WS_H/VSCROLL */
            WS_HSCROLL | WS_VSCROLL |        /* Vertical and horizontal scrollbars */
            WS_VISIBLE | WS_CHILD,           /* Visible, child window */
            0, 0, 0, 0,                      /* Location */
            hwnd,                            /* Parent window */
            (HMENU) IDC_TREE,                /* Tree control ID */
            g_hInst,                         /* Application instance */
            NULL);
        if (!g_hwndTree)
            return -1;

        /* Resources, such as bitmaps, should be loaded and must remain    */
        /* valid until the tree control is destroyed or no longer uses     */
        /* these.  For example, use DeleteObject to delete any bitmaps.    */

        SftTree_SetShowHeader(g_hwndTree, TRUE);/* Show column headers */
        SftTree_SetItemLines(g_hwndTree, 5); /* (Maximum) number of text lines */
        /* Register the label picture size.  All label pictures    */
        /* used must be the same size.  Only one picture needs to  */
        /* be registered, even if several are used.                */
        Sft_InitPicture(&Pic);
        Sft_SetPictureSizeOnly(&Pic, PIC_SIZEX, PIC_SIZEY);/* Dimensions only for registration */
        SftTree_SetItemLabelPicture(g_hwndTree, -1, &Pic);/* Register the label picture size */
        /* Set individual label bitmaps using the following sample code: */
        // SFT_PICTURE Pic;
        // Sft_InitPicture(&Pic);
        // Sft_SetPictureBitmap(&Pic, a_bitmap_handle);
        // SftTree_SetItemLabelPicture(g_hwndTree, index, &Pic);/* Set a label picture */
        /* Register the item pictures.  These pictures are used    */
        /* for all items in the tree control. All three pictures   */
        /* must be the same size.                                  */
        Sft_InitPicture(&m_aThreeItemPictures[0]);
        Sft_InitPicture(&m_aThreeItemPictures[1]);
        Sft_InitPicture(&m_aThreeItemPictures[2]);
        if (SftTree_GetGDIPlusAvailable(g_hwndTree)) {
            // In this example, we are using GDI+ images.
            // Even though this is a C application, we can embed the images as resources 
            // and use SftTree's SftTree_LoadGDIPlusImageFromResource function to load them
            // from a resource.
            // GDI+ images CANNOT be added as BITMAP resources. They are always added with
            // a custom resource type, in this example we use "PNG".
            m_FolderClosed = SftTree_LoadGDIPlusImageFromResource(g_hInst, TEXT("PNG"), MAKEINTRESOURCE(IDR_FOLDERCLOSED));
            m_FolderOpen = SftTree_LoadGDIPlusImageFromResource(g_hInst, TEXT("PNG"), MAKEINTRESOURCE(IDR_FOLDEROPEN));
            m_FolderLeaf = SftTree_LoadGDIPlusImageFromResource(g_hInst, TEXT("PNG"), MAKEINTRESOURCE(IDR_FOLDERLEAF));
            Sft_SetPictureGDIPlusImage(&m_aThreeItemPictures[0], m_FolderClosed);
            Sft_SetPictureGDIPlusImage(&m_aThreeItemPictures[1], m_FolderOpen);
            Sft_SetPictureGDIPlusImage(&m_aThreeItemPictures[2], m_FolderLeaf);
        } else {
            m_BitmapClosed = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_EXPANDABLE));
            m_BitmapOpen = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_EXPANDED));
            m_BitmapLeaf = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_LEAF));
            Sft_SetPictureBitmap(&m_aThreeItemPictures[0], m_BitmapClosed);/* Expandable picture */
            Sft_SetPictureBitmap(&m_aThreeItemPictures[1], m_BitmapOpen);/* Expanded picture */
            Sft_SetPictureBitmap(&m_aThreeItemPictures[2], m_BitmapLeaf);/* Leaf picture */
        }
        SftTree_SetPictures(g_hwndTree, m_aThreeItemPictures);/* Use item picture */
        /* Override individual item pictures using: */
        // Sft_InitPicture(&m_OtherItemPicture);
        // Sft_SetPictureBitmap(m_OtherItemPicture, LoadBitmap(app_instance, MAKEINTRESOURCE(IDB_your_bitmap)));/* Item picture */
        // SftTree_SetItemPicture(g_hwndTree, index, m_OtherItemPicture);/* Set an item bitmap */
        SftTree_SetItemPictureAlign(g_hwndTree, TRUE);/* Align item bitmaps */
        /* Register the cell picture size.  All cell pictures used */
        /* must be the same size.  Only one picture needs to be    */
        /* registered, even if several are used.                   */
        {
            SFTTREE_CELLINFOPARM CellInfo;
            CellInfo.version = 7;            
            CellInfo.index = -1;             /* Registering picture size */
            Sft_InitPicture(&CellInfo.Cell.CellPicture1);
            Sft_SetPictureSizeOnly(&CellInfo.Cell.CellPicture1, PIC_SIZEX, PIC_SIZEY);/* Dimensions only for registration */
            SftTree_SetCellInfo(g_hwndTree, &CellInfo);/* Register use of cell pictures */
            /* Set individual cell pictures using this sample code: */
            // SFTTREE_CELLINFOPARM CellInfo;
            // CellInfo.version = 7;         
            // CellInfo.index = cell_index_to_change;
            // CellInfo.iCol = column_number_to_change;
            // SftTree_GetCellInfo(g_hwndTree, &CellInfo);
            // /* m_hCellBitmap = LoadBitmap(app_instance, MAKEINTRESOURCE(IDB_your_bitmap)); *//* Cell bitmap */
            // Sft_SetPictureBitmap(&CellInfo.Cell.CellPicture1, m_hCellBitmap);
            // CellInfo.Cell.flag = SFTTREE_BMP_RIGHT;
            // SftTree_SetCellInfo(g_hwndTree, &CellInfo);
        }

        SftTree_SetTreeLineStyle(g_hwndTree, SFTTREE_TREELINE_AUTOMATIC0);/* Dotted tree lines (incl. level 0) */
        SftTree_SetShowButtons(g_hwndTree, TRUE);/* Expand/collapse buttons (level 1..n) */
        SftTree_SetShowButton0(g_hwndTree, TRUE);/* Show expand/collapse buttons (level 0) */
        if (SftTree_GetGDIPlusAvailable(g_hwndTree))
            SftTree_SetButtons(g_hwndTree, SFTTREE_BUTTON_USERDEF);/* User-defined buttons */
        else
            SftTree_SetButtons(g_hwndTree, SFTTREE_BUTTON_AUTOMATIC3);/* Automatic button style 3 */
        SftTree_SetShowGrid(g_hwndTree, TRUE);/* Show grid */
        SftTree_SetGridStyle(g_hwndTree, SFTTREE_GRID_BOTH_DOT);/* Dotted grid lines */
        SftTree_SetShowTruncated(g_hwndTree, TRUE);/* Show ... if truncated */
        SftTree_SetSelectionStyle(g_hwndTree, SFTTREE_SELECTION_ALL | SFTTREE_SELECTION_OUTLINE);/* Select entire item using outline */
        SftTree_SetSelectionArea(g_hwndTree, SFTTREE_SELECTIONAREA_ALLCELLS);/* Selection changes by clicking on an item's cells */
        SftTree_SetFlyby(g_hwndTree, TRUE);  /* Flyby highlighting */
        SftTree_SetUpdateCaretExpandCollapse(g_hwndTree, FALSE);/* don't update caret location when expand/collapse button clicked */
        SftTree_SetScrollTips(g_hwndTree, TRUE);/* Show Scrolltips */
        SftTree_SetInheritBgColor(g_hwndTree, TRUE);/* Inherit background color of first cell */
        SftTree_SetReorderColumns(g_hwndTree, TRUE);/* Column reordering */
        SftTree_SetOpenEnded(g_hwndTree, FALSE);/* Last column width */
        SftTree_SetShowHeaderButtons(g_hwndTree, TRUE);/* Show column header as buttons */

        /* Define control attributes */
        {
            SFTTREE_CONTROL CtrlInfo;
            memset(&CtrlInfo, 0, sizeof(SFTTREE_CONTROL));
            CtrlInfo.cbSize = sizeof(SFTTREE_CONTROL);
            if (!SftTree_GetControlInfo(g_hwndTree, &CtrlInfo))/* Get current settings */
                ; /* Error handling goes here */
            // You need to create a images for at least the ButtonExpanded and ButtonCollapsed button state
            //Sft_SetPictureBitmap(&CtrlInfo.ButtonExpanded, a_bitmap_handle);
            //Sft_SetPictureBitmap(&CtrlInfo.ButtonCollapsed, a_bitmap_handle);
            
            if (SftTree_GetGDIPlusAvailable(g_hwndTree)) {
                // In this example, we are using GDI+ images.
                // Even though this is a C application, we can embed the images as resources 
                // and use SftTree's SftTree_LoadGDIPlusImageFromResource function to load them
                // from a resource.
                // GDI+ images CANNOT be added as BITMAP resources. They are always added with
                // a custom resource type, in this example we use "PNG".
                m_ButtonExpanded = SftTree_LoadGDIPlusImageFromResource(g_hInst, TEXT("PNG"), MAKEINTRESOURCE(IDR_BUTTONEXPANDED));
                m_ButtonExpandedHot = SftTree_LoadGDIPlusImageFromResource(g_hInst, TEXT("PNG"), MAKEINTRESOURCE(IDR_BUTTONEXPANDED_HOT));
                m_ButtonCollapsed = SftTree_LoadGDIPlusImageFromResource(g_hInst, TEXT("PNG"), MAKEINTRESOURCE(IDR_BUTTONCOLLAPSED));
                m_ButtonCollapsedHot = SftTree_LoadGDIPlusImageFromResource(g_hInst, TEXT("PNG"), MAKEINTRESOURCE(IDR_BUTTONCOLLAPSED_HOT));
                Sft_SetPictureGDIPlusImage(&CtrlInfo.ButtonExpanded, m_ButtonExpanded);
                Sft_SetPictureGDIPlusImage(&CtrlInfo.ButtonExpandedHot, m_ButtonExpandedHot);
                Sft_SetPictureGDIPlusImage(&CtrlInfo.ButtonCollapsed, m_ButtonCollapsed);
                Sft_SetPictureGDIPlusImage(&CtrlInfo.ButtonCollapsedHot, m_ButtonCollapsedHot);
            }

            if (!SftTree_SetControlInfo(g_hwndTree, &CtrlInfo))/* Save new settings */
                ; /* Error handling goes here */
        }

        /* Define columns */
        {
            SFTTREE_COLUMN_EX aCol[2] = {
              { 0, 0,                        /* Reserved */
                221,                         /* Width (in pixels) */
                ES_LEFT | SFTTREE_MULTILINE | SFTTREE_TOOLTIP,/* Cell alignment */
                ES_LEFT | SFTTREE_HEADER_UP, /* Title style */
                TEXT("Picture"),             /* Column header title */
                NULL, NULL,                  /* Reserved field and bitmap handle */
                SFTTREE_BMP_RIGHT,           /* Picture alignment */
                0, 0, 0,                     /* Reserved fields */
                SFTTREE_NOCOLOR,             /* Cell background color */
                SFTTREE_NOCOLOR,             /* Cell foreground color */
                SFTTREE_NOCOLOR,             /* Selected cell background color */
                SFTTREE_NOCOLOR,             /* Selected cell foreground color */
                0,                           /* Real column position (set by SetColumns call) */
                0,                           /* Display column number (display position) */
                SFTTREE_COL_MERGE |          /* Column can merge with next */
                SFTTREE_COL_MERGEINTO |      /* Previous column can merge into this column */
                0,                           /* Column flag */
                0,                           /* Minimum column width */
              },                             
              { 0, 0,                        /* Reserved */
                300,                         /* Width (in pixels) */
                ES_LEFT | SFTTREE_MULTILINE | SFTTREE_WRAP | SFTTREE_TOOLTIP,/* Cell alignment */
                ES_LEFT | SFTTREE_HEADER_UP, /* Title style */
                TEXT("Description"),         /* Column header title */
                NULL, NULL,                  /* Reserved field and bitmap handle */
                SFTTREE_BMP_RIGHT,           /* Picture alignment */
                0, 0, 0,                     /* Reserved fields */
                SFTTREE_NOCOLOR,             /* Cell background color */
                SFTTREE_NOCOLOR,             /* Cell foreground color */
                SFTTREE_NOCOLOR,             /* Selected cell background color */
                SFTTREE_NOCOLOR,             /* Selected cell foreground color */
                0,                           /* Real column position (set by SetColumns call) */
                1,                           /* Display column number (display position) */
                SFTTREE_COL_MERGE |          /* Column can merge with next */
                SFTTREE_COL_MERGEINTO |      /* Previous column can merge into this column */
                0,                           /* Column flag */
                0,                           /* Minimum column width */
              }                              
            };
            SftTree_SetColumnsEx(g_hwndTree, 2, aCol);/* Set column attributes */
        }

        /* Use column header pictures.  All pictures used must be  */
        /* the same size.                                          */
        {
            LPSFTTREE_COLUMN_EX lpCol;
            int nCols;
            nCols = SftTree_GetColumnsEx(g_hwndTree, &lpCol);/* Get column attributes */
            Sft_SetPictureSizeOnly(&lpCol[0].Picture1, PIC_SIZEX, PIC_SIZEY);/* Set column header picture size */
            Sft_SetPictureSizeOnly(&lpCol[1].Picture1, PIC_SIZEX, PIC_SIZEY);/* Set column header picture size */
            SftTree_SetColumnsEx(g_hwndTree, nCols, lpCol);/* Set new column attributes */
        }

        SftTree_SetShowRowHeader(g_hwndTree, SFTTREE_ROWSTYLE_BUTTONCOUNT1);/* Row style */
        /* Register the row header picture size.  All row header   */
        /* pictures used must be the same size.  Only one picture  */
        /* needs to be registered, even if several are used.       */
        {
            SFTTREE_ROWINFOPARM RowInfo;
            RowInfo.version = 7;             
            RowInfo.index = -1;
            Sft_InitPicture(&RowInfo.Row.RowPicture1);
            Sft_SetPictureSizeOnly(&RowInfo.Row.RowPicture1, PIC_SIZEX, PIC_SIZEY);
            SftTree_SetRowInfo(g_hwndTree, &RowInfo);
            /* Set individual row header pictures using: */
            // SFTTREE_ROWINFOPARM RowInfo;
            // RowInfo.version = 7;          
            // RowInfo.index = index;
            // SftTree_GetRowInfo(g_hwndTree, &RowInfo);
            // /* m_hRowBitmap = LoadBitmap(app_instance, MAKEINTRESOURCE(IDB_your_bitmap)); *//* Row header picture */
            // Sft_SetPictureBitmap(&RowInfo.Row.RowPicture1, m_hRowBitmap);
            // RowInfo.Row.flag = SFTTREE_BMP_RIGHT;
            // SftTree_SetRowInfo(g_hwndTree, &RowInfo);
        }
        SftTree_SetRowColHeaderText(g_hwndTree, TEXT(""));/* Row/column header text */
        SftTree_SetRowColHeaderStyle(g_hwndTree, ES_LEFT | SFTTREE_HEADER_UP);/* Row/column header style */
        Sft_InitPicture(&Pic);
        Sft_SetPictureSizeOnly(&Pic, PIC_SIZEX, PIC_SIZEY);/* Row/column header picture */
        SftTree_SetRowColHeaderPicture(g_hwndTree, &Pic);/* Row/column picture */
        SftTree_SetRowColHeaderPictureStyle(g_hwndTree, SFTTREE_BMP_RIGHT);/* Row/column picture alignment */
        SftTree_SetCharSearchMode(g_hwndTree, SFTTREE_CHARSEARCH_ALLCHARS, -1);/* Consider all characters typed */
        /* Change the default colors */
        {
            SFTTREE_COLORS Colors;
            SftTree_GetCtlColors(g_hwndTree, &Colors);/* Get current color settings */
            Colors.colorTreeLines = COLOR_3DDKSHADOW | 0x80000000L;/* Tree line color */
            Colors.colorSelBgNoFocus = COLOR_BTNFACE | 0x80000000L;/* Selection background color (no input focus) */
            Colors.colorSelFgNoFocus = COLOR_BTNTEXT | 0x80000000L;/* Selection foreground color (no input focus) */
            SftTree_SetCtlColors(g_hwndTree, &Colors);/* Set new colors */
        }

        /*------------------------------------------------------------------------------*/
        /* Add a few items.                                                             */
        /*------------------------------------------------------------------------------*/

        {
            int index;

            index = SftTree_AddString(g_hwndTree, TEXT("Progress Bars"));
            SftTree_SetTextCol(g_hwndTree, index, 0, TEXT("SftTree/DLL supports progress bars as cell background (partial or full size)."));

            // add progress bar samples
            {
                SFTTREE_CELLINFOPARM CellInfo;

                int i = SftTree_AddString(g_hwndTree, TEXT("Progress Bar - Full Size"));
                SftTree_SetItemLevel(g_hwndTree, i, 1);
                CellInfo.version = 7;
                CellInfo.index = i;
                CellInfo.iCol = 0;
                SftTree_GetCellInfo(g_hwndTree, &CellInfo);
                CellInfo.Cell.progressMax = 100;    // maximum value 0 - 100
                CellInfo.Cell.progressVal = 33;     // current value
                SftTree_SetCellInfo(g_hwndTree, &CellInfo);

                i = SftTree_AddString(g_hwndTree, TEXT("Progress Bar - Partial"));
                SftTree_SetItemLevel(g_hwndTree, i, 1);
                CellInfo.version = 7;
                CellInfo.index = i;
                CellInfo.iCol = 0;
                SftTree_GetCellInfo(g_hwndTree, &CellInfo);
                CellInfo.Cell.flag3 = SFTTREE_CELL_PROGRESSHORIZONTAL|SFTTREE_CELL_PROGRESSSMALL;
                CellInfo.Cell.progressMax = 200;    // maximum value 0 - 200
                CellInfo.Cell.progressVal = 133;    // current value
                SftTree_SetCellInfo(g_hwndTree, &CellInfo);


                i = SftTree_AddString(g_hwndTree, TEXT("Progress Bar - with gradient fill"));
                SftTree_SetItemLevel(g_hwndTree, i, 1);
                CellInfo.version = 7;
                CellInfo.index = i;
                CellInfo.iCol = 0;
                SftTree_GetCellInfo(g_hwndTree, &CellInfo);
                CellInfo.Cell.flag3 = SFTTREE_CELL_PROGRESSHORIZONTAL|SFTTREE_CELL_PROGRESSSMALL;
                CellInfo.Cell.progressMax = 50;    // maximum value 0 - 50
                CellInfo.Cell.progressVal = 40;    // current value
                CellInfo.Cell.colorProgress = RGB(128,128, 0);
                CellInfo.Cell.colorProgressEnd = RGB(255,255, 0);
                SftTree_SetCellInfo(g_hwndTree, &CellInfo);

                i = SftTree_AddString(g_hwndTree, TEXT("Progress Bar - customizable colors"));
                SftTree_SetItemLevel(g_hwndTree, i, 1);
                CellInfo.version = 7;
                CellInfo.index = i;
                CellInfo.iCol = 0;
                SftTree_GetCellInfo(g_hwndTree, &CellInfo);
                CellInfo.Cell.flag3 = SFTTREE_CELL_PROGRESSSMALL|SFTTREE_CELL_PROGRESSVERTICAL|SFTTREE_CELL_BGHORIZONTAL;
                CellInfo.Cell.progressMax = 150;    // maximum value 0 - 150
                CellInfo.Cell.progressVal = 40;    // current value
                CellInfo.Cell.colorProgress = RGB(128,128, 0);
                CellInfo.Cell.colorProgressEnd = RGB(255,255, 0);
                CellInfo.Cell.colorBg = COLOR_WINDOW | 0x80000000L;
                CellInfo.Cell.colorBgEnd = RGB(255,0,0);
                SftTree_SetCellInfo(g_hwndTree, &CellInfo);
            }
           
            index = SftTree_AddString(g_hwndTree, TEXT("Supported Picture Types"));
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("SftTree/DLL supports numerous image types, such as GDI+, bitmaps, icons, ImageLists and also offers numerous built-in images."));

            index = SftTree_AddString(g_hwndTree, TEXT("GDI+ Images"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("All GDI+ images are supported, like GIF, JPEG, Exif, PNG, TIFF and device-independent bitmaps (up to 64bpp) with semi-transparent and translucent areas."));

            if (SftTree_GetGDIPlusAvailable(g_hwndTree)) {

                int i = SftTree_AddString(g_hwndTree, TEXT("PNG Sample with alpha-channel for translucent edges"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                m_PNGImage = SftTree_LoadGDIPlusImageFromResource(g_hInst, TEXT("PNG"), MAKEINTRESOURCE(IDR_WORLD));
                Sft_SetPictureGDIPlusImage(&Pic, m_PNGImage);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);

                i = SftTree_AddString(g_hwndTree, TEXT("Another PNG Sample with alpha-channel for translucent edges"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                m_PNGImage2 = SftTree_LoadGDIPlusImageFromResource(g_hInst, TEXT("PNG"), MAKEINTRESOURCE(IDR_WARN));
                Sft_SetPictureGDIPlusImage(&Pic, m_PNGImage2);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
            }

            index = SftTree_AddString(g_hwndTree, TEXT("Bitmaps"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("Bitmaps can be of varying sizes and also support Bitmap Transparency, which allows the background to show through the image (in areas selected by the bitmap designer)."));

            // add bitmap samples
            {
                int i = SftTree_AddString(g_hwndTree, TEXT("Large Bitmap"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                m_hBitmapLarge = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_LOGO));
                Sft_SetPictureBitmap(&Pic, m_hBitmapLarge);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);

                m_hIconSmall = LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
                i = SftTree_AddString(g_hwndTree, TEXT("Various bitmap sizes"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                m_hBitmapSmall = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_SMILE));
                Sft_SetPictureBitmap(&Pic, m_hBitmapSmall);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
            }

            index = SftTree_AddString(g_hwndTree, TEXT("Icons"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("The supported icons can be stardard size icons (32x32) or any other size supported by the operating system."));

            // add icon samples
            {
                int i = SftTree_AddString(g_hwndTree, TEXT("Standard Icon (32x32)"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureIcon(&Pic, LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON1)));
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);

                i = SftTree_AddString(g_hwndTree, TEXT("Any other size"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureIcon(&Pic, m_hIconSmall);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
            }

            index = SftTree_AddString(g_hwndTree, TEXT("ImageLists"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("Complete ImageList support simplifies bitmap handling and can avoid the limited resource availability on earlier Windows versions."));

            // add imaglist samples
            {
                m_hImgList = ImageList_LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_TOOLBAR), 16, 0, RGB(255,0,0));
                if (m_hImgList) {
                    int c, count = ImageList_GetImageCount(m_hImgList);
                    for (c = 0 ; c < count ; ++c) {
                        TCHAR szBuffer[80];
                        int i;
                        wsprintf(szBuffer, TEXT("Image %d"), c);
                        i = SftTree_AddString(g_hwndTree, szBuffer);
                        SftTree_SetItemLevel(g_hwndTree, i, 2);
                        Sft_SetPictureImageList(&Pic, m_hImgList, (short) c, 0);
                        UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                    }
                }
            }


            index = SftTree_AddString(g_hwndTree, TEXT("Color Samples"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("Using the built-in color sample image, simple color selection can easily be implemented.  Color samples can display all colors available."));

            // add color samples from table
            {
                struct tagColorEntry* pc = aPropListColors;
                for ( ; pc->lpszName ; ++pc) {
                    int i = SftTree_AddString(g_hwndTree, pc->lpszName);
                    SftTree_SetItemLevel(g_hwndTree, i, 2);
                    Sft_SetPictureColorSample(&Pic, PIC_SIZEX_COLORSAMPLE, PIC_SIZEY_COLORSAMPLE, pc->color, 0x80000000L|COLOR_WINDOWTEXT);
                    UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                }
            }

            index = SftTree_AddString(g_hwndTree, TEXT("Predefined (Built-in) Pictures"));
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("Predefined images are available for commonly used items, such as check boxes, radio buttons, sort direction indicators and more..."));

            index = SftTree_AddString(g_hwndTree, TEXT("Check Boxes - Honors Windows Themes"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);

            // add checkbox sample
            {
                int i = SftTree_AddString(g_hwndTree, TEXT("Enabled, Selected Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox(&Pic, 1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled, Selected Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox(&Pic, 1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Enabled Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox(&Pic, 0, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox(&Pic, 0, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
            }

            index = SftTree_AddString(g_hwndTree, TEXT("Check Boxes (3-State) - Honors Windows Themes"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);

            // add checkbox (3-state) sample
            {
                int i = SftTree_AddString(g_hwndTree, TEXT("Enabled, Selected Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox3(&Pic, 1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled, Selected Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox3(&Pic, 1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Enabled Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox3(&Pic, 0, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox3(&Pic, 0, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Enabled, Unknown Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox3(&Pic, -1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled, Unknown Check Box"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureCheckBox3(&Pic, -1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
            }

            index = SftTree_AddString(g_hwndTree, TEXT("Radio Buttons - Honors Windows Themes"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);

            // add radio button sample
            {
                int i = SftTree_AddString(g_hwndTree, TEXT("Enabled, Selected Radio Button"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureRadioButton(&Pic, 1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled, Selected Radio Button"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureRadioButton(&Pic, 1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Enabled Radio Button"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureRadioButton(&Pic, 0, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled Radio Button"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureRadioButton(&Pic, 0, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
            }

            index = SftTree_AddString(g_hwndTree, TEXT("Up/Down Buttons - Honors Windows Themes"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);

            // add up/down button sample
            {
                int i = SftTree_AddString(g_hwndTree, TEXT("Enabled Up Button"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureUpDown(&Pic, 1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled Up Button"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureUpDown(&Pic, 1, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Enabled Down Button"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureUpDown(&Pic, 0, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled Down Button"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureUpDown(&Pic, 0, PIC_SIZEX_CHECKBOX, PIC_SIZEY_CHECKBOX, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
            }

            index = SftTree_AddString(g_hwndTree, TEXT("Sort Direction Indicator"));
            SftTree_SetItemLevel(g_hwndTree, index, 1);

            // add sort direction indicator sample
            {
                int i = SftTree_AddString(g_hwndTree, TEXT("Enabled Ascending Indicator"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureUpDownSort(&Pic, 1, PIC_SIZEX_SORT, PIC_SIZEY_SORT, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled Ascending Indicator"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureUpDownSort(&Pic, 1, PIC_SIZEX_SORT, PIC_SIZEY_SORT, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Enabled Descending Indicator"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureUpDownSort(&Pic, 0, PIC_SIZEX_SORT, PIC_SIZEY_SORT, TRUE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
                i = SftTree_AddString(g_hwndTree, TEXT("Disabled Descending Indicator"));
                SftTree_SetItemLevel(g_hwndTree, i, 2);
                Sft_SetPictureUpDownSort(&Pic, 0, PIC_SIZEX_SORT, PIC_SIZEY_SORT, FALSE);
                UpdatePictures(g_hwndTree, i, &Pic, SFTTREE_BMP_RIGHT);
            }

        }
    
        /*------------------------------------------------------------------------------*/
        /* Once ALL TREE CONTROL ITEMS HAVE BEEN ADDED, you can set additional tree     */
        /* control attributes.                                                          */
        /*------------------------------------------------------------------------------*/

        /* Make row header width optimal, so text and pictures are */
        /* not clipped horizontally.                               */
        SftTree_MakeRowHeaderOptimal(g_hwndTree);/* Make row header width optimal */

        SftTree_MakeColumnOptimal(g_hwndTree, 0);/* Only make the first column optimal */
        SftTree_RecalcHorizontalExtent(g_hwndTree);/* Update horizontal scroll bar */

        SftTree_SetCaretIndex(g_hwndTree, 0);
        SftTree_SetCurSel(g_hwndTree, 0);
        CopyPictureFromCurrentItem(g_hwndTree);

        // Set a timer so we can update our progress bars every once in a while
        SetTimer(hwnd, TIMERID, 333, NULL);
        return 0;
     }
    case WM_DESTROY:
        KillTimer(hwnd, TIMERID);

        if (m_ButtonExpanded)
            SftTree_FreeGDIPlusImageLoadedFromResource(m_ButtonExpanded);
        if (m_ButtonExpandedHot)
            SftTree_FreeGDIPlusImageLoadedFromResource(m_ButtonExpandedHot);
        if (m_ButtonCollapsed)
            SftTree_FreeGDIPlusImageLoadedFromResource(m_ButtonCollapsed);
        if (m_ButtonCollapsedHot)
            SftTree_FreeGDIPlusImageLoadedFromResource(m_ButtonCollapsedHot);
        if (m_FolderClosed)
            SftTree_FreeGDIPlusImageLoadedFromResource(m_FolderClosed);
        if (m_FolderOpen)
            SftTree_FreeGDIPlusImageLoadedFromResource(m_FolderOpen);
        if (m_FolderLeaf)
            SftTree_FreeGDIPlusImageLoadedFromResource(m_FolderLeaf);

        if (m_PNGImage)
            SftTree_FreeGDIPlusImageLoadedFromResource(m_PNGImage);
        if (m_PNGImage2)
            SftTree_FreeGDIPlusImageLoadedFromResource(m_PNGImage2);

        if (m_BitmapClosed)
            DeleteObject(m_BitmapClosed);       /* Default item pictures */
        if (m_BitmapOpen)
            DeleteObject(m_BitmapOpen);
        if (m_BitmapLeaf)
            DeleteObject(m_BitmapLeaf);
        //DeleteObject(m_OtherItemPicture.Picture.hBitmap);/* Another item picture */
        if (m_hIconSmall)
            DestroyIcon(m_hIconSmall);
        if (m_hBitmapLarge)
            DeleteObject(m_hBitmapLarge);
        if (m_hBitmapSmall)
            DeleteObject(m_hBitmapSmall);
        if (m_hImgList)
            ImageList_Destroy(m_hImgList);
        
        if (g_hwndTree)
            DestroyWindow(g_hwndTree);
        PostQuitMessage(0);
        break;

    case WM_SIZE: {
        int cx = LOWORD(lParam);
        int cy = HIWORD(lParam);
        SetWindowPos(g_hwndTree, NULL, 0, 0, cx, cy, SWP_NOACTIVATE | SWP_NOZORDER);
        return 0;
     }

    case WM_TIMER: {
        // update all cells that have a progress bar by incrementing the progress value
        // we know that only the first few items can have a progress bar, so we only scan
        // the first dozen items.
        int items = min(12, SftTree_GetCount(g_hwndTree));
        int nCols = SftTree_GetColumns(g_hwndTree, NULL);
        int item; 
        for (item = 0 ; item < items ; ++item) {
            int col;
            for (col = 0 ; col < nCols ; ++col) {
                SFTTREE_CELLINFOPARM CellInfo;
                CellInfo.version = 7;
                CellInfo.index = item;
                CellInfo.iCol = col;
                SftTree_GetCellInfo(g_hwndTree, &CellInfo);
                if (CellInfo.Cell.progressMax > 0) {
                    CellInfo.Cell.progressVal = (CellInfo.Cell.progressVal+4) % CellInfo.Cell.progressMax;
                    SftTree_SetCellInfo(g_hwndTree, &CellInfo);
                }
            }
        }
        break;
     }

    case WM_SETFOCUS:
        if (g_hwndTree)
            SetFocus(g_hwndTree);
        break;

    case WM_COMMAND: {
        HWND hwndCtl = (HWND) lParam;
        int id = LOWORD(wParam);
        int code = HIWORD(wParam);

            switch (id) {
            case IDC_TREE:
                switch(code) {
                case SFTTREEN_LBUTTONDBLCLK_TEXT:
                case SFTTREEN_LBUTTONDOWN_BUTTON:
                case SFTTREEN_LBUTTONDBLCLK_BUTTON: {
                    int index;
                    BOOL fExpand, fControl;
                    /* Get current position */
                    index = SftTree_GetExpandCollapseIndex(hwndCtl);/* Get caret location */
                    /* Check if item is expanded */
                    fExpand = SftTree_GetItemExpand(hwndCtl, index);
                    /* If the CONTROL key is pressed, expand all dependent levels */
                    fControl = (BOOL)(GetKeyState(VK_CONTROL)&0x8000);
                    if (fExpand)
                        SftTree_Collapse(hwndCtl, index, TRUE);
                    else
                        SftTree_Expand(hwndCtl, index, TRUE, fControl);
                    break;
                 }
                case SFTTREEN_EXPANDALL: { // expand all
                    int index;
                    index = SftTree_GetExpandCollapseIndex(hwndCtl);/* Get item to expand/collapse */
                    SftTree_Expand(hwndCtl, index, TRUE, TRUE);
                    break;
                 }
                case SFTTREEN_LBUTTONDBLCLK_COLUMNRES: {
                    /* Resize column optimally */
                    int realCol = SftTree_GetResizeColumn(g_hwndTree);
                    if (realCol >= 0) {
                        SftTree_MakeColumnOptimal(g_hwndTree, realCol);/* Make column width optimal */
                        SftTree_RecalcHorizontalExtent(g_hwndTree);/* Update horizontal scroll bar */
                    }
                    break;
                  }
                case SFTTREEN_SELCHANGE:
                    CopyPictureFromCurrentItem(g_hwndTree);
                    break;

                case SFTTREEN_LBUTTONDOWN_ITEM:
                case SFTTREEN_LBUTTONDBLCLK_ITEM:
                    ToggleItemPicture(g_hwndTree, SftTree_GetCaretIndex(g_hwndTree));
                    break;
                case SFTTREEN_LBUTTONDOWN_CELLBMP:
                case SFTTREEN_LBUTTONDBLCLK_CELLBMP:
                    ToggleCellPicture(g_hwndTree, SftTree_GetCaretIndex(g_hwndTree));
                    break;

                case SFTTREEN_LBUTTONDOWN_COLUMN_HEADER:
                case SFTTREEN_LBUTTONDBLCLK_COLUMN_HEADER:
                    if (SftTree_GetHeaderButton(g_hwndTree) == 0) // sort column 0
                        SetSortDirection(g_hwndTree, !g_fAscending);
                    break;
                }
                break;
                

            case IDM_EXIT:                  // Menu command, Exit
                DestroyWindow(hwnd);
                break;
            }
        }
        break;
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

/**********************************************************************/
/*                              WinMain                               */
/**********************************************************************/

int PASCAL WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int cmdShow)
{
    MSG msg;
    HWND hwndMain;

    // Initialize 
    g_hInst = hinst;

    if (!hinstPrev) {
        WNDCLASS cls;

        cls.hCursor         = LoadCursor(NULL, IDC_ARROW);
        cls.hIcon           = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON1));
        cls.lpszMenuName    = MAKEINTRESOURCE(IDR_MAINMENU);
        cls.hInstance       = g_hInst;
        cls.lpszClassName   = TEXT("SoftelSampleFrame");
        cls.hbrBackground   = (HBRUSH)(COLOR_WINDOW+1);
        cls.lpfnWndProc     = (WNDPROC) SDI_WndProc;
        cls.style           = CS_DBLCLKS;
        cls.cbWndExtra      = 0;
        cls.cbClsExtra      = 0;
        if (!RegisterClass(&cls))
            return 0;
    }

    SftTree_RegisterApp(hinst);   /* Register with SftTree/DLL */

    // Initialize, run, and terminate the application
    hwndMain = CreateWindowEx(
            0L,
            TEXT("SoftelSampleFrame"),
            TEXT("Softel vdm, Inc. - Pictures Sample"),
            WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
            CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT,
            NULL,
            NULL,
            g_hInst,
            NULL);
    if (!hwndMain)
        return 0;

    ShowWindow(hwndMain, cmdShow);
    UpdateWindow(hwndMain);

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    SftTree_UnregisterApp(hinst); /* Unregister from SftTree/DLL */

    return (int) msg.wParam;
}