分享

别人用delphi写的很简单实用的多列功能的treeview

 quasiceo 2014-03-21

别人用delphi写的很简单实用的多列功能的treeview --- treelistview

http://topic.csdn.net/t/20050628/07/4108848.html

下面是控件的源代码。你可以在这里下载源代码和   demo:http://www./test/treelistview.rar

存在的问题是:
1,滚动条如何处理?目前,水平滚动条为父控件Panel所有,垂直滚动条为子控件Treeview所有。这样处理起来是最简单的,但明显是有问题的。

欢迎各位讨论。  
如果你对源代码作了任何改进,请发一份给我qinmaofan@21cn.com,谢谢。

 

treelistview源代码如下: TreeList.pas

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
{
    Multi-column   Treeview   component   for   Borland   Delphi   7
    Name:   pTree
    Version:   1.10
    Created:   06/25/2005
    E-mail:   qinmaofan@21cn.com
    Copyright   (C)   2005   Afan   Tim
    This   is   a   simple   multi-column   treeview   component   base   on   Michal   Mecinski 's
    Multi-Column   Tree   View   (VC++   project)
    I   didn 't   want   to   use   Virtual   Treeview   as   it   is   too   complex   and   too   big.   So   I
    decide   to   wrote   a   simple   one.
    It   still   has   some   bugs   in   vertical   and   horizontal   scrollbars.   Send   one   copy
    to   me   if   you   have   make   any   modification.   Thanks   in   advance.
}
{
Control   ' '   has   no   parent   window   错误地解决方法:
    在   Constructor   中调用   Handle   时注意点即可。
}
unit   TreeList;
interface
uses
    Windows,   SysUtils,   Classes,   Controls,   ComCtrls,   messages,   ExtCtrls,   Graphics,
    CommCtrl,   math,   Forms;
const
    WM_ENDDRAGHEADER   =   WM_USER   +   380;
    WM_HEADERWIDTH   =       WM_USER   +   381;
type
    Tmyheader   =   class(THeaderControl)
    private
        trHandle:   THandle;
        procedure   CNNotify(var   msg:   TWMNotify);   message   CN_NOTIFY;
    public
        Constructor   Create(AOwner:TComponent);override;
end;
type
    TTreeList   =   class(TTreeView)
    private
        //m_cyHeader,                   {   列头高度   }
        m_xPos,                               {   水平滚动条当前位置   }
        m_xOffset:     integer;     {   rect的水平偏移   }
        arrColWidths:   array   of   DWORD;     {   列头的各列宽度,发送消息获取   }
        FHeaderFont:   TFont;
        FHighlightColor:   TColor;
        FChildHighlightTextColor:   TColor;
        FHighlightText:   TColor;
        FMaskColor:   TColor;
        FSeperator:   char;
        FColCount:   integer;
        FColsWidth:   integer;
        Function   GetNodeTextFromItem(hItem:   HTreeItem;   var   NodeText:   string):   boolean;
        procedure   SetColumnSeperator(Value:   char);
        procedure   DoDrawItem(Sender:   TCustomTreeView;   Node:   TTreeNode;   State:   TCustomDrawState;   Stage:   TCustomDrawStage;   var   PaintImages,   DefaultDraw:   Boolean);
        procedure   CNNotify(var   msg:   TWMNotify);   message   CN_NOTIFY;
    Protected
    public
        constructor   Create(AOwner:   TComponent);   override;
        Procedure   SetColArray(_arr:   array   of   integer);
        Procedure   HideHScroll;
    Published
        Property   Seperator:   char   read   FSeperator   write   SetColumnSeperator;
        Property   ColCount:   integer     read   FColCount     write   FColCount;
        Property   ColsWidth:   integer   read   FColsWidth   write   FColsWidth;
    end;
