• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            旅途

            如果想飛得高,就該把地平線忘掉

            Checkboxes in a Tree Control

            Abstract

            "Checkboxes in a tree control" shows how to add normal and three-state checkboxes to a tree control, and how to get notified when the checkbox changes. The sample project uses MFC, but the technique can easily be adapted to a Win32 or an ATL/WTL application.

            Overview

            The TreeView common control supports checkboxes since version 4.70 (distributed originally with Internet Explorer 3.0), and enabling this is supposedly easy- choose one of three:

            • use the Checkboxes option in dialog resource editor
            • specify the TVS_CHECKBOXES window style bit when creating the tree
            • Use
                treeCtrl.SetWindowStyle(0, TVS_CHECKBOXES)
              in MFC applications, or
                SetWindowLong(hwndTree, GWL_STYLE, GetWindowLong(hwndTree, GWL_STYLE) | TVS_CHECKBOXES);
              InvalidateRect(hwndTree, NULL, true)

              for Win32 applications. This must be done before the tree control is filled with items.

            However, there are a few problems asociated with this:

            • How do I detect when the checkbox is changed
            • How (and when!) do I retrieve the current check state
            • How to use Three-State Checkboxes.

             

            Tree Control Images

            The tree control uses the state image list to implement the checkboxes. When the TVS_CHECKBOXES style is set, the tree control creates a custom state image list with the two state image buttons - unchecked & checked. When clicking on the state image, the tree control cycles through the state images.

            Tree Control images: The  tree control uses two image lists: First, the 'normal' image list, with the images as they are specified in CTreeCtrl::InsertItem as nImage or nSelectedImage. (These parameters are the same as the nImage / nSelectedImage members of the TVITEM struct.) Second, there is the State image list: State images are displayed left beside the normal image. The currently displayed item is controled to the item's state mask, bits 12..15. To add to the confusion, some of the state images can be overlayed onto the "normal" images.

            Retrieving and Setting State Images

            void TreeCtrl_SetStateImage(CTreeCtrl & tree, HTREEITEM item, int stateImage)
                        {
                        tree.SetItemState(item, INDEXTOSTATEIMAGEMASK(stateImage), TVIS_STATEIMAGEMASK);
                        }
            int TreeCtrl_GetStateImage(CTreeCtrl & tree, HTREEITEM item)
                        {
                        return tree.GetItemState(item, TVIS_STATEIMAGEMASK) >> 12;
                        }

            Note that 0 indicates no state image; so you can use bool isChecked = (TreeCtrl_GetStateImage(...) - 1) != 0.

             

            Three-State Check boxes

            For three-state checkboxes, we just need to replace the default created state image list with our custom image list, windows will figure out the number of check states from the length of the image list. Remember that the first image (index 0) is unused. The sample uses the following Bitmap resource (IDB_STATEIMG in the sample):

            checktree.gif (3735 bytes)

            • Add a member variable, CImageList m_ilState to the dialog
              (the image list must not be destroyed as long as the tree control is displayed)
            • In OnInitDialog, add the following:
              m_ilState.Create(IDB_STATEIMG /* resID of bitmap */,
                               16 /* width of single image */,    0 /* 0: the image list won't grow */,
                               RGB(255,255,255) /* transparent color */);
              m_treeCtrl.SetImageList(&m_ilState, TVSIL_STATE); // set state image list

            The size of the bitmap affects the number of checkbox 'states'. To retrieve the current state, use TreeCtrl_GetStateImage(...) - 1. As with a checkbox, this value is 0 for unchecked, 1 for checked, and 2 for indeterminate.

            This way, you could create a 'checkbox' with up to 15 states - which, on the other hand, ounds notlike fun for your users. More promising is the idea that you are not limited to checkboxes!

            Being Notified when Checkbox changes

            We want to know when the checkmark is clicked,so we can do something. The TreeView control does not send a separate notification, when item state changes, so we must manage both NM_CLICK wnd TVN_KEYDOWN message separately.

            It's even trickier: When you get these notifications, the item state bits still indicates the old state. This wouldn't be as bad itself, but Microsoft might be tempted to change this behavior in the future. You can get the correct image (and thus, the current check state) when the current "Click" or "KeyDown"  message is completely handled. To do this, we can post a message to outselves, using PostMessage(some_unique_message_id, ..), and evaluating the new style there. With the message, I send the tree control ID in WPARAM (in case there are multiple tree controls in the dialog), and the item which has changed in LPARAM.

             

            // .h:
                        
                        #define UWM_TV_CHECKBOX    WM_APP   // the custom message we post to ourself
                        class CDlgOrWhatever
                        {
                        // ...
                        CTreeCtrl    m_tree;
                        afx_msg LRESULT OnTvCheckbox(WPARAM wp, LPARAM lp); // our message handler for the posted message
                        };
            // .cpp
                        #include "windowsx.h"  // required for GET_X_LPARAM, GET_Y_LPARAM)
            // ----- Message map ------
                        BEGIN_MESSAGE_MAP(...)
                        ON_MESSAGE(UWM_TV_CHECKBOX, OnTvCheckbox)
                          // ... and, of course, the message handlers for NM_CLICK and TVN_KEYDOWN notifications
                        END_MESSAGE_MAP()
            // ----- NM_CLICK Message Handler: ------
                        void CCheckTreeDlg::OnClickTree1(NMHDR* pNMHDR, LRESULT* pResult)
                        {
                        DWORD dw = GetMessagePos();                   // retrieve mouse cursor position when msg was sent
                        CPoint p(GET_X_LPARAM(dw), GET_Y_LPARAM(dw)); // ..and put into point structure
                        m_tree.ScreenToClient(&p);                    // make coords local to tree client area
                        UINT htFlags = 0;
                        HTREEITEM it = m_tree.HitTest(p, &htFlags);   // See where the click was on
                        if (it != NULL && ( htFlags & TVHT_ONITEMSTATEICON)) {
                            // the check box was hit - we just post a message for later processing
                            PostMessage(UWM_TV_CHECKBOX, pNMHDR->idFrom, (LPARAM) it);
                        }
                        *pResult = 0;
                        }
            // ----- Handle checkbox changed here: ------
                        LRESULT CCheckTreeDlg::OnTvCheckbox(WPARAM wp, LPARAM lp)
                        {
                        CTreeCtrl & tree = GetDlgItem(wp);  // if we have multiple trees
                        HTREEITEM hitem = (HTREEITEM) lp;
                        int checked = (tree.GetItemState(hitem, TVIS_STATEIMAGEMASK) >> 12) - 1;
                          // "checked" now contains the check state.
                        // the sample does the following:
                          CString s = tree.GetItemText(hitem);
                        if (checked==0) s += " unchecked";
                        else if (checked==1) s+= " checked";
                        else if (checked==2) s+= " dunno";
                        else s+= " ???";
                        SetDlgItemText(IDC_INFO, s);
                        return 0;
                        }
                        

            Notes:

            19.2.2002: brushed up formatting. Fixed an alignment error in the resource bitmap 8the image on this page is still wrong, but that doesn#t mater much I guess). Added the TVN_KEYDOWN handler to the sample to catch the state change correctly when a key is hit.

            30.11.2002: fiexd a bug in the OnClick Handler (thanks Michael!)

            posted on 2007-07-18 16:49 旅途 閱讀(2674) 評論(0)  編輯 收藏 引用 所屬分類: 深入windows

            久久九九免费高清视频| 蜜臀av性久久久久蜜臀aⅴ| 久久99国产一区二区三区| 欧美伊人久久大香线蕉综合69| 中文字幕精品无码久久久久久3D日动漫| 伊人久久大香线蕉av不卡| 亚洲国产天堂久久综合网站| 久久久这里只有精品加勒比| 久久精品国产免费一区| 成人综合久久精品色婷婷 | 免费观看成人久久网免费观看| 精品久久久久中文字幕一区| 国内精品久久久久久99| 久久久这里有精品| 久久久久久亚洲精品不卡| 国产精品久久久福利| 国色天香久久久久久久小说| 丁香五月综合久久激情| 久久精品国产亚洲AV嫖农村妇女 | 青青国产成人久久91网| 婷婷久久久亚洲欧洲日产国码AV| 色综合合久久天天给综看| 天天爽天天爽天天片a久久网| 精品少妇人妻av无码久久| 久久久无码一区二区三区| 精品国产日韩久久亚洲| 一本久久免费视频| 少妇被又大又粗又爽毛片久久黑人| 久久国产免费观看精品| 国产午夜精品理论片久久影视| 国产产无码乱码精品久久鸭| 国产情侣久久久久aⅴ免费| 久久99国产精品久久99果冻传媒 | 久久乐国产精品亚洲综合| 久久精品二区| 香蕉久久永久视频| 久久久久久伊人高潮影院 | 国产三级观看久久| 亚洲七七久久精品中文国产| 一本一本久久a久久精品综合麻豆| 超级97碰碰碰碰久久久久最新|