Treeview Control Example

To create a Tab control specify WC_TREEVIEW as the window class and register the class by specifying the ICC_LISTVIEW_CLASSES bit flag in the accompanying INITCOMMONCONTROLSEX structure.

// treeview control demo
#include <windows.h>
#include <commctrl.h>
#define ID_TREEVIEW 1
#define ID_CREATEBUTTON 2
#define ID_DELETEBUTTON 3
#define ID_EDITBOX 4
#pragma comment(lib, "comctl32.lib")
HWND hwndEdit,hwndTV;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void CreateControls(HWND hwnd);
void addnode();

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow) {

HWND hwnd;
MSG msg ;
WNDCLASS wc = {0};
wc.lpszClassName = TEXT("myWindowClass");
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0,IDC_ARROW);

RegisterClass(&wc);
hwnd = CreateWindow(wc.lpszClassName, TEXT("Treeview control"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 550, 200, 0, 0, hInstance, 0);

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

return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
// load common control class ICC_LISTVIEW_CLASSES from the dynamic-link library (DLL).
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);

RECT rcClient;
GetClientRect(hwnd, &rcClient);
//create child windows
hwndTV = CreateWindowEx(0, WC_TREEVIEW, TEXT("Tree View"), WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES |TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS, 10, 10, rcClient.right-50, rcClient.bottom-50, hwnd, (HMENU) ID_TREEVIEW, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
hwndEdit =CreateWindow(TEXT("edit"), NULL,WS_CHILD | WS_VISIBLE | WS_BORDER,290, rcClient.bottom-30, 120, 25, hwnd, (HMENU) ID_EDITBOX,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);//edit control
CreateWindow(TEXT("button"), TEXT("Add Child"),WS_CHILD | WS_VISIBLE, 20, rcClient.bottom-30,120, 25, hwnd, (HMENU) ID_CREATEBUTTON , (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
CreateWindow(TEXT("button"), TEXT("Delete Selected"),WS_CHILD | WS_VISIBLE, 150, rcClient.bottom-30, 120, 25, hwnd, (HMENU) ID_DELETEBUTTON , (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);

addnode();
break;

case WM_COMMAND:
//respond to button click
if (HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
//create button click
case ID_CREATEBUTTON:
HTREEITEM tvIte;
tvIte = TreeView_GetSelection(hwndTV);
addnode();
break;
//delete button click
case ID_DELETEBUTTON:
tvIte = TreeView_GetSelection(hwndTV);
if (tvIte)
{
SendDlgItemMessage(hwnd,ID_TREEVIEW, TVM_DELETEITEM,TVGN_CARET,(LPARAM)tvIte);
SetFocus(hwndTV);
}
break;
}
}
break;

case WM_NOTIFY:
{
//Contains information about a tree view notification message.
NMTREEVIEW *nmptr=(LPNMTREEVIEW)lParam;
if(((LPNMHDR)lParam)->code == NM_DBLCLK)
{
//respond to double click
}
if (nmptr->hdr.code==TVN_SELCHANGED)
{
//respond to treeview selection change
}
}
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}

return DefWindowProc(hwnd, msg, wParam, lParam);
}

//add node to tree view
void addnode()
{
HTREEITEM tvIte;
TV_INSERTSTRUCT tvinsert;
TVITEM tvi;
tvinsert.item.mask=TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
tvi.mask= TVIF_TEXT | TVIF_PARAM;
int totalnodes= TreeView_GetCount(hwndTV);
//check if treeview is empty and if so add root node
if (totalnodes==0)
{
tvinsert.hParent=TVI_ROOT;
tvinsert.item.pszText=TEXT("root");
}
//if treeview not empty add new node using name specified in textbox
else
{
TCHAR textvalue[10]=TEXT("\0");
GetWindowText(hwndEdit, textvalue, 10);
int stringlength=lstrlen(textvalue);
if (stringlength>0)
{
tvIte = TreeView_GetSelection(hwndTV);
tvinsert.hParent=tvIte;
tvinsert.hInsertAfter=TVI_LAST;
tvinsert.item.pszText=textvalue;
}

}
TreeView_InsertItem(hwndTV ,(LPARAM)&tvinsert);
SetFocus(hwndTV);
}