type
    TpTree   =   class(TPanel)
    private
        m_xPos:   integer;
        m_cxTotal:   integer;
        m_cyHeader:   integer;
        m_xOffset:   integer;
        FTV:   TTreeList;
        FHDR:   Tmyheader;
        Fhds:   THeaderSections;
        Procedure   MsgHeaderWidth(var   msg:Tmessage);   message   WM_HEADERWIDTH;
        Function   AllColumnWidth:   integer;
        Procedure   MsgDragSection(var   msg:Tmessage);   message   WM_ENDDRAGHEADER;
        procedure   OnHScroll(var   msg:TWMHScroll);   message   WM_HSCROLL;
        Procedure   myOnSize(var   msg:TWMSize);   message   WM_SIZE;
        Procedure   RepositionControls;
    Protected
        procedure   UpdateScroller;
    public
        constructor   Create(AOwner:   TComponent);   override;
        Procedure   UpdateColumns;
        Procedure   HideTVHScrollBar;
        Procedure   SetHDSectionWidth(const   index,   HdsWidth:   integer);
        Function   SubItemAdd(nParent,   nChild:   TTreeNode;   const   sItem:   string):   TTreeNode;
        Procedure   Clear; 
    Published
        property   tv:   TTreeList   read   FTV   write   FTV;
        property   hdr:   Tmyheader   read   Fhdr   write   Fhdr;
        property   ColumnsWidth:   integer   read   AllColumnWidth;
        property   HeaderSections:   THeaderSections     read   Fhds   write   Fhds;
    end;
procedure   Register;
type
    pDLLVERSIONINFO   =   ^DLLVERSIONINFO;
    DLLVERSIONINFO   =   record
      cbSize   :   integer;
      dwMajor   :   integer;
      dwMinor   :   integer;
      dwBuildNumber   :   integer;
      dwPlatformID   :   integer;
end;
{   取文件版本信息的结构   }
type
    PFixedFileInfo   =   ^TFixedFileInfo;
    TFixedFileInfo   =   record
          dwSignature               :   DWORD;
          dwStrucVersion         :   DWORD;
          wFileVersionMS         :   WORD;     //   次版本号
          wFileVersionLS         :   WORD;     //   主版本号
          wProductVersionMS   :   WORD;     //   建立次数(build)
          wProductVersionLS   :   WORD;     //   发行次数(release)
          dwFileFlagsMask       :   DWORD;
          dwFileFlags               :   DWORD;
          dwFileOS                     :   DWORD;
          dwFileType                 :   DWORD;
          dwFileSubtype           :   DWORD;
          dwFileDateMS             :   DWORD;
          dwFileDateLS             :   DWORD;
    end;
const
        TVS_NOHSCROLL   =   $8000;
        Node_Text_Len_1   =   128;
        Node_Text_Len_2   =   512;
implementation
{   缩减矩形面积   }
Procedure   DeflateRect(var   rect:TRECT;   w,h:integer);
begin
    Inc(rect.Left,   w);
    Dec(rect.Right,   w);
    Inc(rect.Top,   h);
    Dec(rect.Bottom,   h);
end;
//下面是取版本信息函数
Function   FileVersionInfo(   const   FileName:String;   var   Major:DWORD):boolean;
var
    dwHandle,   dwVersionSize,   pulen   :   DWORD;
    strSubBlock                           :   String;
    pTemp                                       :   Pointer;
    pData                                       :   Pointer;
    FixedFileInfo                       :   pFixedFileInfo;
begin
    result:=   false;
    strSubBlock   :=   '\ ';
    //   取得文件版本信息的大小
    dwVersionSize   :=   GetFileVersionInfoSize(PChar(FileName),   dwHandle   );
    if   dwVersionSize   <>   0   then     begin
        GetMem(pTemp,   dwVersionSize);
        try
        //取文件版本信息
      if   GetFileVersionInfo(PChar(   FileName   ),dwHandle,dwVersionSize,pTemp   )   then
          if   VerQueryValue(pTemp,PChar(   strSubBlock   ),pData,pulen)   then   begin
              Result   :=   true;
              FixedFileInfo:=   pData;
              Major:=   FixedFileInfo^.wFileVersionLS;
          end;
        finally
            FreeMem(pTemp,   dwVersionSize);
        end;
    end;
end;
Function   FullPath(fname:string):   string;
var
    filepart,buffer:pchar;
    err,cbLen:   dword;
