全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:5641
推到 Plurk!
推到 Facebook!

Tree-List views 設計範例

 
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-01-06 15:42:32 IP:61.218.xxx.xxx 未訂閱

Tree-List views

By David Bridges 資料來源: http://www.bridgespublishing.com One of the big advantages that Borland C Builder has over other C development environments is its ease of building sophisticated user interfaces. Chances are that if you have developed any kind of database application, you’ve used the TListView class, which is a wrapper for the Windows ListView common control. Many times I’ve wanted the ListView control to do more than it does (it already does a lot, but I always want more!). Specifically, there are times when I need to display hierarchical data as in the TreeView control. However, one of the disadvantages of using the TreeView control is that it doesn’t support multiple columns of data. What I really want to have is a "TreeListView" control that does both. You can see an example of this kind of control in the C Builder Project Manager window (shown in Figure A). This is a "TreeListView" type of control—it’s a standard TreeView control but it also shows additional data in a column to the right. 8Figure A The TTreeView class allows creating TreeView controls with extended columns such as the Project Manager window. As it turns out, it’s not too hard to do this. All that’s needed is a little custom drawing and a header control that’s associated with the TreeView. The TTLVController class As I have often done before, I have implemented my new control type as a "Controller" class—a non-visual component that binds other objects together and handles interaction between them. To use this class, you simply create an instance of it and bind it to an existing TTreeView and THeaderControl, and it automatically adds the "TreeListView" behavior. This is demonstrated in Listing A. Figure B shows the TreeListView in action. When the header columns are resized, the column text moves along with it, just as in a ListView. Figure B A winow created by TTreeListView. Now let’s take a look at what the TTLVController class does. In its constructor, it "binds" itself to a TTreeView and a THeaderControl by installing its own handlers for the TreeView’s OnAdvancedCustomDraw event and the Header’s OnSectionTrack event. The HeaderSectionTrack function simply invalidates the TreeView, causing it to re-draw. This ensures that the text will always be redisplayed after resizing a column header. The AdvancedCustomDrawItem function is where most of the work takes place. The OnAdvancedCustomDrawItem event of TTreeView allows you to write custom code for drawing a TreeView item. I have chosen to take advantage of some of the default drawing of TTreeView, such as the image icons. Therefore, the function only draws the text when the DrawStage is cdPostPaint. This will have the effect of drawing on top of what has already been drawn for the list view item. Having a good deal of experience with the Windows GDI functions, I’ve chosen to grab the device context handle of the TreeView and use the GDI functions to do the drawing, rather than using the TCanvas functions. In a nutshell, the function goes through each column of the header control and calculates the rectangular area to be drawn for the "cell" of data. Then it decides what foreground and background color to use, then fires the OnGetItemInfo event to get the actual data to be drawn. Implementing the "data getter" using an event allows the component to be independent of any application logic, and allows it to be easily reused. Conclusion TTLVController is a relatively simple component, which can add some nice functionality to the TTreeView class, and demonstrates the use of application independent code for extending user interface controls. Listing A
#include     #pragma hdrstop         #include "Demo.h"    #include "treelistview.h"         #pragma package(smart_init)    #pragma resource "*.dfm"    TDemoForm *DemoForm;         // Sample data for the TreeList view    struct ListItem {      char* name;      char* address;      char* city;    };    #define ITEM_COUNT 3    ListItem DemoData[] = {      {"Montgomery Burns", "344 Oakwood Ave.",         "Springfield"},      {"Dr. Zoidburg",  "512 Galactic Expressway",        "New New York"},      {"Dale Gribble", "99 Circle Court", "Arlen"}    };         __fastcall TDemoForm::TDemoForm(TComponent* Owner)      : TForm(Owner)    {      // Insert data      for (int i = 0; i < ITEM_COUNT; i  ) {        TTreeNode* node = tvItems->Items->AddObject(          NULL, DemoData[i].name, &DemoData[i]);             // Add some sub-items        TTreeNode* child;        child =           tvItems->Items->AddChild(node, "Subitem 1");        child->ImageIndex = 1;        child->SelectedIndex = 1;        child =           tvItems->Items->AddChild(node, "Subitem 2");        child->ImageIndex = 1;        child->SelectedIndex = 1;           }           // Create the TreeListView controller      TTLVController* TreeListView =         new TTLVController(this, hdrMain, tvItems);      TreeListView->OnGetItemInfo = GetListItemInfo;    }         // This event handler will be called whenever    // a column of data needs to be refreshed.    void __fastcall TDemoForm::GetListItemInfo(      TObject* Sender, TTreeNode* Node, int Column,      AnsiString &ItemText, TColor& ItemColor)    {      // Get data      ListItem* data =         reinterpret_cast(Node->Data);      if (data) {        // Get the text for the column        switch (Column) {          case 0: ItemText = data->name; break;          case 1: ItemText = data->address; break;          case 2: ItemText = data->city; break;        }      }    }         void __fastcall TDemoForm::btnCloseClick(      TObject *Sender)    {      Close();    }         Listing B
// TREELISTVIEW.H         #ifndef TreeListViewH    #define TreeListViewH         // Event handler type to get the item text & color    // for an object in the tree view    typedef void __fastcall       (__closure *TGetTLVItemInfoEvent)      (System::TObject* Sender, TTreeNode* Node,      int iColumn, AnsiString &sItemText,       TColor&    clItemColor);         class TTLVController : public TComponent    {      protected:      THeaderControl* Header;      TTreeView*      Tree;           public:           __fastcall TTLVController(TComponent* AOwner,       THeaderControl* AHeader, TTreeView* ATreeView);           __fastcall ~TTLVController();           // Events      TGetTLVItemInfoEvent OnGetItemInfo;           // Event Handlers      void __fastcall HeaderSectionTrack(        THeaderControl *HeaderControl,        THeaderSection *Section,        int Width, TSectionTrackState State);           void __fastcall AdvancedCustomDrawItem(        TCustomTreeView *Sender, TTreeNode *Node,        TCustomDrawState State,TCustomDrawStage Stage,         bool &PaintImages, bool &DefaultDraw);    };         #endif         Listing B
// TREELISTVIEW.CPP         #include     #pragma hdrstop         #include "TreeListView.h"              #pragma package(smart_init)         // TreeListView Controller implementation    __fastcall TTLVController::TTLVController(      TComponent* AOwner, THeaderControl* AHeader,      TTreeView* ATreeView) : TComponent(AOwner)    {      OnGetItemInfo = NULL;      Header = AHeader;      Tree = ATreeView;           // Install handlers for custom drawing      // and header tracking      Tree->OnAdvancedCustomDrawItem =         AdvancedCustomDrawItem;      Header->OnSectionTrack = HeaderSectionTrack;    }         __fastcall TTLVController::~TTLVController()    {    }         void __fastcall TTLVController::HeaderSectionTrack(      THeaderControl *HeaderControl,      THeaderSection *Section, int Width,      TSectionTrackState State)    {      // When the user finishes dragging a header      // column, redraw the TreeView      if (State == tsTrackEnd) {        Tree->Invalidate();      }    }              void __fastcall TTLVController::AdvancedCustomDrawItem(      TCustomTreeView *Sender, TTreeNode *Node,      TCustomDrawState State, TCustomDrawStage Stage,      bool &PaintImages, bool &DefaultDraw)    {      DefaultDraw = true;      PaintImages = true;           // Only process if mode is ‘cdPostPaint’, that      // way the custom drawing happens on top of the       // default drawing.      if (Stage == cdPostPaint) {        RECT NodeRect;        RECT LineRect;        NodeRect = Node->DisplayRect(true);        LineRect = Node->DisplayRect(false);        HDC hDC = Sender->Canvas->Handle;             COLORREF clBackground =           GetSysColor(COLOR_WINDOW);        COLORREF clText =           GetSysColor(COLOR_WINDOWTEXT);             if (State.Contains(cdsSelected)) {          clBackground = GetSysColor(COLOR_BTNFACE);          clText = GetSysColor(COLOR_WINDOWTEXT);        }        if (State.Contains(cdsFocused)) {          clBackground = GetSysColor(COLOR_HIGHLIGHT);          clText = GetSysColor(COLOR_HIGHLIGHTTEXT);        }             SetBkColor(hDC, clBackground);             // Iterate through all of the columns of the         // header control. For each column, fire the         // ‘OnGetItemInfo’ event to get column text.        THeaderSections* sections = Header->Sections;        RECT rect = NodeRect;        for (int i = 1; i < sections->Count; i  ) {          THeaderSection* sect = sections->Items[i];          AnsiString sText = "";          if (OnGetItemInfo) {            OnGetItemInfo(              this, Node, i, sText, clText);          }          SetTextColor(hDC, clText);          UINT uDrawMode = DT_LEFT;          if (sect->Alignment == taRightJustify) {            uDrawMode =  DT_RIGHT;          }          uDrawMode |= DT_SINGLELINE |             DT_NOPREFIX | DT_END_ELLIPSIS;               rect.left = sect->Left;          rect.right = rect.left   sect->Width;          DrawText(hDC, sText.c_str(),             sText.Length(), &rect, uDrawMode);        }             // Draw focus rectangle if focused        if (State.Contains(cdsFocused)) {          DrawFocusRect(hDC, &LineRect);        }      }    }
Copyright © 2002, Bridges Publishing. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Bridges Publishing is prohibited. All other product names and logos are trademarks or registered trademarks of their respective owners. 聯盟----Visita網站http://www.vista.org.tw ---[ 發問前請先找找舊文章 ]--- 發表人 - axsoft 於 2003/01/07 12:16:30
skcc
中階會員


