首页 > 其他分享 >Win32 SDK TreeView 控件的基本用法,节点的编辑,拖动,添加,删除,弹出菜单

Win32 SDK TreeView 控件的基本用法,节点的编辑,拖动,添加,删除,弹出菜单

时间:2023-05-08 18:15:07浏览次数:54  
标签:控件 return int hWnd Win32 tvi HWND TreeView

TreeView控件老是用的稀里糊涂的,写个测试程序总结一下基本用法

要注意的是控件是发通知给父窗口处理,因此消息中鼠标的坐标不是相对控件的,要从屏幕坐标转换来。

程序是WIN32 SDK向导生成的C语言框架。树的操作定义成一个类。 

微软网站上TreeView_XXX 宏的说明文档好多错误,应该是返回句柄的都写成了void型,难道是SDK编程没人用,不维护了?

 

 

// Tree.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"

//xgz 扩展控件用库
#include "Commctrl.h"
#pragma comment(lib,"comctl32.lib")

//xgz==========
#define IDC_EDIT                1001 
#define IDC_STATUSBAR           1002
#define IDC_TOOLSBAR            1003
#define IDC_VIEW_TREEVIEW1      1101 

HWND m_hWndEdit;
HWND m_hStatusbar;
HWND m_hToolsbar;

int OnCreate(HWND, UINT, WPARAM, LPARAM);
int OnSize(HWND, UINT, WPARAM, LPARAM);
int OnPaint(HWND, UINT, WPARAM, LPARAM);
int OnTimer(HWND, UINT, WPARAM, LPARAM);
int OnNotify(HWND, UINT, WPARAM, LPARAM); //控件的通知是发给父窗口处理
int OnLButtonDown(HWND, UINT, WPARAM, LPARAM);
int OnLButtonUp(HWND, UINT, WPARAM, LPARAM);
int onm ouseMove(HWND, UINT, WPARAM, LPARAM);
int OnFileNew(HWND, UINT, WPARAM, LPARAM);
int OnFileOpen(HWND, UINT, WPARAM, LPARAM);
int OnFileSave(HWND, UINT, WPARAM, LPARAM);
int OnTreeEdit(HWND, UINT, WPARAM, LPARAM);

int PRINT(const TCHAR* fmt, ...)
{
    TCHAR buffer[1024];
    va_list argptr;
    int cnt;
    int iEditTextLength;
    HWND hWnd = m_hWndEdit;
    if (NULL == hWnd) return 0;

    va_start(argptr, fmt);
    cnt = wvsprintf(buffer, fmt, argptr);  // not %f
    va_end(argptr);
    iEditTextLength = GetWindowTextLength(hWnd);
    if (iEditTextLength + cnt > 30000)       // edit text max length is 30000
    {
        SendMessage(hWnd, EM_SETSEL, 0, 10000);
        SendMessage(hWnd, WM_CLEAR, 0, 0);
        iEditTextLength = iEditTextLength - 10000;
    }
    SendMessage(hWnd, EM_SETSEL, iEditTextLength, iEditTextLength);
    SendMessage(hWnd, EM_REPLACESEL, 0, (LPARAM)buffer);

    return(cnt);
}

//============

class CTree
{
public:
    CTree();
    ~CTree();

    HMENU        m_hMenu, m_hPopMenu;
    HINSTANCE    m_hInst;
    HWND        m_hWnd;
    HTREEITEM    m_hRoot;
    HWND        CreateTreeView(HWND hWndParent);
    int           InitTreetView();
    HTREEITEM    AddItemToTree(HWND hwndTV, LPTSTR lpszItem, int nLevel);
    HTREEITEM    InsertTreeNode(HWND hWndTV, HTREEITEM hPrev, LPTSTR lpszItem);
    //int   DeleteTreetView(); //TreeView_DeleteAllItems(m_hWndTree);
    void        ExpandAll(HTREEITEM hItem);

    HTREEITEM        m_hBeginDrag;         //记录拖动起点的Item
    HIMAGELIST        m_hDragImageList;   //拖动的图像列表

    BOOL        m_bDrag;                   //用来判断是否进行拖动
    void        CopyNodes(HTREEITEM hDesItem, HTREEITEM hSrcItem);//复制节点函数
     