begin
    result:=   ' ';
    cbLen:=   0;
    cbLen:=   Searchpath(nil,   pchar(fname),   nil,   0,   nil,   filepart);
    if   cbLen   =   0   then   exit;
    GetMem(buffer,   cbLen   +   1);
    err:=   Searchpath(nil,   pchar(fname),   nil,   cbLen,   buffer,   filepart);
    if   err   <>   0   then
        result:=   string(buffer);
    freemem(buffer);
end;
procedure   Register;
begin
    RegisterComponents( 'Samples ',   [TpTree]);
end;
//============================================================================//
{   TTreeList   }
constructor   TTreeList.Create(AOwner:   TComponent);
var
    bIsComCtl6:   boolean;
    v:   dword;
    s:   string;
    size:   TSize;
    sect:   THeaderSection;
begin
    inherited   Create(AOwner);
    ToolTips:=   false;
    Readonly:=   true;
    //HideHScroll;
    SetLength(arrColWidths,   1);
    FSeperator   :=   '| ';
//   check   if   the   common   controls   library   version   6.0   is   available
bIsComCtl6   :=   FALSE;
    v:=   0;
    s:=   Fullpath( 'comctl32.dll ');
    if   s   <>   ' '   then
        if   FileVersionInfo(s,   v)   and   (v   > =6)   then
            bIsComCtl6:=   true;
    if   bIsComCtl6   then
        m_xOffset:=   9
    else
        m_xOffset   :=   6;
m_xPos   :=   0;
    //OnAdvancedCustomDrawItem:=   DoDrawItem;
end;
procedure   TTreeList.SetColumnSeperator(Value:   char);
begin
    FSeperator   :=   Value;
end;
procedure   TTreeList.SetColArray(_arr:   array   of   integer);
var
    i,len:   integer;
begin
    len:=   Length(_arr);
    SetLength(arrColWidths,   len);
    ZeroMemory(@arrColWidths[0],   SizeOf(arrColWidths));
    For   i:=   low(_arr)   to   high(_arr)   do
        arrColWidths[I]:=   _arr[I];
end;
procedure   TTreeList.CNNotify(var   msg:   TWMNotify);
var
    nmDraw:   pNMCUSTOMDRAW;
    tvDraw:   pNMTVCustomDraw;
    hItem:   HTREEITEM;
    aBrush,OldBrush:   hBrush;
    rcLabel,rcText,rcItem:   TRECT;
    dc:   hDC;
    crTextBk,crWnd,crText:   dword;
    i,k,xOffset,MainWidth:   integer;
    strNode,strSub:   string;
    uDrawMode:UINT   ;
    HasChildren:   boolean;
