首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用TreeView展开TreeView_Expand项

无法使用TreeView展开TreeView_Expand项
EN

Stack Overflow用户
提问于 2014-05-27 11:18:54
回答 1查看 839关注 0票数 3

我想让TreeView的项目在项目展开时动态地创建它的子项目。根据http://support.microsoft.com/kb/130697,我编写了以下代码:

代码语言:javascript
复制
#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include <windowsx.h>
#include <CommCtrl.h>

#pragma comment(lib, "ComCtl32.Lib")
#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL MainWindow_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct);
void MainWindow_OnDestroy(HWND hWnd);
void MainWindow_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify);
LRESULT MainWindow_OnNotify(HWND hWnd, int idFrom, NMHDR *pnmhdr);

#define ID_TREEVIEW 100
#define ID_EXPAND 101

HTREEITEM root_item;

int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
    WNDCLASSEX wcex = { sizeof(wcex) };

    wcex.lpfnWndProc = WindowProc;
    wcex.hInstance = hInstance;
    LoadIconMetric(NULL, IDI_APPLICATION, LIM_LARGE, &wcex.hIcon);
    wcex.hCursor = static_cast<HCURSOR>(LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED));
    wcex.lpszClassName = TEXT("MainWindow");
    LoadIconMetric(NULL, IDI_APPLICATION, LIM_SMALL, &wcex.hIconSm);

    RegisterClassEx(&wcex);

    HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, TEXT("TreeView Test"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hInstance, NULL);
    ShowWindow(hWnd, nCmdShow);

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

    return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        HANDLE_MSG(hWnd, WM_CREATE, MainWindow_OnCreate);
        HANDLE_MSG(hWnd, WM_DESTROY, MainWindow_OnDestroy);
        HANDLE_MSG(hWnd, WM_NOTIFY, MainWindow_OnNotify);
        HANDLE_MSG(hWnd, WM_COMMAND, MainWindow_OnCommand);
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
}

BOOL MainWindow_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
    HWND h_treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, TEXT("TreeView"), WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_LINESATROOT, 10, 10, 400, 400, hWnd, reinterpret_cast<HMENU>(ID_TREEVIEW), GetModuleHandle(NULL), NULL);

    TVINSERTSTRUCT tvis = { TVI_ROOT, TVI_LAST, { TVIF_TEXT | TVIF_CHILDREN } };
    tvis.item.pszText = TEXT("Root");
    tvis.item.cChildren = 1;
    root_item = TreeView_InsertItem(h_treeview, &tvis);

    CreateWindow(WC_BUTTON, TEXT("Expand"), WS_CHILD | WS_VISIBLE, 420, 10, 75, 23, hWnd, reinterpret_cast<HMENU>(ID_EXPAND), GetModuleHandle(NULL), NULL);

    return TRUE;
}

void MainWindow_OnDestroy(HWND hWnd)
{
    PostQuitMessage(0);
}

LRESULT MainWindow_OnNotify(HWND hWnd, int idFrom, NMHDR *pnmhdr)
{
    switch (pnmhdr->code)
    {
    case TVN_ITEMEXPANDING:
        {
            LPNMTREEVIEW pnmtv = reinterpret_cast<LPNMTREEVIEW>(pnmhdr);
            if (pnmtv->action == TVE_EXPAND)
            {
                LPCTSTR items[] = { TEXT("Item 1"), TEXT("Item 2"), TEXT("Item 3") };
                for (LPCTSTR item : items)
                {
                    TVINSERTSTRUCT tvis = { pnmtv->itemNew.hItem, TVI_LAST, { TVIF_TEXT } };
                    tvis.item.pszText = const_cast<LPTSTR>(item);
                    TreeView_InsertItem(pnmhdr->hwndFrom, &tvis);
                }
            }
            break;
        }
    case TVN_ITEMEXPANDED:
        {
            LPNMTREEVIEW pnmtv = reinterpret_cast<LPNMTREEVIEW>(pnmhdr);
            if (pnmtv->action == TVE_COLLAPSE)
            {
                TreeView_Expand(pnmhdr->hwndFrom, pnmtv->itemNew.hItem, TVE_COLLAPSE | TVE_COLLAPSERESET);
            }
            break;
        }
    }
    return 0;
}

void MainWindow_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify)
{
    if (id == ID_EXPAND)
    {
        TreeView_Expand(GetDlgItem(hWnd, ID_TREEVIEW), root_item, TVE_EXPAND);
    }
}

代码创建一个带有TreeView和Button的窗口。单击按钮时,应该展开TreeView的根项。

我可以第一次扩展根项。单击“展开”按钮或单击根项旁边的"+“符号即可。但是,如果我折叠了根项,则不能再次单击“展开”按钮来展开它,而"+“符号仍然有效。我注意到,虽然我使用了TVE_COLLAPSERESET标志来清除TVIS_EXPANDEDONCE标志,但它在TreeView_Expand调用之前仍然有标志。根据MSDN,我认为我需要保持未设置的TVIS_EXPANDEDONCE标志。我在哪里做错了?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-28 01:28:42

使用PostMessage重置TVE_COLLAPSERESET标志:

代码语言:javascript
复制
PostMessage(pnmhdr->hwndFrom, TVM_EXPAND, TVE_COLLAPSE | TVE_COLLAPSERESET, reinterpret_cast<LPARAM>(pnmtv->itemNew.hItem));

据我理解,TreeView发送TVN_ITEMEXPANDED通知,该通知将消息发送回TreeView,这可能会导致问题。我们可能需要将消息延迟到当前消息被处理之后。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23888041

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档