    int       OnTvnBegindrag(NMHDR* pNMHDR);
    int        OnLButtonUp(HWND, UINT, WPARAM, LPARAM);
    int        onm ouseMove(HWND, UINT, WPARAM, LPARAM);
    int        OnTvnBeginlabeledit(LPNMHDR lphr);
    int       OnTvnEndlabeledit(LPNMHDR lphr);
    
    int        OnLClkTree(LPNMHDR lphr);
    int        OnRClkTree(LPNMHDR lphr);
    int        OnDBLClkTree(LPNMHDR lphr);

    int        ItemLabelEdit();
    int        InsertChild();
    int        InsertSibling();
    int       DeleteItem();

};

CTree::CTree()
{
}
CTree::~CTree()
{
}

CTree m_Tree1;

HWND CTree::CreateTreeView(HWND hWndParent)
{
    InitCommonControls();

    m_hInst = (HINSTANCE)GetWindowLong(hWndParent, GWL_HINSTANCE);

    HWND hWndTreeView = CreateWindow(WC_TREEVIEW, _T("Tree"),
        WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS | TVS_LINESATROOT | WS_BORDER | TVS_EDITLABELS,
        0, 0, 0, 0,
        hWndParent,
        (HMENU)IDC_VIEW_TREEVIEW1,
        m_hInst,
        NULL);

    HIMAGELIST hImageList;
    hImageList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 15, 15);             //size 16x16  X15 
    for (unsigned int i = 0; i < 15; i++)
    {
        HICON  hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_ICON1 + i));
        ImageList_AddIcon(hImageList, hIcon);
        DestroyIcon(hIcon);
    }
    SendMessage(hWndTreeView, TVM_SETIMAGELIST, 0, (LPARAM)hImageList);

    m_hWnd = hWndTreeView; //xgz 直接保存
    
    m_hMenu = LoadMenu(m_hInst, (LPCSTR)IDC_TREE);  
    m_hPopMenu = GetSubMenu(m_hMenu, 2);    //XGZ 用主菜单的第三列菜单作为弹出菜单

    return (hWndTreeView);

}

int CTree::InitTreetView()
{

    HTREEITEM hti;

    m_hRoot = InsertTreeNode(m_hWnd, NULL, _T("Root"));
    hti = InsertTreeNode(m_hWnd, m_hRoot, _T("Node1"));
    hti = InsertTreeNode(m_hWnd, m_hRoot, _T("Node2"));
    hti = InsertTreeNode(m_hWnd, m_hRoot, _T("Node3"));
    hti = InsertTreeNode(m_hWnd, hti, _T("Node3-1"));
    hti = InsertTreeNode(m_hWnd, hti, _T("Node3-1-1"));
   
    //TreeView_Expand(m_hWnd, m_hRoot, TVE_EXPAND);//只展开一个节点
    ExpandAll(m_hRoot);   //递归展开所有节点

    return 1;
}

HTREEITEM CTree::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 | TVIF_STATE;

    // 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 = 0;// g_nDocument; 
    tvi.iSelectedImage = 0;// 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 = 2;//g_nClosed; 
        tvi.iSelectedImage = 2;// g_nClosed; 
        TreeView_SetItem(hwndTV, &tvi);
    }

    return hPrev;
}