begin
    if   msg.NMHdr.code   <>   NM_CUSTOMDRAW   then   begin
        inherited;
        exit;
    end;
    nmDraw:=     pNMCUSTOMDRAW(pointer(msg.NMHdr));
    tvDraw:=     pNMTVCUSTOMDRAW(pointer(msg.NMHdr));
    case   nmDraw.dwDrawStage   of
        CDDS_PREPAINT:
            msg.Result   :=   CDRF_NOTIFYITEMDRAW;
        CDDS_ITEMPREPAINT:
            msg.Result   :=   CDRF_DODEFAULT   or   CDRF_NOTIFYPOSTPAINT;
        CDDS_ITEMPOSTPAINT:
        begin
            rcItem:=   nmDraw.rc;
            if   IsRectEmpty(rcItem)   then   begin
                msg.Result   :=   CDRF_DODEFAULT;
                exit;
            end;
            hItem:=   HTreeItem(nmDraw.dwItemSpec);
            if   not   GetNodeTextFromItem(hItem,   strNode)   then   begin
                exit;
            end;
            strSub:=   ' ';
            //HasChildren:=   TreeView_GetChild(handle,   hItem)   <>   nil;
            HasChildren:=   Pos(FSeperator,   strNode)   =   0;
            {   Send   message   to   parent   window   to   get   header   information   }
            if   not   Boolean(SendMessage(Parent.Handle,   WM_HEADERWIDTH,   0,   0))   then
                exit;
            if   FColCount   =   0   then   exit;
            dc:=   nmDraw.hdc;
            Treeview_GetItemRect(handle,   hItem,   rcLabel,   true);
            if   rcLabel.Right   > =   Width   then
                HideHScroll;
            crTextBk:=   tvDraw.clrTextBk;
            //clrText:=   GetSysColor(COLOR_WINDOWTEXT);                       {   font   and   background   color   }
            crWnd:=   GetSysColor(COLOR_WINDOW);
          {   clear   the   original   label   rectangle   }
            aBrush:=   CreateSolidBrush(crWnd);
            //OldBrush:=   SelectObject(dc,   aBrush);
            rcLabel.Right   :=   max(FColsWidth   -   2,   rcLabel.Right);
            FillRect(dc,   rcLabel,   aBrush);
            DeleteObject(aBrush);
            //SelectObject(dc,   OldBrush);
{
            if   nmDraw.dwDrawStage   and   CDIS_SELECTED   =   CDIS_SELECTED   then   begin
                //clrBackground   :=   GetSysColor(COLOR_BTNFACE);
                crText   :=   GetSysColor(COLOR_WINDOWTEXT);
            end;
            if   nmDraw.dwDrawStage   and   CDIS_FOCUS   =   CDIS_FOCUS   then   begin
                //clrBackground   :=   GetSysColor(COLOR_HIGHLIGHT);
                crText   :=   GetSysColor(COLOR_HIGHLIGHTTEXT);
            end;
}
            if   HasChildren   then
                strSub:=   strNode
            else   begin
                k:=   Pos(FSeperator,   strNode);
                if   k   >   0   then   begin
                    strSub:=   Copy(strNode,   1,   k-1);
                    System.Delete(strNode,   1,   k);
                end
                else   begin
                    strSub:=   strNode;
                    strNode:=   ' ';
                end;
            end;
            //   calculate   main   label 's   size
            ZeroMemory(@rcText,   SizeOf(rcText));
            DrawText(DC,   pchar(strSub),   Length(StrSub),   rcText,   DT_NOPREFIX   or   DT_CALCRECT);
            MainWidth:=   min(rcLabel.left   +   rcText.right   +   4,   arrColWidths[0]   -   4);
            rcLabel.Right   :=   FColsWidth   -   2;
            SetBkColor(dc,   crTextBk);                                                                 {   如果没有这行,view中第一个节点显示就有问题   }
            if   rcLabel.right   -   rcLabel.Left   <   0   then
                crTextBk   :=   crWnd;
            //   draw   label 's   background
            if   crTextBk   <>   crWnd   then   begin
                aBrush:=   CreateSolidBrush(crTextBk);
                FillRect(dc,   rcLabel,   aBrush);
                DeleteObject(aBrush);
            end;
            SetTextColor(dc,   tvDraw.clrText);
            //SetTextColor(dc,   crText);
            //   draw   main   label
            rcText   :=   rcLabel;
            if   not   HasChildren   then
                rcText.Right   :=   MainWidth;
            DeflateRect(rcText,   2,   1);
            DrawText(DC,   pchar(strSub),   Length(StrSub),   rcText,   DT_NOPREFIX   or   DT_END_ELLIPSIS);
            xOffset   :=   arrColWidths[0];
            SetBkMode(dc,   TRANSPARENT);
            if   not   HasChildren   then   begin
                //SetTextColor(dc,   GetSysColor(COLOR_WINDOWTEXT));
                for   i:=   1   to   Length(arrColWidths)   -   1   do   begin
                    k:=   Pos(FSeperator,   strNode);
                    if   k   >   0   then   begin
                        strSub:=   Copy(strNode,   1,   k-1);
                        System.Delete(strNode,   1,   k);
                    end
                    else   begin
                        strSub:=   strNode;
                        strNode:=   ' ';
                    end;
                    rcText   :=   rcLabel;
                    rcText.left   :=   xOffset;
                    rcText.right   :=   xOffset   +   arrColWidths[I];
                    Inc(rcText.Left,   m_xOffset);
                    Dec(rcText.Right,   1);
                    Inc(rcText.Top,   2);
                    Dec(rcText.Bottom,   1);
                    DrawText(DC,   pchar(strSub),   Length(strsub),   rcText,   DT_NOPREFIX   or   DT_END_ELLIPSIS);
                    Inc(xOffset,   arrColWidths[I]);
                end;   {of   FOR}
            end;
{
                //   draw   focus   rectangle   if   necessary
                if   nmDraw.uItemState   and   CDIS_FOCUS   =   CDIS_FOCUS   then
                    DrawFocusRect(dc,   rcLabel);
}
            msg.Result   :=   CDRF_DODEFAULT;
        end;
        else
            msg.Result   :=   CDRF_DODEFAULT;
    end;   {of   CASE}
