Hide

SftTree/DLL 7.5 - Tree Control

Display
Print

OwnerDraw Sample (C)

This sample illustrates owner-draw cells and column headers.

The source code is located at C:\Program Files (x86)\Softelvdm\SftTree DLL 7.5\Samples\C\OwnerDraw\OwnerDraw.c or C:\Program Files\Softelvdm\SftTree DLL 7.5\Samples\C\OwnerDraw\OwnerDraw.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>

// If the following cause compile errors, you will have to update your
// Microsoft Windows Platform SDK, as these files are fairly recent for 
// Windows Themes support.
// If you're using an older version you may have to use #include <vssym32.h> instead of #include <tmschema.h>
#include <uxtheme.h>
//#include <tmschema.h>                    /* Theme support - XP */
#include <vssym32.h>                       /* Theme support */

#pragma comment(lib, "uxtheme.lib")

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

#include "resource.h"                    // resource IDs

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

#define IDC_TREE    100                 /* Tree control ID */

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

HFONT g_hFontVertical;                  /* Vertical font */
HBITMAP g_hBitmap;                      /* Sample bitmap */

// 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 */

BOOL CALLBACK Tree_OwnerDrawCallback(HWND hwnd, LPSFTTREE_OWNERDRAW lpInfo, SFTTREE_DWORD_PTR UserData);

