How do I detect which element of a TreeView was clicked on?

88 Views Asked by At

I'm trying to use the HTREEITEM common control in Windows, while checking for the WM_NOTIFY to see when the user clicks on it.

The problem is I can't figure out which item was clicked on.

1

There are 1 best solutions below

0
Junjie Zhu - MSFT On

My test code for your reference, a simple test.

#define ID_TREEVIEW  555

HTREEITEM AddItemToTree(HWND hwndTV, LPTSTR lpszItem, int nLevel)
{
    TVITEM tvi;
    TVINSERTSTRUCT tvins;
    static HTREEITEM hPrev = (HTREEITEM)TVI_FIRST;
    static HTREEITEM hPrevRootItem = NULL;
    static HTREEITEM hPrevLev2Item = NULL;
    HTREEITEM hti;

    tvi.mask = TVIF_TEXT | TVIF_IMAGE
        | TVIF_SELECTEDIMAGE | TVIF_PARAM;

    // Set the text of the item. 
    tvi.pszText = lpszItem;
    tvi.cchTextMax = sizeof(tvi.pszText) / sizeof(tvi.pszText[0]);

    // Assume the item is not a parent item, so give it a 
    // document image. 
  //  tvi.iImage = g_nDocument;
    //tvi.iSelectedImage = g_nDocument;

    // Save the heading level in the item's application-defined 
    // data area. 
    tvi.lParam = (LPARAM)nLevel;
    tvins.item = tvi;
    tvins.hInsertAfter = hPrev;

    // Set the parent item based on the specified level. 
    if (nLevel == 1)
        tvins.hParent = TVI_ROOT;
    else if (nLevel == 2)
        tvins.hParent = hPrevRootItem;
    else
        tvins.hParent = hPrevLev2Item;

    // Add the item to the tree-view control. 
    hPrev = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM,
        0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);

    if (hPrev == NULL)
        return NULL;

    // Save the handle to the item. 
    if (nLevel == 1)
        hPrevRootItem = hPrev;
    else if (nLevel == 2)
        hPrevLev2Item = hPrev;

    // The new item is a child item. Give the parent item a 
    // closed folder bitmap to indicate it now has child items. 
    if (nLevel > 1)
    {
        hti = TreeView_GetParent(hwndTV, hPrev);
        tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
        tvi.hItem = hti;
       // tvi.iImage = g_nClosed;
       // tvi.iSelectedImage = g_nClosed;
        TreeView_SetItem(hwndTV, &tvi);
    }

    return hPrev;
}
  
HWND hwndTV = NULL;
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   hwndTV = CreateWindowEx(0, WC_TREEVIEW, TEXT("Tree View"),
       WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT,
       0, 0, 200, 200, hWnd, (HMENU)ID_TREEVIEW, hInst, NULL);

  // Associate an image list with the control.
  // HIMAGELIST hImageList = CreateImageList(hwndTV);
  // TreeView_SetImageList(hwndTV, hImageList, TVSIL_NORMAL);

   // Add items to the control.

   wchar_t lpWStr[32] = { 0 };
   wsprintfW(lpWStr, L"Root");
   HTREEITEM hRoot = AddItemToTree(hwndTV, lpWStr, 0);

   wsprintfW(lpWStr, L"Child");
   HTREEITEM hChild = AddItemToTree(hwndTV, lpWStr, 1);

   wsprintfW(lpWStr, L"Grandchild");
   HTREEITEM hGrandchild = AddItemToTree(hwndTV, lpWStr, 2);

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_NOTIFY:
    {
        LPNMHDR lpnm = (LPNMHDR)lParam; // Get the notification header
        if (lpnm->idFrom == ID_TREEVIEW && lpnm->code == TVN_SELCHANGED) // Check if the notification is from the tree view and the selection has changed
        {
            LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam; // Get the tree view notification structure
            HTREEITEM hItem = pnmtv->itemNew.hItem; // Get the handle of the newly selected item
            TVITEM tvi; // Declare a TVITEM structure to get the item information
            tvi.mask = TVIF_TEXT | TVIF_PARAM; // Specify the mask to get the text and the parameter of the item
            tvi.hItem = hItem; /
            LPWSTR szBuffer = new wchar_t[256];
            tvi.pszText = szBuffer; // Set the buffer to receive the item text
            tvi.cchTextMax = 256; 
            TreeView_GetItem(hwndTV, &tvi); 
            MessageBox(hWnd, tvi.pszText, TEXT("Selected Item"), MB_OK); 
        }
        break;

    }
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Parse the menu selections:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: Add any drawing code that uses hdc here...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}