end;
{   获取节点的文字   }
function   TTreeList.GetNodeTextFromItem(hItem:   HTreeItem;   var   NodeText:   string):   boolean;
var
    tvi:   TTVItem;
begin
    result:=   true;
    NodeText:=   ' ';
    Fillchar(tvi,   SizeOf(tvi),   0);
    tvi.hItem:=   hItem;
    tvi.mask   :=   TVIF_TEXT;
    tvi.cchTextMax:=   Node_Text_Len_1;
    GetMem(tvi.pszText,   Node_Text_Len_1);
    if   not   Treeview_GetItem(handle,   tvi)   then   begin
        FreeMem(tvi.pszText);
        result:=   false;
        exit;
    end;
    NodeText:=   Trim(tvi.pszText);
    FreeMem(tvi.pszText);
    if   Length(NodeText)   > =   Node_Text_Len_1   -   1   then   begin
        Fillchar(tvi,   SizeOf(tvi),   0);
        tvi.hItem:=   hItem;
        tvi.mask   :=   TVIF_TEXT;
        tvi.cchTextMax:=   Node_Text_Len_2;
        GetMem(tvi.pszText,   Node_Text_Len_2);
        if   not   Treeview_GetItem(handle,   tvi)   then   begin
            FreeMem(tvi.pszText);
            exit;
        end;
        NodeText:=   Trim(tvi.pszText);
        FreeMem(tvi.pszText);
    end;
end;
procedure   TTreeList.HideHScroll;
begin
    ShowScrollBar(Handle,   SB_HORZ,   false);
end;
//===========================================================================//
{   Tmyheader   }
constructor   Tmyheader.Create(AOwner:   TComponent);
begin
    inherited   Create(AOwner);
end;
procedure   Tmyheader.CNNotify(var   msg:   TWMNotify);
var
    code:   integer;
    hditem:   HD_ITEM;
begin
    inherited;
    code:=   PHDNotify(msg.NMHdr)^.Hdr.code;
    if   (code   =   HDN_ENDTRACKW)   or   (code   =   HDN_ENDTRACK)   then   begin
        {   列头的宽度不应该在这里求,没有变   }
        {   Post   message   to   get   columns   width   }
        PostMessage(Parent.Handle,   WM_ENDDRAGHEADER,   0,   0);
    end;
end;
//===========================================================================//
{   TpnlTreeview   }
constructor   TpTree.Create(AOwner:   TComponent);
var
    bIsComCtl6:   boolean;
    v:   DWORD;
    s:   string;
begin
    inherited   Create(AOwner);
    caption:=   ' ';
    BevelInner:=   bvNone;
    BevelOuter:=   bvNone;
    Self.BorderStyle:=   bsSingle;
    m_xPos:=   0;
    m_cxTotal:=   0;
    Fhdr:=   Tmyheader.Create(self);
    with   Fhdr   do   begin
        Parent   :=   Self;
        Align   :=   alTop;
        Name   :=   'Header1 ';
        Fhds:=   Sections;
    end;
    Ftv:=   TTreeList.Create(self);
    with   Ftv   do   begin
        Parent   :=   Self;
        HideSelection:=   false;
        RowSelect:=   true;
        Align   :=   alClient;
        BevelInner:=   bvNone;
        BevelOuter:=   bvNone;
        BorderStyle:=   bsNone;
        BevelEdges:=   [];
        Ctl3D   :=   false;
        Name   :=   'Treeview1 ';
        //HideHScroll;
    end;
    Fhdr.Align   :=   alNone;
    Ftv.Align   :=   alNone;
