<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    VC中實現帶有背景位圖的樹型控件

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接 當前許多應用程序都在使用樹型控件時為其添加了背景位圖,增強的控件的魅力,然而對于Visual C++編程愛好者來說,使用Visual C++MFC提供的樹型控件(CTreeCtrl)本身就是一個難點,至于如何使該控件能夠帶有背景位圖,那就更加是一個令人困惑的問題了。本實例對CTreeCtrl類進行了增強,不僅使它帶有背景位圖,而且解決了在點擊樹型控件時背景位圖閃動的問題,另外,通過在對話框中使用該控件來顯示三級目錄,演示了樹型控件的基本使用方法。下圖為程序編譯后的運行效果圖:

    RFID設備管理軟件
    圖一、帶背景圖的樹型控件效果圖


       一、實現方法

      在實現樹型控件的背景位圖之前,我們首先介紹一下樹型控件的基本使用方法。樹形控件在系統中大量被使用,例如Windows資源管理器就是一個典型的例子。樹形控件可以用于樹形的結構,其中有一個根接點(Root)然后下面有許多子結點,而每個子結點上又允許有一個或多個或沒有子結點。

      MFC中使用CTreeCtrl類來封裝樹形控件的各種操作,通過調用BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );創建一個窗口,dwStyle中可以使用以下一些樹形控件的專用風格:TVS_HASLINES 在父/子結點之間繪制連線;TVS_LINESATROOT 在根/子結點之間繪制連線;TVS_HASBUTTONS 在每一個結點前添加一個按鈕,用于表示當前結點是否已被展開;TVS_EDITLABELS 結點的顯示字符可以被編輯;TVS_SHOWSELALWAYS 在失去焦點時也顯示當前選中的結點;TVS_DISABLEDRAGDROP 不允許Drag/Drop;TVS_NOTOOLTIPS 不使用ToolTip顯示結點的顯示字符。

      在樹形控件中每一個結點都有一個句柄(HTREEITEM),同時添加結點時必須提供的參數是該結點的父結點句柄(其中根Root結點只有一個,既不可以添加也不可以刪除),利用HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST )可以添加一個結點,pszItem為顯示的字符,hParent代表父結點的句柄,當前添加的結點會排在hInsertAfter表示的結點的后面,返回值為當前創建的結點的句柄。

      如果你希望在每個結點前添加一個小圖標,就必需先調用CTreeCtrl類的成員函數CImageList* SetImageList( CImageList * pImageList, int nImageListType ),指明當前控件所使用的圖像列表(ImageList),nImageListType為TVSIL_NORMAL。在調用完成后控件中使用圖片以設置的ImageList中圖片為準。然后調用HTREEITEM InsertItem( LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST)添加結點,其中參數nImage為結點沒被選中時所使用圖片序號,nSelectedImage為結點被選中時所使用圖片序號。

      此外CTreeCtrl還提供了一些函數用于得到/修改控件的狀態:

      ·HTREEITEM GetSelectedItem( )將返回當前選中的結點的句柄;

      ·BOOL SelectItem( HTREEITEM hItem )將選中指明結點;

      ·BOOL GetItemImage( HTREEITEM hItem, int& nImage, int& nSelectedImage ) / BOOL SetItemImage( HTREEITEM hItem, int nImage, int nSelectedImage )用于得到/修改某結點所使用圖標索引;

      ·CString GetItemText( HTREEITEM hItem ) /BOOL SetItemText( HTREEITEM hItem, LPCTSTR lpszItem )用于得到/修改某一結點的顯示字符;

      ·BOOL DeleteItem( HTREEITEM hItem )用于刪除某一結點,BOOL DeleteAllItems( )將刪除所有結點。

      此外如果想遍歷樹可以使用下面的函數:

      ·HTREEITEM GetRootItem( )得到根結點;

      ·HTREEITEM GetChildItem( HTREEITEM hItem )得到子結點;

      ·HTREEITEM GetPrevSiblingItem/GetNextSiblingItem( HTREEITEM hItem )得到指明結點的上/下一個兄弟結點;

      ·HTREEITEM GetParentItem( HTREEITEM hItem )得到父結點。

      樹形控件的消息映射使用ON_NOTIFY宏,形式如同:ON_NOTIFY( wNotifyCode, id, memberFxn ),wNotifyCode為通知代碼,id為產生該消息的窗口ID,memberFxn為處理函數,函數的原型如同void OnXXXTree(NMHDR* pNMHDR, LRESULT* pResult),其中pNMHDR為一數據結構,在具體使用時需要轉換成其他類型的結構。對于樹形控件可能取值和對應的數據結構為:

      ·TVN_SELCHANGED 在所選中的結點發生改變后發送,所用結構:NMTREEVIEW;

      ·TVN_ITEMEXPANDED 在某結點被展開后發送,所用結構:NMTREEVIEW;

      ·TVN_BEGINLABELEDIT 在開始編輯結點字符時發送,所用結構:NMTVDISPINFO;

      ·TVN_ENDLABELEDIT 在結束編輯結點字符時發送,所用結構:NMTVDISPINFO;

      ·TVN_GETDISPINFO 在需要得到某結點信息時發送,(如得到結點的顯示字符)所用結構:NMTVDISPINFO;

      對于Visual C++ MFC提供的標準樹型控件CTreeCtrl來說,并不支持背景位圖,所以如果需要實現背景位圖就需要先讓其在內存CDC對象上對TREEVIEW缺省繪圖,然后在選擇背景位圖,與缺省位圖合成,即采用貼圖的方式,把標準的TREEVIEW窗口貼在底圖上。這個操作在內存中完成。同時為了避免閃爍,必須重載OnItemexpanding()和OnItemexpanded()這兩個函數。SetRedraw函數主要保證其不要在子節點彈出時重畫,而是在子節點已經擴展后重畫。為此,例程中定義了一個CTreeCtrl類的子類CmyTreeCtrl,并重載了以下幾個成員函數:

    BOOL CMyTreeCtrl::SetBKImage(LPCTSTR LpszResource)
    void CMyTreeCtrl::OnPaint()
    void CMyTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
    void CMyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
    BOOL CMyTreeCtrl::OnEraseBkgnd(CDC* pDC)

       二、編程步驟

      1、 啟動Visual C++6.0,生成一個基于對話框的項目Tree,在框架上放置一個樹形控制件,其ID標志符為:IDC_TREE1;

      2、 創建CmyTreeCtrl類后,使用CLASSWIZARD為其添加消息映射:

    ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED,OnItemexpanded) ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
      消息響應函數:

    afx_msg void OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult);

      3、 將樹型控件與CmyTreeCtrl類建立關聯,在對話框中添加變量CMyTreeCtrl m_CtrlTree;

      4、 制作一個準備作為樹形控件背景的位圖;

      5、 修改對話框的初始化函數BOOL CTreeDlg::OnInitDialog();

      6、 添加代碼,編譯運行程序。 陳剛

    三、實現代碼

    /////////////////////////////////////////////////
    #if !defined(AFX_TREEDLG_H__D82DB384_F574_44A7_96DA_6EC9068E22B1__INCLUDED_)
    #define AFX_TREEDLG_H__D82DB384_F574_44A7_96DA_6EC9068E22B1__INCLUDED_
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    /////////////////////////////////////////// CTreeDlg dialog
    #include "MyTreeCtrl.h"
    class CTreeDlg : public CDialog
    {
     // Construction
     public:
      CTreeDlg(CWnd* pParent = NULL); // standard constructor

      // Dialog Data
      //{{AFX_DATA(CTreeDlg)
       enum { IDD = IDD_TREE_DIALOG };
       CMyTreeCtrl m_CtrlTree;
      //}}AFX_DATA

      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CTreeDlg)
       protected:
        virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
      //}}AFX_VIRTUAL

      // Implementation
     protected:
      HICON m_hIcon;

      // Generated message map functions
      //{{AFX_MSG(CTreeDlg)
       virtual BOOL OnInitDialog();
       afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
       afx_msg void OnPaint();
       afx_msg HCURSOR OnQueryDragIcon();
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
    };

    #endif

    ////////////////////////////////// MyTreeCtrl.cpp : implementation file

    #include "StdAfx.h"
    #include "Tree.h"
    #include "MyTreeCtrl.h"
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    ////////////////////////////// CMyTreeCtrl

    CMyTreeCtrl::CMyTreeCtrl()
    {}

    CMyTreeCtrl::~CMyTreeCtrl()
    {}

    BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl)
     //{{AFX_MSG_MAP(CMyTreeCtrl)
      ON_WM_PAINT()
      ON_WM_ERASEBKGND()
      ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemexpanded)
      ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
     //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CMyTreeCtrl message handlers
    BOOL CMyTreeCtrl::SetBKImage(LPCTSTR LpszResource)
    {
     // if this is not the first call then delete gdi objects
     if( m_bitmap.m_hObject != NULL )
      m_bitmap.DeleteObject();

      HBITMAP hbmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
    LpszResource, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);

     if( hbmp == NULL )
      return FALSE;
     m_bitmap.Attach( hbmp );
     return TRUE;
    }

    LRESULT CMyTreeCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
     // TODO: Add your specialized code here and/or call the base class
     return CTreeCtrl::WindowProc(message, wParam, lParam);
    }

    void CMyTreeCtrl::OnPaint()
    {
     CPaintDC dc(this); // device context for painting
     CRect rcclient;
     GetClientRect(&rcclient);

     // create a compatible memory dc
     CDC memdc;
     memdc.CreateCompatibleDC(&dc);
     CBitmap bitmap;
     bitmap.CreateCompatibleBitmap(&dc, rcclient.Width(), rcclient.Height());
     memdc.SelectObject( &bitmap );
     CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC , 0);
     CDC maskdc;
     maskdc.CreateCompatibleDC(&dc);
     CBitmap maskbitmap;
     maskbitmap.CreateBitmap(rcclient.Width(), rcclient.Height(), 1, 1, NULL);
     maskdc.SelectObject( &maskbitmap );
     maskdc.BitBlt( 0, 0, rcclient.Width(), rcclient.Height(), &memdc,
     rcclient.left, rcclient.top, SRCCOPY);
     CBrush brush;
     brush.CreatePatternBrush(&m_bitmap);
     dc.FillRect(rcclient, &brush);
     memdc.SetBkColor(RGB(0,0,0));
     memdc.SetTextColor(RGB(255,255,255));
     memdc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &maskdc, rcclient.left,  rcclient.top, SRCAND);
     dc.SetBkColor(RGB(255,255,255));
     dc.SetTextColor(RGB(0,0,0));
     dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &maskdc, rcclient.left, rcclient.top, SRCAND);
     dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(), &memdc, rcclient.left, rcclient.top,SRCPAINT);
     brush.DeleteObject();
    }

    BOOL CMyTreeCtrl::OnEraseBkgnd(CDC* pDC)
    {
     // TODO: Add your message handler code here and/or call default
     return TRUE;
    }

    void CMyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
    {
     NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
     // TODO: Add your control notification handler code here
     Invalidate();
     SetRedraw(TRUE);
     *pResult = 0;
    }

    void CMyTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
    {
     NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
     // TODO: Add your control notification handler code here
     SetRedraw(FALSE);

     *pResult = 0;
    }

    ///////////////////////////////////////////////////////
    BOOL CTreeDlg::OnInitDialog()
    {
     CDialog::OnInitDialog();
     // Add "About..." menu item to system menu.
     // IDM_ABOUTBOX must be in the system command range.
     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
     ASSERT(IDM_ABOUTBOX < 0xF000);
     CMenu* pSysMenu = GetSystemMenu(FALSE);
     if (pSysMenu != NULL)
     {
      CString strAboutMenu;
      strAboutMenu.LoadString(IDS_ABOUTBOX);
      if (!strAboutMenu.IsEmpty())
      {
       pSysMenu-> AppendMenu(MF_SEPARATOR);
       pSysMenu-> AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
      }
     }
     // Set the icon for this dialog. The framework does this automatically
     // when the application's main window is not a dialog
     SetIcon(m_hIcon, TRUE); // Set big icon
     // TODO: Add extra initialization here
     m_CtrlTree.SetBKImage("IDB_BITMAP1");
     SetIcon(m_hIcon, FALSE); // Set small icon
     TVINSERTSTRUCT tvInsert;
     tvInsert.hParent = NULL;
     tvInsert.hInsertAfter = NULL;
     tvInsert.item.mask = TVIF_TEXT;
     tvInsert.item.pszText = _T("Visual C++編程實例");
     HTREEITEM hCountry = m_CtrlTree.InsertItem(&tvInsert);
     HTREEITEM hPA = m_CtrlTree.InsertItem(TVIF_TEXT,
     _T("文章中心"), 0, 0, 0, 0, 0, hCountry, NULL);
     HTREEITEM hWA = m_CtrlTree.InsertItem(_T("代碼中心"),0, 0, hCountry, hPA);
     m_CtrlTree.InsertItem(_T("全屏幕程序的實現"), hPA, TVI_SORT);
     m_CtrlTree.InsertItem(_T("實現窗口的任意分割"), hPA, TVI_SORT);
     m_CtrlTree.InsertItem(_T("實現菜單的自繪"), hPA, TVI_SORT);
     m_CtrlTree.InsertItem(_T("實現全屏幕顯示的代碼"), hWA, TVI_SORT);
     m_CtrlTree.InsertItem(_T("窗口任意分割的代碼"), hWA, TVI_SORT);
     m_CtrlTree.InsertItem(_T("菜單自繪代碼"), hWA, TVI_SORT);
     m_CtrlTree.Expand(hCountry,TVE_EXPAND);
     return TRUE; // return TRUE unless you set the focus to a control
    }

       四、小結

      到此為止,本例通過實現樹形控件的背景位圖介紹了一些樹視圖控件編程方法,包括樹視圖控件的建立、節點值的賦予等。當然,它應用的方面很廣,使用方法也很多。這里僅僅是涉及到了構建樹視圖控件的基本框架,讀者朋友們可以在此基礎上,可進行擴展,從而完成更強大的功能,感興趣的讀者不妨自己擴展該控件試試。陳剛

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全