/**********************************************************************/
/*                          Frame Window Proc                         */
/**********************************************************************/

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

    case WM_CREATE: {
        int i;

        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 */
        /* 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]);
        Sft_SetPictureBitmap(&m_aThreeItemPictures[0], LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_EXPANDABLE)));/* Expandable picture */
        Sft_SetPictureBitmap(&m_aThreeItemPictures[1], LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_EXPANDED)));/* Expanded picture */
        Sft_SetPictureBitmap(&m_aThreeItemPictures[2], LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_LEAF)));/* 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 */
        SftTree_SetTreeLineStyle(g_hwndTree, SFTTREE_TREELINE_AUTOMATIC0);/* Dotted or invisible 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) */
        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_CELL1 | SFTTREE_SELECTION_OUTLINE);/* Select first cell only 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, TRUE);/* Last column width */
        SftTree_SetShowHeaderButtons(g_hwndTree, TRUE);/* Show column header as buttons */

        /* Define columns */
        {
            SFTTREE_COLUMN_EX aCol[3] = {
              { 0, 0,                        /* Reserved */
                221,                         /* Width (in pixels) */
                ES_LEFT | SFTTREE_TOOLTIP,   /* Cell alignment */
                ES_LEFT | SFTTREE_HEADER_UP, /* Title style */
                TEXT("Vertical Titles"),     /* 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) */
                0,                           /* Column flag */
                0,                           /* Minimum column width */
              },                             
              { 0, 0,                        /* Reserved */
                253,                         /* Width (in pixels) */
                ES_LEFT | SFTTREE_TOOLTIP,   /* Cell alignment */
                ES_LEFT | SFTTREE_HEADER_UP, /* Title style */
                TEXT("Second Column"),       /* 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) */
                0,                           /* Column flag */
                0,                           /* Minimum column width */
              },                             
              { 0, 0,                        /* Reserved */
                100,                         /* Width (in pixels) */
                ES_LEFT | SFTTREE_TOOLTIP,   /* Cell alignment */
                ES_LEFT | SFTTREE_HEADER_UP, /* Title style */
                TEXT("Third Column"),        /* 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) */
                2,                           /* Display column number (display position) */
                0,                           /* Column flag */
                0,                           /* Minimum column width */
              }                              
            };
            SftTree_SetColumnsEx(g_hwndTree, 3, aCol);/* Set column attributes */
        }

        SftTree_SetShowRowHeader(g_hwndTree, SFTTREE_ROWSTYLE_BUTTONCOUNT1);/* Row style */
        SftTree_SetRowColHeaderText(g_hwndTree, TEXT("?"));/* Row/column header text */
        SftTree_SetRowColHeaderStyle(g_hwndTree, ES_LEFT | SFTTREE_HEADER_UP);/* Row/column header style */
        SftTree_SetRowColHeaderPictureStyle(g_hwndTree, SFTTREE_BMP_RIGHT);/* Row/column picture alignment */
        SftTree_SetCharSearchMode(g_hwndTree, SFTTREE_CHARSEARCH_ALLCHARS, -1);/* Consider all characters typed */
        /* Use an ownerdraw callback routine */
        {
            SFTTREE_OWNERDRAWPARM Parm;      /* Parameter list */
            Parm.lpfnOwnerDrawProc = (LPFNSFTTREE_OWNERDRAWPROC) Tree_OwnerDrawCallback;/* User supplied drawing routine */
            Parm.OwnerDrawUserData = (SFTTREE_DWORD_PTR)0;/* User supplied data */
            SftTree_SetOwnerDrawCallback(g_hwndTree, &Parm);
        }
        /* 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.                                                             */
        /*------------------------------------------------------------------------------*/

        for (i = 0 ; i < 50 ; ++i) {
            int index;

            index = SftTree_AddString(g_hwndTree, TEXT("An item"));/* Add an item */
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("2nd Column"));/* Set text in next column */
            SftTree_SetTextCol(g_hwndTree, index, 2, TEXT("3nd Column"));/* Set text in next column */
            index = SftTree_AddString(g_hwndTree, TEXT("Another item"));/* Add another item */
            SftTree_SetItemLevel(g_hwndTree, index, 1);/* change level */
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("2nd Column"));/* Set text in next column */
            SftTree_SetTextCol(g_hwndTree, index, 2, TEXT("3nd Column"));/* Set text in next column */
            /* Set an item's row header text using: */
            SftTree_SetRowText(g_hwndTree, index, TEXT("?"));/* Row header text */

            index = SftTree_AddString(g_hwndTree, TEXT("A third item"));/* Add another item */
            SftTree_SetItemLevel(g_hwndTree, index, 2);/* change level */
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("2nd Column"));/* Set text in next column */
            SftTree_SetTextCol(g_hwndTree, index, 2, TEXT("3nd Column"));/* Set text in next column */
            index = SftTree_AddString(g_hwndTree, TEXT("A fourth item"));/* Add another item */
            SftTree_SetItemLevel(g_hwndTree, index, 1);/* change level */
            SftTree_SetTextCol(g_hwndTree, index, 1, TEXT("2nd Column"));/* Set text in next column */
            SftTree_SetTextCol(g_hwndTree, index, 2, TEXT("3nd Column"));/* Set text in next column */

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

        /* Make all column widths optimal, so text and pictures    */
        /* are not clipped horizontally.                           */
        SftTree_MakeColumnOptimal(g_hwndTree, -1);/* Make column widths optimal */

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

        SftTree_SetCurSel(g_hwndTree, 4); // select the 4th item
        SftTree_SetCaretIndex(g_hwndTree, 4); // and make it current
        SftTree_SetTopIndex(g_hwndTree, 0); // show the first item

        return 0;
     }
    case WM_DESTROY:
        DeleteObject(m_aThreeItemPictures[0].Picture.hBitmap);/* Default item pictures */
        DeleteObject(m_aThreeItemPictures[1].Picture.hBitmap);
        DeleteObject(m_aThreeItemPictures[2].Picture.hBitmap);
        //DeleteObject(m_OtherItemPicture.Picture.hBitmap);/* Another item picture */

        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_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;
              }
            }
            break;

        case 1000:                      // 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;
    }

    // create a vertical font
    {
        LOGFONT lf;

        HFONT hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
        GetObject(hFont, sizeof(LOGFONT), &lf);
        lf.lfEscapement = 900;
        lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
        lf.lfCharSet = DEFAULT_CHARSET;
        lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
        lf.lfQuality = DEFAULT_QUALITY;
        lf.lfPitchAndFamily = FF_DONTCARE;
        lstrcpy(lf.lfFaceName, TEXT("Arial"));

        g_hFontVertical = CreateFontIndirect(&lf);
    }

    // load sample bitmap
    g_hBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_LOGO));

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

    // Initialize, run, and terminate the application
    hwndMain = CreateWindowEx(
            0L,
            TEXT("SoftelSampleFrame"),
            TEXT("Softel vdm, Inc. - OwnerDraw 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);
    }

    DeleteObject(g_hBitmap);
    DeleteObject(g_hFontVertical);

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

    return (int) msg.wParam;
}