HTREEITEM CTree::InsertTreeNode(HWND hWndTV, HTREEITEM hPrev, LPTSTR lpszItem)
{
    TVINSERTSTRUCT tvins;
    TVITEM tvi;

    tvins.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; //TVIF_TEXT| TVIF_PARAM; 
    tvins.item.pszText = lpszItem;

    if (NULL != hPrev)   //把上级图标改为文件夹
    {
        tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;   //只处理 IMAGE
        tvi.hItem = hPrev;
        tvi.iImage = 10;
        tvi.iSelectedImage = 10;
        TreeView_SetItem(hWndTV, &tvi);
    }

    tvins.item.iImage = 0;          //初始图标都是文件 
    tvins.item.iSelectedImage = 0;

    tvins.hParent = hPrev;
    tvins.hInsertAfter = TVI_LAST;

    return (HTREEITEM)SendMessage(hWndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
}

void CTree::ExpandAll(HTREEITEM hItem)
{
    if (!hItem)    return;

    HTREEITEM hChild = TreeView_GetChild(m_hWnd, hItem);

    ExpandAll(hChild);

    if (hChild) TreeView_Expand(m_hWnd, hItem, TVE_EXPAND);//XGZ 有子节点的展开父节点,上个返回可能是NULL

    HTREEITEM hSibling = TreeView_GetNextSibling(m_hWnd, hItem);

    ExpandAll(hSibling);
    //XGZ  sibling节点无需展开
    return;
}

//复制节点,将hSrcItem及其子项目复制到下hDesItem节点下
void CTree::CopyNodes(HTREEITEM hDesItem, HTREEITEM hSrcItem)
{
    if (hDesItem == NULL || hSrcItem == NULL)                //Item为空则不进行操作
    {
        return;
    }
    TVITEM tvItem;                            //定义项目信息结构体
    tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_PARAM;    //xgz 必须要copy param
    tvItem.hItem = hSrcItem;
    char chText[MAX_PATH] = { 0 };
    tvItem.pszText = chText;
    tvItem.cchTextMax = MAX_PATH;
    //GetItem(&tvItem);                    //获取项目信息
    TreeView_GetItem(m_hWnd, &tvItem);

    TVINSERTSTRUCT tvInsert;                //定义插入操作的数据结构
    tvInsert.hParent = hDesItem;                        //定义插入的父节点
    tvInsert.item = tvItem;                             //定义插入的子节点

    HTREEITEM hInsert = TreeView_InsertItem(m_hWnd, &tvInsert);//插入Item,并获取插入完之后的Item新的句柄

    //Item里的所有子Item也插过来
    HTREEITEM hChild = TreeView_GetChild(m_hWnd, hSrcItem);//获取子节点

    while (hChild != NULL)
    {
        CopyNodes(hInsert, hChild);                //递归复制子节点
        hChild = TreeView_GetNextSibling(m_hWnd, hChild); //获取下一个兄弟节点
    }
}

//WM_NOTIFY 消息在 wParam 中包含发送消息的控件的 ID,在 lParam 中包含指向结构的指针。
//该结构要么是 NMHDR 结构,要么是具有 NMHDR 结构作为其第一个成员的较大结构。 
//由于 NMHDR 是第一个成员,因此指向此结构的指针可用作指向 NMHDR 的指针,也可以用作指向较大结构的指针,具体取决于转换方式。
//开始拖动时控件发通知给父窗口,父窗口须记录源树节点,捕获鼠标以便处理移动消息
int CTree::OnTvnBegindrag(NMHDR* pNMHDR)
{
  
    //LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    //// TODO: Add your control notification handler code here
    //*pResult = 0;

    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
    HTREEITEM hItem = pNMTreeView->itemNew.hItem;        //获取开始拖动的Item的句柄
    if (hItem == TreeView_GetRoot(m_hWnd))         //根节点不能拖动
    {
        return 0;
    }

    m_hBeginDrag = hItem;                       //保存拖动的树节点

    POINT dragPt;                               //拖动位置坐标,相对树控件
    dragPt.x = pNMTreeView->ptDrag.x;
    dragPt.y = pNMTreeView->ptDrag.y;

    m_hDragImageList = (HIMAGELIST)SendMessage(m_hWnd, TVM_CREATEDRAGIMAGE, 0, (LPARAM)pNMTreeView->itemNew.hItem); //创建拖动的图像列表

    if (m_hDragImageList != NULL)
    {
        ImageList_BeginDrag(m_hDragImageList, 0, 8, 8); //xgz 拖动图标加个(8,8)位置偏移,避免光标遮挡
        ClientToScreen(m_hWnd, &(dragPt));                  //转换客户坐标到屏幕坐标
        ImageList_DragEnter(m_hWnd, dragPt.x, dragPt.y); //在拖动的过程中显示拖动的图像 
        SetCapture(GetParent(m_hWnd));                             //树的父窗口开始鼠标捕捉
        m_bDrag = TRUE;                           //这里表示当前状态是拖动操作
    }
    return 0;
}

//父窗口的鼠标消息,和控件可能有位移,所以不用lParam中的坐标,而是从屏幕坐标转换
int CTree::OnMouseMove(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (m_bDrag)                        //处于拖动状态
    {
        HTREEITEM hItem;
        UINT nHitFlags;
            
        POINT point;
        GetCursorPos(&point);
        ScreenToClient(m_hWnd, &point); //控件坐标

        ImageList_DragMove(point.x, point.y);  //设置拖动的图像位置为鼠标位置,相对于控件显示

        //设置鼠标经过时高亮显示选中
        TVHITTESTINFO tvhit;
        tvhit.pt = point;
        hItem = TreeView_HitTest(m_hWnd, &tvhit);
        if (hItem != NULL)
        {
            ImageList_DragShowNolock(FALSE);            //隐藏拖动的图像
            TreeView_SelectDropTarget(m_hWnd, hItem);//设置选中的项目

            //若有子节点就展开
            HTREEITEM hChild = TreeView_GetChild(m_hWnd, hItem);
            if (hChild) TreeView_Expand(m_hWnd, hItem, TVE_EXPAND);//XGZ 有子节点的展开父节点,上个返回可能是NULL

            ImageList_DragShowNolock(TRUE);  //显示拖动的图像,展开子节点后再显示,避免残影
        }
        return 1;
    }
    else
    {
        //CTreeCtrl::OnMouseMove(nFlags, point);//MFC如果不是拖动,就交父类默认处理
        return 1; //xgz 自己封装SDK API,父类没处理,直接返回
    }
}

//拖放完成可以用UP,也可以用Down,习惯上可能多用UP
int CTree::OnLButtonUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    //CTreeCtrl::OnLButtonUp(nFlags, point);  //FMC的基本调用格式,nFlags可以是键盘状态等,在WPARAM中,
    POINT point;
    point.x = LOWORD(lParam);
    point.y = HIWORD(lParam);

    if (m_bDrag == TRUE)   //正在拖动
    {
        m_bDrag = FALSE;                 //结束拖动状态
        ImageList_DragLeave(m_hWnd);  //隐藏拖动图像,允许窗口进行更新            (3)
        ImageList_EndDrag();              //结束图像的拖动                          (4)
        ReleaseCapture();                     //释放鼠标捕捉

        ImageList_Destroy(m_hDragImageList);  //释放图像列表
        m_hDragImageList = NULL;

        HTREEITEM hItemDest;  //拖放目的地的Item

        TVHITTESTINFO tvhit;
        GetCursorPos(&point);
        ScreenToClient(m_hWnd, &point);
        tvhit.pt = point;
        tvhit.flags = TVHT_TORIGHT;
        hItemDest = TreeView_HitTest(m_hWnd, &tvhit);

        if (hItemDest != NULL)  //目的地有效
        {
            BOOL blMove = TRUE; //可以移动的条件:目的节点不是源节点的父节点,目的不是源也不是源的子孙

            if (hItemDest == TreeView_GetParent(m_hWnd, m_hBeginDrag)) blMove = FALSE; //目标和源的父相同

            HTREEITEM hItem = hItemDest;
            while (hItem != NULL)
            {
                if (hItem == m_hBeginDrag)  //目标或目标的父节点和源节点相同则不能移动
                {
                    blMove = FALSE;
                    break;
                }
                hItem = TreeView_GetParent(m_hWnd, hItem); //向上查找
            }

            if (blMove) //满足移动条件
            {
                HTREEITEM hItemScrParent = TreeView_GetParent(m_hWnd, m_hBeginDrag);

                CopyNodes(hItemDest, m_hBeginDrag);            //完成节点的复制
                
                TreeView_DeleteItem(m_hWnd, m_hBeginDrag); //删除原Item,其子节点也会自动删除。


                TVITEM tvi;
                tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;   //只处理 IMAGE
                tvi.hItem = hItemDest;                        //有了子节点图标应该是文件夹
                tvi.iImage = 10;
                tvi.iSelectedImage = 10;
                TreeView_SetItem(m_hWnd, &tvi);

                if (TreeView_GetChild(m_hWnd, hItemScrParent) == NULL)  //如果源的父没有子了
                {
                    tvi.hItem = hItemScrParent;             
                    tvi.iImage = 0;                        //图标改成文件
                    tvi.iSelectedImage = 0;
                    TreeView_SetItem(m_hWnd, &tvi);
                }
            }
            TreeView_SelectDropTarget(m_hWnd, NULL);   //取消移入Item的选中状态
            m_hBeginDrag = NULL;
        }
    }
    return 1;
}