//   check   if   the   common   controls   library   version   6.0   is   available
bIsComCtl6   :=   FALSE;
    v:=   0;
    s:=   Fullpath( 'comctl32.dll ');
    if   s   <>   ' '   then
        if   FileVersionInfo(s,   v)   and   (v   > =6)   then
            bIsComCtl6:=   true;
    if   bIsComCtl6   then
        m_xOffset:=   9
    else
        m_xOffset   :=   6;
m_xPos   :=   0;
    if   bIsComCtl6   then
        m_cyHeader:=   7
    else
        m_cyHeader:=   4;
    //UpdateColumns;
end;
{   Header发送列头改变的消息给父组件,然后父组件处理滚动条和treeview重绘   }
{   This   event   notified   by   Header   }
procedure   TpTree.MsgDragSection(var   msg:   Tmessage);
begin
    UpdateColumns();
    Ftv.Invalidate;
end;
{   子控件发送消息要求取列头宽度数据   }
{   Get   columns   width   in   Header   }
procedure   TpTree.MsgHeaderWidth(var   msg:   Tmessage);
var
    arr:   array   of   integer;
    i,k,w:   integer;
    hdItem:   HD_ITEM;
begin
    k:=   Fhdr.Sections.Count   ;
    w:=   0;
    SetLength(arr,   k);
    for   i:=   0   to   k   -   1   do   begin
        Fillchar(hdItem,   SizeOf(hdItem),   0);
        hdItem.Mask:=   HDI_WIDTH;
        if   Header_GetItem(Fhdr.Handle   ,   i,   hdItem)   then   begin
            arr[I]:=   hdItem.cxy;
            Inc(w,   hdItem.cxy);
        end;
    end;
    Ftv.ColCount:=   k;
    Ftv.ColsWidth:=   w;
    Ftv.SetColArray(arr);
    msg.Result   :=   1;
end;
function   TpTree.AllColumnWidth:   integer;
var
    i,k:   integer;
    hdItem:   HD_ITEM;
begin
    result:=   0;
    k:=   Fhdr.Sections.Count   ;
    for   i:=   0   to   k   -   1   do   begin
        Fillchar(hdItem,   SizeOf(hdItem),   0);
        hdItem.Mask:=   HDI_WIDTH;
        if   Header_GetItem(Fhdr.Handle   ,   i,   hdItem)   then
            Inc(result,   hdItem.cxy);
    end;