/**********************************************************************/
/*                         Ownerdraw Callback                         */
/**********************************************************************/

static void OwnerDraw_Column_Header(HWND hwndTree, LPSFTTREE_OWNERDRAW lpInfo, SFTTREE_DWORD_PTR UserData)
{
    // This function paints the column header using a vertical font
    // it even takes themes into consideration, so it's a bit more complicated
    // than the average application.

    // get general information about tree control and columns
    LPSFTTREE_COLUMN_EX lpCol;
    int nCols = SftTree_GetColumnsEx(hwndTree, &lpCol);/* Get column attributes */ 

    // calculate the text size
    RECT rect, textRect;
    int len = lstrlen(lpCol[lpInfo->col].lpszTitle); // column title
    COLORREF clrFg = SetTextColor(lpInfo->hDC, GetSysColor(COLOR_BTNTEXT));
    int mode = SetBkMode(lpInfo->hDC, TRANSPARENT);

    HFONT hOldFont = (HFONT) SelectObject(lpInfo->hDC, g_hFontVertical);

    SetRectEmpty(&rect);
    DrawText(lpInfo->hDC, lpCol[lpInfo->col].lpszTitle, len, &rect, DT_CALCRECT|DT_LEFT);
    SetRect(&textRect, rect.top, rect.left, rect.bottom, rect.right);

    if (lpInfo->style == SFTTREE_OD_CALC) {
        // we need to return just the size of the header we want to paint
        rect = textRect;
        if (lpInfo->fThemed) {
            // Windows themes are used
            RECT extentRect;
            GetThemeBackgroundExtent(lpInfo->hThemeHeader, lpInfo->hDC, HP_HEADERITEM, HIS_NORMAL, &rect, &extentRect);
            rect = extentRect;
            InflateRect(&rect, 3, 6); // leave a slight gap
        } else {
            // No windows themes
            InflateRect(&rect, 4, 4); // leave a slight gap
        }
        lpInfo->DrawRect.bottom = rect.bottom-rect.top;
        lpInfo->DrawRect.right = rect.right-rect.left;
    } else {
        // we need to paint the header
        int xOffs, yOffs;
        if (lpInfo->fThemed) {
            // Windows themes are used
            int iPartId = HP_HEADERITEM;
            int iStateId = HIS_NORMAL;
            if (lpInfo->fSelected)
                iStateId = HIS_PRESSED;
            if (lpInfo->fFlyby)
                iStateId = HIS_HOT;
            DrawThemeBackground(lpInfo->hThemeHeader, lpInfo->hDC, iPartId, iStateId, &lpInfo->DrawRect, &lpInfo->DrawRect);
            GetThemeBackgroundContentRect(lpInfo->hThemeHeader, lpInfo->hDC, iPartId, iStateId, &lpInfo->DrawRect, &rect);
        } else {
            // No windows themes
            DrawFrameControl(lpInfo->hDC, &lpInfo->DrawRect, DFC_BUTTON, DFCS_BUTTONPUSH | (lpInfo->fSelected ? DFCS_PUSHED : 0));
            rect = lpInfo->DrawRect;
        }
        xOffs = max(0, ((lpInfo->DrawRect.right-lpInfo->DrawRect.left) - (textRect.right-textRect.left))/2);
        yOffs = max(0, ((lpInfo->DrawRect.bottom-lpInfo->DrawRect.top) - (textRect.bottom-textRect.top))/2);
        if (lpInfo->fSelected) {
            xOffs++;
            yOffs--;
        }
        ExtTextOut(lpInfo->hDC, lpInfo->DrawRect.left+xOffs, lpInfo->DrawRect.bottom-yOffs, 0, &lpInfo->DrawRect, lpCol[lpInfo->col].lpszTitle, len, NULL);
    }
    SelectObject(lpInfo->hDC, hOldFont);

    SetBkMode(lpInfo->hDC, mode);
    SetTextColor(lpInfo->hDC, clrFg);
}