int CTree::OnTvnBeginlabeledit(LPNMHDR lphr)
{
    TV_DISPINFO* pTVDispinfo = (TV_DISPINFO*)lphr;
    HWND hWndEdit = TreeView_GetEditControl(m_hWnd); //xgz 这是EDIT控件,可以发消息
    if (pTVDispinfo->item.lParam == 0)  //0 是取消了编辑
        return 1;  //阻止编辑
    else
        return 0;  //允许编辑
}

int CTree::OnTvnEndlabeledit(NMHDR* pNMHDR)
{
//    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);

    TV_DISPINFO* pTVDispinfo = (TV_DISPINFO*)pNMHDR;
    if (pTVDispinfo->item.pszText != 0)  //xgz 修改了才更新,0是取消,若取消编辑保持原来的字符串
    {
        //SetItemText(pTVDispinfo->item.hItem, pTVDispinfo->item.pszText);
        //TreeView_SetItem(m_hWnd, &(pTVDispinfo->item));
        
        TVITEM tvi;
        
        tvi.mask = TVIF_TEXT;   //只处理 TEXT
        tvi.hItem = pTVDispinfo->item.hItem;
        tvi.pszText = pTVDispinfo->item.pszText;
        TreeView_SetItem(m_hWnd, &tvi);
    }
    return 0;
}