end;
{   Panel大小改变时,更新滚动条和重新定位字控件的位置   }
{   Update   scrollbar,   Header,   Treeview   after   panel 's   size   changed   }
procedure   TpTree.myOnSize(var   msg:   TWMSize);
begin
    inherited;
UpdateScroller();
RepositionControls();
end;
{   设置水平滚动条   }
procedure   TpTree.OnHScroll(var   msg:   TWMHScroll);
var
    xLast:   integer;
begin
    xLast:=   m_xPos;
    case   msg.ScrollCode   of
        SB_LINELEFT:
            Dec(m_xPos,   15);
        SB_LINERIGHT:
            Inc(m_xPos,   15);
        SB_PAGELEFT:
            Dec(m_xPos,   width);
        SB_PAGERIGHT:
            Inc(m_xPos,   width);
        SB_LEFT:
            m_xPos   :=   0;
        SB_RIGHT:
            m_xPos   :=   m_cxTotal   -   width;
        SB_THUMBTRACK:
            m_xPos   :=   msg.Pos;
    end;
    if   m_xPos   <   0   then
        m_xPos:=   0
    else   if   m_xPos   >   m_cxTotal   -   width   then
        m_xPos:=   m_cxTotal   -   width;
    if   xLast   =   m_xPos   then   exit;
    SetScrollPos(handle,   SB_HORZ,   m_xPos,   true);
    RepositionControls();
end;
{   移动   Treeview   和   header   的位置   }
{   Move   Header   and   Treeview   in   panel   while   scrolling   }
procedure   TpTree.RepositionControls;
var
    x,cx,cy:   integer;
begin
    if   self.HandleAllocated   then   begin
        cx:=   Width;
        cy:=   Height;
        x:=   0;
        if   cx   <   m_cxTotal   then   begin
            x   :=   GetScrollPos(handle,   SB_HORZ);
            Inc(cx,   x);
        end;
        MoveWindow(Fhdr.Handle,   -x,   0,   cx,   Fhdr.Height,   true);
        MoveWindow(Ftv.Handle,   -x,   Fhdr.Height,   cx,   cy   -   Fhdr.Height,   true);
    end;
end;
procedure   TpTree.UpdateColumns;
begin
    if   not   HandleAllocated   then   exit;
    m_cxTotal:=   AllColumnWidth   ;
    Ftv.Width   :=   m_cxTotal;
UpdateScroller();
RepositionControls();
end;
{   更新水平滚动条   }
procedure   TpTree.UpdateScroller;
var
    si:   ScrollInfo;
    i:   integer;
begin
    if   m_xPos   >   m_cxTotal   -   width   then
        m_xPos:=   m_cxTotal   -   width;
    if   m_xPos   <   0   then
        m_xPos:=   0;
    FillChar(si,   sizeof(si),   0);
si.cbSize   :=   sizeof(si);
si.fMask   :=   SIF_PAGE   or   SIF_POS   or   SIF_RANGE;
si.nPage   :=   width;
si.nMin   :=   0;
si.nMax   :=   m_cxTotal;
si.nPos   :=   m_xPos;
SetScrollInfo(handle,   SB_HORZ,   si,   true);
end;
procedure   TpTree.HideTVHScrollBar;
begin
    ShowScrollBar(Ftv.Handle,   SB_HORZ,   false);
end;
{   Change   header   section '   width   and   invalidate   }
procedure   TpTree.SetHDSectionWidth(const   index,   Hdswidth:   integer);
begin
    if   HeaderSections.Count   >   index   then
        if   HeaderSections[index].Width   <>   HdsWidth   then   begin
            HeaderSections[Index].Width:=   HdsWidth;
            Ftv.Invalidate;
        end;
end;
{   Clear   all   items   in   treeview   }
procedure   TpTree.Clear;
begin
    Ftv.Items.Clear;
end;
{   Add   column   item   (child   node)   to   nParent   treenode     }
function   TpTree.SubItemAdd(nParent,   nChild:   TTreeNode;   const   sItem:   string):   TTreeNode;
var
    s:   string;
begin
    {   The   first   column   }
    if   nChild   =   nil   then
        result:=   Ftv.Items.AddChild(nParent,   sItem)
    {   Other   column   }
    else   begin
        s:=   nChild.Text   ;
        s:=   s   +   tv.Seperator   +   sItem;
        nChild.Text   :=   s;
    end;
end;
end.

 

 

 

vc源码本地下载URL:

posted on 2010-12-16 16:14 chulia 阅读(571) 评论(4) 编辑 收藏

评论

#1楼[楼主]   

本文作者在CSDN上的ID是:qinmaofan
CSDN上的网址是:http://blog.csdn.net/qinmaofan
http://feeds./csdn.net/qinmaofan

该作者最重要的特点是---他是一个共享软件开发者。
2010-12-20 11:00 | chulia  

#2楼[楼主]   

2010-12-20 16:38 | chulia  

#3楼[楼主]   

delphi中点击tree conctol时如何得到此item的HTREEITEM结构数据?
http://www./show-TlRjd05UWTQ=.html
1楼:
CPoint point(::GetMessagePos());
m_treectrl.ScreenToClient(&point);
UINT Flags;
HTREEITEM hItem = m_treectrl.HitTest(point, &Flags);
或者
HTREEITEM hItem = m_treectrl.GetSelectedItem();

2楼:在TV_ITEMEXPANDING事件中加入
while(bWorking){
bWorking = finder.FindNextFile();
if(finder.IsDirectory()){
TreeCtrlItem.hParent=hTreeItem;//主要是这个我想在点击d:时把d:下的子目录链上去
TreeCtrlItem.item.lParam=10;
pTxt=new char[strlen(finder.GetFileName())+1];
strcpy(pTxt, finder.GetFileName());
TreeCtrlItem.item.pszText=pTxt;
m_Path_TreeCtrl.InsertItem(&TreeCtrlItem);
delete pTxt;
TRACE("\nhehe=%s\n",finder.GetFileName());
}
//TRACE("\nkankan");
}
3楼:HTREEITEM hParent=((LPNMTREEVIEW)lParam)->itemNew.hItem;

你的TreeCtrlItem是什么?是TVINSERTSTRUCT吗?如果是,则你的写法似乎有点问题。
TVINSERTSTRUCT tvis;
tvis.hParent=hParent;
tvis.hInsertAfter=TVI_LAST;
TVITEM tvi;
tvi.mask=TVIF_TEXT|TVIF_PARAM;
tvi.pszText=szText;
tvi.cchTextMax=lstrlen(szText)+1;
tvi.lParam=10;
tvis.item=tvi;
m_Path_TreeCtrl.InsertItem(&tvis);



4楼:谢谢!HTREEITEM hParent=((LPNMTREEVIEW)pNMHDR)->itemNew.hItem;
就是这个问题解决的非常感谢。都很多天了.

2010-12-21 23:06 | chulia  

#4楼[楼主]   

想写一个树型结构的控件,请各位指导一下?谢谢先
http:///t3144806.html
wildacj 题问:大概操作是:先有一个图片按钮,点击以后出现下一级字按钮,用图片线连接。谢谢!

57808475 2004-10-20 12:48
要用到什么??调用哪些类库

wildacj 2004-10-20 14:52
就是,我需要用C++写出来的,谢谢先

Polarislee 2004-10-20 15:40
你要写还是要用,Windows提供的控件里就有Tree

wildacj 2004-10-20 15:56
是想写,不用MFC,大概的意思是有一张按钮的图片放到窗口上,点击该图片出现子目录按钮,用OPENGL来写,怎么写呢?

nlstone 2004-10-20 17:34
数据结构很简单,网上有很多现成的树的类库或者模板库
完全自己来画?麻烦......:)

wildacj 2004-10-21 08:57
就是觉得很困难才来问问看的啊,哪为老兄能给点思路呢

lynnboy 2004-10-21 09:33
用一个二叉树保存树结构,绘图并保存绘图位置。
保护一个当前焦点的记录索引itemCurr,
获取键盘和鼠标事件,通过图形坐标计算出所操作的item,转换成item事件,
处理item事件并重新绘制。

nlstone 2004-10-21 11:57
很困难也不至于,麻烦是在于"画"的那部分,而不是在数据结构方面,树可以直接找现成的.

TO:楼上,怎么会用"二叉树"?

显示重绘的时候实际上也是一个对显示当前结点的显示函数的递归调用,但要注意保留计算保留当前层的一些坐标信息,譬如说前一个兄弟结点显示完后(有可能展开),才能算出当前结点的Y坐标,而这个Y是根据前一个兄弟结点的Y坐标以及它的子结点的展开算出来的(递归过程中需要进行统计)

总的来说,是个细活,仔细考虑吧...



nlstone 2004-10-21 11:58
最好是找个合适的控件或者完整的类库:)
非MFC的OpenGL的应该也有...

wildacj 2004-10-21 15:00
nlstone(天外流星):最好是找个合适的控件或者完整的类库:)
非MFC的OpenGL的应该也有...

这个是什么意思?哪里去找呢?

nlstone 2004-10-21 23:01
譬如说很多游戏开发方面的资源,或者一些OpenGL社区/网站,"也许"有一些资源可以用.
毕竟这种OpenGL/DX显示模式下的树形显示结构在娱乐行业应用还是很多的.
这方面我不擅长,所供建议,仅供参考...

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多