static void OwnerDraw_Cell_Bitmap(HWND hwndTree, LPSFTTREE_OWNERDRAW lpInfo, SFTTREE_DWORD_PTR UserData)
{
    RECT rect;
    BITMAP bm;

    HDC hDCTemp = CreateCompatibleDC(lpInfo->hDC);
    HBITMAP hOldBitmap = (HBITMAP) SelectObject(hDCTemp, g_hBitmap);   // Select the bitmap

    GetObject(g_hBitmap, sizeof(BITMAP), &bm);
    SetRect(&rect, 0, 0, bm.bmWidth, bm.bmHeight);

    if (lpInfo->style == SFTTREE_OD_CALC) {
        // we need to return just the size of the cell we want to paint
        lpInfo->DrawRect = rect;
    } else {
        // we need to paint the cell
        FillRect(lpInfo->hDC, &lpInfo->DrawRect, (HBRUSH) (COLOR_WINDOW+1));
        BitBlt(lpInfo->hDC, lpInfo->DrawRect.left, lpInfo->DrawRect.top, lpInfo->DrawRect.right-lpInfo->DrawRect.left, lpInfo->DrawRect.bottom-lpInfo->DrawRect.top, 
            hDCTemp, 0, 0, SRCCOPY);
    }

    SelectObject(hDCTemp, hOldBitmap);
    DeleteDC(hDCTemp);
}

static void OwnerDraw_Cell_Text(HWND hwndTree, LPSFTTREE_OWNERDRAW lpInfo, SFTTREE_DWORD_PTR UserData)
{
    TCHAR szText[1000];
    HFONT hFont, hOldFont;

    hFont = (HFONT) SendMessage(lpInfo->hwndCtl, WM_GETFONT, 0, 0);
    hOldFont = (HFONT) SelectObject(lpInfo->hDC, hFont);

    SftTree_GetTextCol(lpInfo->hwndCtl, lpInfo->index, lpInfo->col, szText); // retrieve the cell text

    if (lpInfo->style == SFTTREE_OD_CALC) {
        // we need to return just the size of the cell we want to paint
        RECT r;
        SetRectEmpty(&r);
        DrawText(lpInfo->hDC, szText, -1, &r, DT_CALCRECT | DT_LEFT | DT_SINGLELINE);
        InflateRect(&r, lpInfo->gap/2, 0); 
        lpInfo->DrawRect = r;
    } else {
        // we need to paint the cell
        RECT r;
        FillRect(lpInfo->hDC, &lpInfo->DrawRect, (HBRUSH) (COLOR_3DFACE+1));
        if (lpInfo->fSelected)
            SftTree_DrawSelectionOutline(lpInfo->hwndCtl, lpInfo->hDC, &lpInfo->DrawRect, RGB(128,0,0), RGB(255,100,100), RGB(255,255,255), RGB(255,0,0));
        r = lpInfo->DrawRect;
        InflateRect(&r, -lpInfo->gap/2, 0);
        DrawText(lpInfo->hDC, szText, -1, &r, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    }

    SelectObject(lpInfo->hDC, hOldFont);
}

BOOL CALLBACK Tree_OwnerDrawCallback(HWND hwnd, LPSFTTREE_OWNERDRAW lpInfo, SFTTREE_DWORD_PTR UserData)
{
    if (lpInfo->itemType == SFTTREE_OD_COLHEADER) {
        OwnerDraw_Column_Header(hwnd, lpInfo, UserData);
        return TRUE;
    }
    if ((lpInfo->itemType == SFTTREE_OD_CELL || lpInfo->itemType == SFTTREE_OD_CELLTOOLTIP) && lpInfo->col == 1) {
        if ((lpInfo->index % 5) == 0) {
            OwnerDraw_Cell_Bitmap(hwnd, lpInfo, UserData);
            return TRUE;
        } else if ((lpInfo->index % 4) == 0) {
            OwnerDraw_Cell_Text(hwnd, lpInfo, UserData);
            return TRUE;
        }
    }
    return FALSE;
}