int CTree::OnLClkTree(LPNMHDR lphr)
{
    TVHITTESTINFO thti;
    HTREEITEM htItem;
    TVITEM tvi;
    POINT point;
        
    GetCursorPos(&point);
    ScreenToClient(m_hWnd, &point);
    thti.pt = point;
    thti.flags = TVHT_TORIGHT;
    htItem = TreeView_HitTest(m_hWnd, &thti);

    if (htItem == NULL)
        return 0;

    TCHAR szText[20];
    memset(&tvi, 0, sizeof(tvi));
    tvi.mask = TVIF_TEXT | TVIF_PARAM;
    tvi.hItem = htItem;
    tvi.pszText = szText;
    tvi.cchTextMax = sizeof(szText);
    TreeView_GetItem(m_hWnd, &tvi);

    PRINT(_T("\r\n<INFO>CTree::OnLClkTree= %s"), szText);

    return 1;
}
int CTree::OnRClkTree(LPNMHDR lphr)
{
    TVHITTESTINFO thti;
    HTREEITEM htItem;
    TVITEM tvi;
    POINT point;

    GetCursorPos(&point);
    ScreenToClient(m_hWnd, &point);
    thti.pt = point;
    thti.flags = TVHT_TORIGHT;
    htItem = TreeView_HitTest(m_hWnd, &thti);

    if (htItem == NULL)
        return 0;

    TCHAR szText[20];
    memset(&tvi, 0, sizeof(tvi));
    tvi.mask = TVIF_TEXT | TVIF_PARAM;
    tvi.hItem = htItem;
    tvi.pszText = szText;
    tvi.cchTextMax = sizeof(szText);
    TreeView_GetItem(m_hWnd, &tvi);

    PRINT(_T("\r\n<INFO>CTree::OnRClkTree = %s"), szText);

    GetCursorPos(&point);

    TrackPopupMenu(m_hPopMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, 0, GetParent(m_hWnd), NULL);  //通知是控件的父窗口处理

    return 1;
}
int CTree::OnDBLClkTree(LPNMHDR lphr) { HTREEITEM htItem; TVITEM tvi; htItem = TreeView_GetSelection(m_hWnd); if (htItem == NULL) return 0;
// HWND m_hWndClient = ((CXMDIFrameEx*)m_pMainFrame)->m_hWndClient; TCHAR szText[20]; memset(&tvi, 0, sizeof(tvi)); tvi.mask = TVIF_TEXT | TVIF_PARAM; tvi.hItem = htItem; tvi.pszText = szText; tvi.cchTextMax = sizeof(szText); TreeView_GetItem(m_hWnd, &tvi); PRINT(_T("\r\n<INFO>CTree::OnDBLClkTree= %s"), szText); return 1; } int CTree::ItemLabelEdit() { HTREEITEM htItem; TVITEM tvi; htItem = TreeView_GetSelection(m_hWnd); if (htItem == NULL) return 0; TreeView_EditLabel(m_hWnd, htItem); return 1; } int CTree::InsertChild() { // TODO: Add your command handler code here HTREEITEM hItem = TreeView_GetSelection(m_hWnd); HTREEITEM hItemNew = NULL; if (NULL == hItem) { PRINT(_T("\r\n<FAIL>No selected")); return 0; } else { hItemNew = InsertTreeNode(m_hWnd, hItem, _T("NewChild")); TreeView_Expand(m_hWnd, hItem, TVE_EXPAND); TreeView_SelectItem(m_hWnd, hItemNew); TreeView_EditLabel(m_hWnd, hItemNew); //插入后就编辑 return 1; } } int CTree::DeleteItem() { HTREEITEM hItem = TreeView_GetSelection(m_hWnd); HTREEITEM hItemNew = NULL; if (NULL == hItem) { PRINT(_T("\r\n<FAIL>No selected")); return 0; } else { TreeView_DeleteItem(m_hWnd, hItem); return 1; } } int CTree::InsertSibling() { HTREEITEM hItem = TreeView_GetSelection(m_hWnd); HTREEITEM hItemNew = NULL; hItem = TreeView_GetParent(m_hWnd, hItem); if (NULL == hItem) { PRINT(_T("\r\n<FAIL>No selected")); return 0; } else { hItemNew = InsertTreeNode(m_hWnd, hItem, _T("NewSibling")); TreeView_Expand(m_hWnd, hItem, TVE_EXPAND); TreeView_SelectItem(m_hWnd, hItemNew); TreeView_EditLabel(m_hWnd, hItemNew); //插入后就编辑 return 1; } } //========工具条和状态条========================== HWND CreateStatusbar(HWND hWnd) { int Rightend[3]; RECT rt; GetClientRect(hWnd, &rt); HWND hWndStatusBar = CreateWindowEx(0, STATUSCLASSNAME, _T(""), WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP, 0, 0, 0, 0, hWnd, (HMENU)IDC_STATUSBAR, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL); if (!hWndStatusBar) return NULL; Rightend[0] = rt.right / 2; Rightend[1] = rt.right * 3 / 4; Rightend[2] = rt.right; //set statusbar to three segment SendMessage(hWndStatusBar, SB_SETPARTS, (WPARAM)3, (LPARAM)Rightend); MoveWindow(hWndStatusBar, 0, 0, 0, 0, TRUE); //TextOut in statusbar SendMessage(hWndStatusBar, SB_SETTEXT, 0, (long)TEXT("Status 0")); SendMessage(hWndStatusBar, SB_SETTEXT, 1, (long)TEXT("========test=====")); SendMessage(hWndStatusBar, SB_SETTEXT, 2, (long)TEXT("Step 2")); return hWndStatusBar; } HWND CreateToolbar(HWND hWnd) { // image,COMMAND, STATUS, STYLE, //用系统标准图标 TBBUTTON tbButton[] = { { STD_FILENEW, IDM_FILE_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_FILEOPEN, IDM_FILE_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_FILESAVE, IDM_TEST_TEST1, TBSTATE_ENABLED , TBSTYLE_BUTTON , 0L, 0}, { STD_HELP, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, -1}, { STD_FIND, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_UNDO, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_REDOW, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, -1}, { STD_COPY, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_PASTE, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_CUT, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_DELETE, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_FILESAVE, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_PROPERTIES, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_FIND, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_REPLACE, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_PRINT, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_FILESAVE, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_FILESAVE, IDM_TEST_TEST3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { STD_PRINTPRE, IDM_EXIT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0} }; HINSTANCE hLib = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); //It can be other DLL,here same as m_hInst HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, _T(""), //WS_VISIBLE|WS_CHILD|TBSTYLE_TOOLTIPS, //| WS_BORDER|TBSTYLE_FLAT, TBSTYLE_FLAT | WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS | CCS_NORESIZE | CCS_ADJUSTABLE | CCS_NODIVIDER | CCS_NOPARENTALIGN, //for rebar 0, 0, 0, 0, hWnd, (HMENU)IDC_TOOLSBAR, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL); if (!hWndToolbar) return NULL; SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); SendMessage(hWndToolbar, TB_SETEXTENDEDSTYLE, 0, (LPARAM)(DWORD)(TBSTYLE_EX_DRAWDDARROWS)); TBADDBITMAP tbBitmap1; tbBitmap1.hInst = HINST_COMMCTRL; tbBitmap1.nID = IDB_STD_SMALL_COLOR; SendMessage(hWndToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbBitmap1); SendMessage(hWndToolbar, TB_SETBITMAPSIZE, 0, (LPARAM)MAKELONG(16, 16)); //size 16x16 SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0); SendMessage(hWndToolbar, TB_ADDBUTTONS, 15, (LONG)&tbButton); //add 6 button return hWndToolbar; } //=====模板生成的WIN32 程序框架 ========================= #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_TREE, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TREE); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TREE); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_TREE; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } InitCommonControls(); m_hToolsbar = CreateToolbar(hWnd); m_hStatusbar = CreateStatusbar(hWnd); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; TCHAR szHello[MAX_LOADSTRING]; LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); switch (message) { case WM_CREATE: OnCreate(hWnd, message, wParam, lParam); break; case WM_SIZE: OnSize(hWnd, message, wParam, lParam); break; case WM_PAINT: OnPaint(hWnd, message, wParam, lParam); break; case WM_TIMER: OnTimer(hWnd, message, wParam, lParam); break; case WM_LBUTTONDOWN: OnLButtonDown(hWnd, message, wParam, lParam); break; case WM_LBUTTONUP: OnLButtonUp(hWnd, message, wParam, lParam); break; case WM_MOUSEMOVE: onm ouseMove(hWnd, message, wParam, lParam); break; case WM_NOTIFY: OnNotify(hWnd, message, wParam, lParam); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_FILE_NEW: OnFileNew(hWnd, message, wParam, lParam); break; case IDM_FILE_OPEN: OnFileOpen(hWnd, message, wParam, lParam); break; case IDM_FILE_SAVE: OnFileSave(hWnd, message, wParam, lParam); break; case IDM_TREE_EDIT: OnTreeEdit(hWnd, message, wParam, lParam); break; case IDM_TREE_INSERTCHILD: m_Tree1.InsertChild(); break; case IDM_TREE_INSERTSIBLING: m_Tree1.InsertSibling(); break; case IDM_ABOUT: MessageBox(hWnd, "Test", "Test",MB_OK); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } int OnCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { m_hWndEdit = CreateWindow(_T("edit"), NULL, WS_CHILD | WS_BORDER | WS_VISIBLE | ES_MULTILINE | WS_VSCROLL, 0, 0, 0, 0, hWnd, (HMENU)IDC_EDIT, hInst, NULL); SetTimer(hWnd, 1, 10000, NULL); //10s m_Tree1.CreateTreeView(hWnd); m_Tree1.InitTreetView(); return 1; } //留一个状态条的位置 int OnSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int cxClient, cyClient; cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); MoveWindow(m_hToolsbar, 0, 0, cyClient, 25, TRUE); MoveWindow(m_hStatusbar, 0, 0, 0, 0, TRUE); MoveWindow(m_hWndEdit, 0, cyClient - 220, cxClient, 200, TRUE); MoveWindow(m_Tree1.m_hWnd, 0, 25, 220, cyClient - 200 - 50, TRUE); return DefWindowProc(hWnd, message, wParam, lParam); } int OnPaint(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; RECT rt; hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rt); //DrawText(hdc, StatusText, strlen(StatusText), &rt, DT_LEFT|DT_BOTTOM|DT_SINGLELINE); EndPaint(hWnd, &ps); return 1; } int OnTimer(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return 1; } int OnFileNew(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PRINT("\r\nOnFileNew"); return 1; } int OnFileOpen(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return 1; } int OnFileSave(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return 1; } int OnTreeEdit(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PRINT("\r\nOnTreeEdit"); m_Tree1.ItemLabelEdit(); return 1; } int OnLButtonDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return 1; } int OnLButtonUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { m_Tree1.OnLButtonUp(hWnd, message, wParam, lParam); return 1; } int onm ouseMove(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { m_Tree1.OnMouseMove(hWnd, message, wParam, lParam); return 1; } int OnNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int idCtrl = (int)wParam; //控件的 ID LPNMHDR lphr = (LPNMHDR)lParam; //先看是哪个控件,再决定结构 //m_hWndTree = GetDlgItem(hWnd, IDM_VIEW_TREEVIEW1); if (lphr->hwndFrom == m_Tree1.m_hWnd) { NM_TREEVIEW* pTree = (NM_TREEVIEW*)lParam; //是树控件,所以用树控件通知结构 switch (pTree->hdr.code) { case NM_CLICK: m_Tree1.OnLClkTree(lphr); break; case NM_RCLICK: m_Tree1.OnRClkTree(lphr); break; case NM_DBLCLK: m_Tree1.OnDBLClkTree(lphr); break; case TVN_BEGINDRAG: return m_Tree1.OnTvnBegindrag(lphr); case TVN_BEGINLABELEDIT: return m_Tree1.OnTvnBeginlabeledit(lphr); //是否允许编辑,是通知的返回值 case TVN_ENDLABELEDIT: return m_Tree1.OnTvnEndlabeledit(lphr); break; default: //PRINT("\r\nm_hWndTree=%d %d", m_hWndTree, pTree->hdr.code); break; } } return 0; //返回消息是给控件处理 }

 

 

 

标签:控件,return,int,hWnd,Win32,tvi,HWND,TreeView
From: https://www.cnblogs.com/xgz21/p/17382532.html

相关文章

  • 自学c#基础第六课,常用控件label
    labellabel和linklabel控件,主要是设置里面可见属性、字体什么的,linklabel的话有点中后下划线样式LinkBehaviorlistbox主要介绍了里面的方法//清除listBox1列表//listBox1.Items.Clear();//添加listBox1元素//listBox1.......
  • 第6-1讲,Listbox 列表框控件
    Listbox列表框控件在与用户交互的过程成中,如果需要用户自己做出选择,可以使用列表框控件.importtkinterastk#创建一个窗口window=tk.Tk()#创建窗口的标题window.title("listbox")#设置窗口的大小window.geometry('500x400')#设置窗体的图标window.iconbitmap('../......
  • 选择好友的下拉控件
    <!doctypehtmlpublic"-//W3C//DTDHTML4.01//EN''http://www.w3.org/TR/html4/strict.dtd"><html><head><metahttp-equiv="content-type"content="text/html;charset=utf-8"/><title>選擇好友......
  • 界面控件Telerik UI for WinForms使用指南 - 数据绑定 & 填充(二)
    TelerikUIforWinForms拥有适用WindowsForms的110多个令人惊叹的UI控件,所有的UIforWinForms控件都具有完整的主题支持,可以轻松地帮助开发人员在桌面和平板电脑应用程序提供一致美观的下一代用户体验。TelerikUIforWinForms组件为可视化任何类型的数据提供了非常丰富的UI......
  • 界面控件DevExpress Blazor UI v22.2亮点:全新的Window组件
    DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpressDashboardeXpressApp框架、适用于VisualStudio的CodeRush等一系列辅助工具,该组件拥有众多新产品和数十个具有高影响力的功能,可为桌面、Web和移动应用提供直观的解决方案,全面解决各种使用场......
  • SQL_DataGridView控件
    1.DataGridView控件——加载数据usingSystem;usingSystem.Data;usingSystem.Text;usingSystem.Windows.Forms;usingSystem.Data.SqlClient;namespaceTest03{publicpartialclassForm1:Form{publicForm1(){Initializ......
  • Windows10下安装OpenSSL curl WIN32 /WIN64 openssl1.1.x
     首先是环境,强调下环境,很多问题是环境造成的。1.WINDOWS1064位系统;2.VisualStudio2015 工具: 1.ActivePerl-5.24.3.2404-MSWin32-x64-404865.exe,下载地址:https://www.activestate.com/products/activeperl/downloads/  2. openssl-1.1.0f.tar.gz  下载地址: h......
  • 一个网页的控件很碍眼,怎么能将它关闭掉?
    ctrl+shift+i打开开发者模式,用小箭头选中控件右击“Hiddenelement”,或者Editattribute,添加属性class="display:none"。前者更简单,后者更彻底。......
  • C#一行代码之获取控件值
    代码使用varcellValue=dataGridView.ExInvokeGetCellValue(0,1);代码封装///<summary>///DataGridView获取单元格值///</summary>///<paramname="dataGridView"></param>///<paramname="rowIndex"></param>//......
  • C#一行代码之跨线程更新控件1
    代码使用ThreadPool.QueueUserWorkItem(o=>{for(inti=0;i<100;i++){textBox1.ExInvokeIt(textBox=>textBox.Text=i.ToString());}});//或Task.Run(()=>{for(inti=0;i<100;i++){textBox1.E......