發表:36
回覆:96
積分:88
註冊:2002-08-28

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-01-09 15:38:38 IP:203.198.xxx.xxx 未訂閱
謝謝 axsoft 大大分享。不過小弟依文件實作,好像有一些問題。問題是在執期間,若在 TTreeListView 元件 select 其中一項目後,若跳選另外一項目時,會出現四方的虛線在上一次所選的項目上。 其情況如下圖: 這問題可以解決嗎? Anthony Lee
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-01-10 11:22:20 IP:61.218.xxx.xxx 未訂閱
引言: 謝謝 axsoft 大大分享。不過小弟依文件實作,好像有一些問題。問題是在執期間,若在 TTreeListView 元件 select 其中一項目後,若跳選另外一項目時,會出現四方的虛線在上一次所選的項目上。 其情況如下圖: 這問題可以解決嗎? Anthony Lee
因Post出來的文章有掉Code的現象,您參考原始的文章試試! http://www.bridgespublishing.com/articles/0702/July02-02.htm 聯盟----Visita網站http://www.vista.org.tw ---[ 發問前請先找找舊文章 ]---
skcc
中階會員


發表:36
回覆:96
積分:88
註冊:2002-08-28

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-01-10 12:07:33 IP:203.198.xxx.xxx 未訂閱
引言: 因Post出來的文章有掉Code的現象,您參考原始的文章試試! http://www.bridgespublishing.com/articles/0702/July02-02.htm 聯盟----Visita網站http://www.vista.org.tw ---[ 發問前請先找找舊文章 ]---
謝謝 axsoft 大大,我自己看看吧。 Anthony Lee
系統時間:2024-04-24 19:54:01
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!