{\rtf1\ansi\ansicpg1252\uc1 \deff28\deflang1031\deflangfe1031{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;} {\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f14\fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;}{\f28\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Verdana;} {\f29\fmodern\fcharset0\fprq1{\*\panose 020d0409020203030204}Orator10 BT;}{\f154\froman\fcharset238\fprq2 Times New Roman CE;}{\f155\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f157\froman\fcharset161\fprq2 Times New Roman Greek;} {\f158\froman\fcharset162\fprq2 Times New Roman Tur;}{\f159\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f160\froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f161\froman\fcharset186\fprq2 Times New Roman Baltic;} {\f170\fmodern\fcharset238\fprq1 Courier New CE;}{\f171\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f173\fmodern\fcharset161\fprq1 Courier New Greek;}{\f174\fmodern\fcharset162\fprq1 Courier New Tur;} {\f175\fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f176\fmodern\fcharset178\fprq1 Courier New (Arabic);}{\f177\fmodern\fcharset186\fprq1 Courier New Baltic;}{\f378\fswiss\fcharset238\fprq2 Verdana CE;}{\f379\fswiss\fcharset204\fprq2 Verdana Cyr;} {\f381\fswiss\fcharset161\fprq2 Verdana Greek;}{\f382\fswiss\fcharset162\fprq2 Verdana Tur;}{\f385\fswiss\fcharset186\fprq2 Verdana Baltic;}{\f386\fmodern\fcharset238\fprq1 Orator10 BT CE;}{\f389\fmodern\fcharset161\fprq1 Orator10 BT Greek;} {\f390\fmodern\fcharset162\fprq1 Orator10 BT Tur;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255; \red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 \snext0 Normal;}{\s1\ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 \sbasedon0 \snext0 heading 1;}{ \s2\ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 \sbasedon0 \snext0 heading 2;}{\s3\ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 \sbasedon0 \snext0 heading 3;}{\*\cs10 \additive Default Paragraph Font;}{\*\cs15 \additive \ul\cf2 \sbasedon10 Hyperlink;}{\*\cs16 \additive \ul\cf12 \sbasedon10 FollowedHyperlink;}{\s17\ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\cf1\lang2057\langfe1031\cgrid\langnp2057\langfenp1031 \sbasedon0 \snext17 Body Text;}}{\*\listtable{\list\listtemplateid-2061993062\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360 \levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li720\jclisttab\tx720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li1440\jclisttab\tx1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 \levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2160\jclisttab\tx2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0 \leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2880\jclisttab\tx2880 }{\listlevel\levelnfc23 \levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li3600\jclisttab\tx3600 }{\listlevel \levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li4320 \jclisttab\tx4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5040\jclisttab\tx5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5760\jclisttab\tx5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr \brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li6480\jclisttab\tx6480 }{\listname ;}\listid251742083}{\list\listtemplateid792494758\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360 \levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li720\jclisttab\tx720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li1440\jclisttab\tx1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 \levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2160\jclisttab\tx2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0 \leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2880\jclisttab\tx2880 }{\listlevel\levelnfc23 \levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li3600\jclisttab\tx3600 }{\listlevel \levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li4320 \jclisttab\tx4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5040\jclisttab\tx5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5760\jclisttab\tx5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr \brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li6480\jclisttab\tx6480 }{\listname ;}\listid305862123}{\list\listtemplateid-1479128176\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0 \levelindent0{\leveltext\leveltemplateid67567633\'02\'00);}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li720\jclisttab\tx720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li1440\jclisttab\tx1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1 \levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-180\li2160\jclisttab\tx2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li2880\jclisttab\tx2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li3600\jclisttab\tx3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1 \levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-180\li4320\jclisttab\tx4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li5040\jclisttab\tx5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li5760\jclisttab\tx5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1 \levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-180\li6480\jclisttab\tx6480 }{\listname ;}\listid522868215}{\list\listtemplateid-470893324\listhybrid {\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567633\'02\'00);}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li720\jclisttab\tx720 } {\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li1440 \jclisttab\tx1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-180\li2160\jclisttab\tx2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li2880\jclisttab\tx2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\chbrdr \brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li3600\jclisttab\tx3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;} \chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-180\li4320\jclisttab\tx4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers \'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li5040\jclisttab\tx5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567641 \'02\'07.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li5760\jclisttab\tx5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext \leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-180\li6480\jclisttab\tx6480 }{\listname ;}\listid641082332}{\list\listtemplateid-116895826\listhybrid{\listlevel\levelnfc23\levelnfcn23 \leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li1080\jclisttab\tx1080 }{\listlevel\levelnfc23 \levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li1800\jclisttab\tx1800 }{\listlevel \levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2520 \jclisttab\tx2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li3240\jclisttab\tx3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li3960\jclisttab\tx3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr \brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li4680\jclisttab\tx4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567617 \'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5400\jclisttab\tx5400 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext \leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li6120\jclisttab\tx6120 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0 {\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li6840\jclisttab\tx6840 }{\listname ;}\listid689137503}{\list\listtemplateid1166842240\listhybrid{\listlevel \levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'00.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li720\jclisttab\tx720 }{\listlevel \levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'01.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li1440\jclisttab\tx1440 }{\listlevel \levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'02.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-180\li2160\jclisttab\tx2160 }{\listlevel \levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'03.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li2880\jclisttab\tx2880 }{\listlevel \levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'04.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li3600\jclisttab\tx3600 }{\listlevel \levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'05.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-180\li4320\jclisttab\tx4320 }{\listlevel \levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67567631\'02\'06.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li5040\jclisttab\tx5040 }{\listlevel \levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67567641\'02\'07.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-360\li5760\jclisttab\tx5760 }{\listlevel \levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67567643\'02\'08.;}{\levelnumbers\'01;}\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1 \fi-180\li6480\jclisttab\tx6480 }{\listname ;}\listid771049630}{\list\listtemplateid-2076262550\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li1080\jclisttab\tx1080 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr \brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li1800\jclisttab\tx1800 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621 \'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2520\jclisttab\tx2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext \leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li3240\jclisttab\tx3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360 \levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li3960\jclisttab\tx3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li4680\jclisttab\tx4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 \levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5400\jclisttab\tx5400 }{\listlevel\levelnfc23\levelnfcn23 \leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li6120\jclisttab\tx6120 }{\listlevel\levelnfc23 \levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li6840\jclisttab\tx6840 } {\listname ;}\listid940339485}{\list\listtemplateid952915692\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr \brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li720\jclisttab\tx720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2 \chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li1440\jclisttab\tx1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621 \'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2160\jclisttab\tx2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext \leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2880\jclisttab\tx2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360 \levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li3600\jclisttab\tx3600 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li4320\jclisttab\tx4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 \levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5040\jclisttab\tx5040 }{\listlevel\levelnfc23\levelnfcn23 \leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5760\jclisttab\tx5760 }{\listlevel\levelnfc23 \levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li6480\jclisttab\tx6480 } {\listname ;}\listid1042050726}{\list\listtemplateid1999940254\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr \brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li720\jclisttab\tx720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2 \chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li1440\jclisttab\tx1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621 \'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2160\jclisttab\tx2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext \leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li2880\jclisttab\tx2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360 \levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li3600\jclisttab\tx3600 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 \levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li4320\jclisttab\tx4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 \levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5040\jclisttab\tx5040 }{\listlevel\levelnfc23\levelnfcn23 \leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li5760\jclisttab\tx5760 }{\listlevel\levelnfc23 \levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f14\chbrdr\brdrnone\brdrcf1 \chshdng0\chcfpat1\chcbpat1\fbias0 \fi-360\li6480\jclisttab\tx6480 } {\listname ;}\listid1620724772}}{\*\listoverridetable{\listoverride\listid689137503\listoverridecount0\ls1}{\listoverride\listid251742083\listoverridecount0\ls2}{\listoverride\listid771049630\listoverridecount0\ls3}{\listoverride\listid522868215 \listoverridecount0\ls4}{\listoverride\listid641082332\listoverridecount0\ls5}{\listoverride\listid940339485\listoverridecount0\ls6}{\listoverride\listid1620724772\listoverridecount0\ls7}{\listoverride\listid305862123\listoverridecount0\ls8} {\listoverride\listid1042050726\listoverridecount0\ls9}}{\info{\author Mike Lischke}{\operator Mike Lischke}{\creatim\yr2002\mo1\dy4\hr9\min47}{\revtim\yr2002\mo1\dy4\hr10\min31}{\version14}{\edmins0}{\nofpages14}{\nofwords3825}{\nofchars21807} {\*\company privat}{\nofcharsws26780}{\vern8249}}\margl1417\margr1417\margt1417\margb1134 \widowctrl\ftnbj\aenddoc\hyphhotz425\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\horzdoc\dghspace120\dgvspace120\dghorigin1701\dgvorigin1984 \dghshow0\dgvshow3\jcompress\viewkind1\viewscale114\viewzk2\nolnhtadjtbl \fet0\sectd \linex0\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3 \pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}} {\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \qc \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\fs28\lang2057\langfe1031\langnp2057 Virtual Treeview step by step \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\lang2057\langfe1031\langnp2057 \par Written by Sven H. (}{\field\fldedit{\*\fldinst {\fs20\lang2057\langfe1031\langnp2057 HYPERLINK "mailto:h.sven@gmx.at"}{\fs20\lang2057\langfe1031\langnp2057 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b2a0000006d00610069006c0074006f003a0068002e007300760065006e00400067006d0078002e00610074000000}}}{\fldrslt {\cs15\fs20\ul\cf2\lang2057\langfe1031\langnp2057 h.sven@gmx.at}}}{ \fs20\lang2057\langfe1031\langnp2057 ), Revision and translation by Mike Lischke (}{\field\fldedit{\*\fldinst {\fs20\lang2057\langfe1031\langnp2057 HYPERLINK "mailto:public@lischke-online.de"}{\fs20\lang2057\langfe1031\langnp2057 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b400000006d00610069006c0074006f003a007000750062006c006900630040006c0069007300630068006b0065002d006f006e006c0069006e0065002e00640065000000}}}{\fldrslt { \cs15\fs20\ul\cf2\lang2057\langfe1031\langnp2057 public@lischke-online.de}}}{\fs20\lang2057\langfe1031\langnp2057 ) \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par At the time when this description had been created I had not much Delphi knowledge and had not yet read through any of my two Delphi books. But I was quite impatient and wanted to try out what is possible. \par \par Although I have some knowledge about object oriented programming and C++ (I have learned something about it during my studies), this project was my first attempt to program in Delphi. \par \par It could be that I have not provided the most elegant solutions und I am always open for improvement suggestions. But all principles I demonstrated here do work (at least for me J). I have implemented them in my first project this way. \par \par This guidance is made in the first place for programmers who are not yet familiar with Virtual Treeview and will so perhaps have an easier start. \par \par If you have questions or suggestions regarding this guidance please forward them to }{\field\fldedit{\*\fldinst {\fs20\cf1\lang2057\langfe1031\langnp2057 HYPERLINK "mailto:h.sven@gmx.at"}{\fs20\cf1\lang2057\langfe1031\langnp2057 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b2a0000006d00610069006c0074006f003a0068002e007300760065006e00400067006d0078002e00610074000000}}}{\fldrslt {\cs15\fs20\ul\cf2\lang2057\langfe1031\langnp2057 h.sven@gmx.at}}}{ \fs20\cf1\lang2057\langfe1031\langnp2057 . For other questions you can contact Mike and use the particularly for this task introduced mailing list at Yahoo Group (}{\field\fldedit{\*\fldinst {\fs20\cf1\lang2057\langfe1031\langnp2057 HYPERLINK "http://www.yahoogroups.com/group/VirtualTreeview"}{\fs20\cf1\lang2057\langfe1031\langnp2057 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6200000068007400740070003a002f002f007700770077002e007900610068006f006f00670072006f007500700073002e0063006f006d002f00670072006f00750070002f005600690072007400750061006c005400 72006500650076006900650077000000}}}{\fldrslt {\cs15\fs20\ul\cf2\lang2057\langfe1031\langnp2057 www.yahoogroups.com/group/VirtualTreeview}}}{\fs20\cf1\lang2057\langfe1031\langnp2057 ), respectively. \par \par I am neither a Virtual Treeview nor a Delphi expert and have collected all the answers (with the help of Mike) with quite some effort. In order to avoid the after wards relatively simple things to become problematical I have written this short guidance. The real problems will appear later J. \par \par \'a9 2001 The parts in this guidance beyond the text from the online help are copyrighted. Every publication requires my admission. \par \par }{\fs22\lang2057\langfe1031\langnp2057 Have fun with it, Sven. \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par \par \par }\pard\plain \s1\ql \fi-432\li432\ri0\keepn\nowidctlpar\tx432\faauto\outlinelevel0\rin0\lin432\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\fs28\cf1\lang2057\langfe1031\langnp2057 1\tab Preparations \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Before we start some preparations are necessary: \par }\pard \ql \fi-360\li720\ri0\nowidctlpar\tx720\faauto\rin0\lin720\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}}\pard \ql \fi-360\li720\ri0\nowidctlpar\jclisttab\tx720\faauto\ls2\rin0\lin720\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 Place a Virtual Treeview component on a form. \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}Change the properties as you like. \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}A record for node data must be defined. \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par In order to store the own node data some musing is important. How shall the record look like? \par \par }\pard \ql \fi-360\li360\ri0\nowidctlpar\tx360\faauto\rin0\lin360\itap0 {\b\fs20\lang2057\langfe1031\langnp2057 a)\tab All nodes in the tree are equal \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 In this case a simple record defines the necessary data structure, e.g.: \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 type \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 rTreeData = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 record}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Text: WideString; \par URL: }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 string}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 [255]; \par CRC: LongInt; \par isOpened: Boolean; \par ImageIndex: Integer; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\f29\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par }\pard \ql \fi-360\li360\ri0\nowidctlpar\tx360\faauto\rin0\lin360\itap0 {\b\fs20\cf1\lang2057\langfe1031\langnp2057 b)\tab There are different nodes in the tree (e.g. folders that can have sub nodes) \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 I will follow this case because my tree will hold folders, which can in turn get own nodes. \par \par Since I intent to store created trees in a file in order to restore them later further deliberations are necessary: \par \par Suppose a folder node has only a name and a leaf node has a name and a text info field. Potentially I also want to store a second kind of leaf node, which will for instance have a number instead of the text field. \par \par The problem in the context of reading data form a stream is that I must know which data is stored in which order in the stream, because I have to read it in exactly the same order again. Hence I have to de termine from the very first information in the stream which information will follow. For instance there is a node name, but then? Is there nothing more or another text information (string) or even an integer value? I think the point is clear. The first da ta, which I read, has to carry this information. \par \par These deliberations have leaded me to the following solution: I save now in the stream [label]}{\f14\fs20\cf1\lang2057\langfe1031\langnp2057 \'e0}{\fs20\cf1\lang2057\langfe1031\langnp2057 [name]}{\f14\fs20\cf1\lang2057\langfe1031\langnp2057 \'e0}{ \fs20\cf1\lang2057\langfe1031\langnp2057 [following data] \par 0 }{\f14\fs20\cf1\lang2057\langfe1031\langnp2057 \'e0}{\fs20\cf1\lang2057\langfe1031\langnp2057 'Folder' \par 1 }{\f14\fs20\cf1\lang2057\langfe1031\langnp2057 \'e0}{\fs20\cf1\lang2057\langfe1031\langnp2057 'Info node' }{\f14\fs20\cf1\lang2057\langfe1031\langnp2057 \'e0}{\fs20\cf1\lang2057\langfe1031\langnp2057 'Blabla' \par 2 }{\f14\fs20\cf1\lang2057\langfe1031\langnp2057 \'e0}{\fs20\cf1\lang2057\langfe1031\langnp2057 'Number node' }{\f14\fs20\cf1\lang2057\langfe1031\langnp2057 \'e0}{\fs20\cf1\lang2057\langfe1031\langnp2057 123 \par \par I know from the stream I always read an integer value first. Depending whether this is 1, 2 or 3 I have to read - now known - following values. Now let us consider the record. \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 type}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par rTreeData = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 record}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Typ: Integer; \par Name: }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 string}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 [255]; \par pNodeData: Pointer; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par Hey, there is suddenly a pointer in the record. Well, here are some additional comments: \par {\listtext\pard\plain\f28\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af28\dbch\af0\loch\f28 1)\tab}}\pard \ql \fi-360\li720\ri0\nowidctlpar\jclisttab\tx720\faauto\ls5\rin0\lin720\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 Typ is an integer value, from which I can determine what kind of node this is, in my example 1, 2 or 3. \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par {\listtext\pard\plain\f28\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af28\dbch\af0\loch\f28 2)\tab}}\pard \ql \fi-360\li720\ri0\nowidctlpar\jclisttab\tx720\faauto\ls5\rin0\lin720\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 Name is the name of the node. This will be needed relatively often because it is also seen as part of the tree and I want to access this information easily (man, I am lazy). \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par {\listtext\pard\plain\f28\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af28\dbch\af0\loch\f28 3)\tab}}\pard \ql \fi-360\li720\ri0\nowidctlpar\jclisttab\tx720\faauto\ls5\rin0\lin720\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 The pointer allows (similar to the data property of the tree) a record or even better a class instance to connect. \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Now I still have the freedom to define a base class of node. It contains all properties and methods, which all classes will share. And from this I can derive proper sub clas ses (e.g. text nodes, value nodes etc.). An additional advantage of this record is its fixed size. Hence you can always return the same size in case the tree asks for it (see also property NodeDataSize), but more about that later. \par \par Just one remark: \par If you don\rquote t want to use classes you can also simply define 3 records, which define as first element, a type and which react differently depending on this type. \par \par }{\b\fs20\ul\cf1\lang2057\langfe1031\langnp2057 Alternative solution:}{\fs20\cf1\lang2057\langfe1031\langnp2057 \par Okay, I admit it. It would of course also be possible to write the type into th e stream and read it from the stream separately without saving it as part of the record. The type of the node class is indirectly known because you can ask a class which class name it has (see e.g. class function ClassName) and the class knows it too, res pectively. \par \par So I shall store a node, okay. I pass on the stream to the Node.SaveToFile(Stream) method, which writes, depending on which node class we actually have, automatically the value 1, 2 or 3 into the stream. \par \par During load from stream I read first the value 1, 2 or 3 and decide what class is meant. Then I create an instance of this class and call its LoadFromFile method. \par \par Well, this solution is my most preferred and before another one enters my brain I will implement it (Note: in step 5 I will change something). \par \par }{\fs20\ul\cf1\lang2057\langfe1031\langnp2057 So I do following: \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par As you can see from the declaration of the internal node of Virtual Tree \par \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TVirtualNode = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 packed}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 record}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }\pard \ql \li0\ri0\nowidctlpar\tx3119\faauto\rin0\lin0\itap0 {\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Index,\tab }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // index of node with regard to its parent}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par ChildCount: Cardinal;\tab }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // number of child nodes}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par ... \par ... \par LastChild: PVirtualNode;\tab }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // link to the node's last child...}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }\pard \ql \fi-3119\li3119\ri0\nowidctlpar\tx3119\faauto\rin0\lin3119\itap0 {\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Data: }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 record}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{ \b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;\tab }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // this is a placeholder, each node gets extra\line // data determined by NodeDataSize}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\f29\fs16\cf1\lang2057\langfe1031\langnp2057 }{ \fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par there is another record at the end of the record structure. Which exact structure this is will be determined indirectly. \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 type \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 rTreeData = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 record}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }\pard \ql \li0\ri0\nowidctlpar\tx3119\faauto\rin0\lin0\itap0 {\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Name: }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 string}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 [255];\tab }{ \f2\fs18\cf2\lang2057\langfe1031\langnp2057 // the identifier of the node}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par ImageIndex: Integer;\tab }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // the image index of the node}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\f2\fs18\cf1\lang2057\langfe1031\langnp2057 pNodeData: Pointer; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 Let the above record be the structure. The Virtual Treeview does not really know this structure, but it knows how much space must be reserved. We tell it by \par \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 myVirtualTree.NodeDataSize := SizeOf(rTreeData); }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par Note: even if you want to store only one value, e.g. a pointer as node data, simply return the size, which should be reserved. \par \par }\pard\plain \s1\ql \fi-432\li432\ri0\keepn\nowidctlpar\tx432\faauto\outlinelevel0\rin0\lin432\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\fs28\cf1\lang2057\langfe1031\langnp2057 2\tab Implementation \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.1\tab An empty tree \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par I begin with an empty tree (no top level nodes are created at design time): \par \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}}\pard \ql \fi-360\li720\ri0\nowidctlpar\jclisttab\tx720\faauto\ls7\rin0\lin720\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 Either an existing tree is read from a file or \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}A top-level node is created. \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Before a node can be created you have to determine the size of the actual node data. According to the docs there are three opportunities: \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}}\pard \ql \fi-360\li720\ri0\nowidctlpar\jclisttab\tx720\faauto\ls8\rin0\lin720\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 In the object inspector \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}In the OnGetNodeDataSize - event or \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}During creation of the form \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par I decide to use the last variant and will now do the following during form creation: \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.FormCreate(Sender: TObject); \par }{\b\f2\fs18\cf1\lang1040\langfe1031\langnp1040 var \par }{\f2\fs18\cf1\lang1040\langfe1031\langnp1040 }{\f2\fs18\cf6\lang1040\langfe1031\langnp1040 Node: PVirtualNode;}{\f2\fs18\cf1\lang1040\langfe1031\langnp1040 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ... \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // create tree \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 MyTree.NodeDataSize := SizeOf(TTreeData);}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 MyForm.filename = '' }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{ \b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // if there is no tree to load \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // create tree with top level node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Node := BookmarkForm.BookmarkTree.}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 AddChild(nil)}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // adds a top level node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 else \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // load tree \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf1 .... \par }{\b\f2\fs18\cf1 end}{\f2\fs18\cf1 ; \par .... \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;\tab }{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.2\tab Data for the node \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par After the call of AddChild data can be assigned. F or this a pointer to the self-defined record will be declared and via the function GetNodeData connected with the correct address. By using this pointer we can now access the elements of the record and assign them values. \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang1040\langfe1031\langnp1040 var \par }{\f2\fs18\cf1\lang1040\langfe1031\langnp1040 ... \par NodeData: ^rTreeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ... \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // determine data for node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeData := BookmarkForm.BookmarkTree.GetNodeData(Node); \par NodeData.Name := }{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'new project'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\f2\fs18\cf1 NodeData.ImageIndex := 0; \par ...}{\f29\fs16\cf1 \par }{\fs20\cf1 \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.3\tab Show the node name \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par The name of the node shall now appear as node identification in the tree. All data about the node as well as the name are unknown to the treeview and it has to query for them. \par \par Every time the identification of the node is needed an event OnGetText will be triggered. In the event handler we return the name of the node in the variable Text. Nothing more is needed. \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBookmarkForm.BookmarkTreeGetText(Sender: TBaseVirtualTree; \par Node: PVirtualNode; Column: Integer; TextType: TVSTTextType; }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Text: WideString); \par }{\b\f2\fs18\cf1\lang1040\langfe1031\langnp1040 var \par }{\f2\fs18\cf1\lang1040\langfe1031\langnp1040 NodeData: ^rTreeData; \par }{\b\f2\fs18\cf1\lang1040\langfe1031\langnp1040 begin \par }{\f2\fs18\cf1\lang1040\langfe1031\langnp1040 NodeData := Sender.GetNodeData(Node); \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // return identifier of the node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Text := NodeData.Name; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.4\tab The icon for the node \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Because I like it}{\fs20\cf1\lang1033\langfe1031\langnp1033 colorful}{\fs20\cf1\lang2057\langfe1031\langnp2057 I want also to provide an icon for the top-level node. Following steps are necessary to accomplish that: \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}}\pard \ql \fi-360\li720\ri0\nowidctlpar\jclisttab\tx720\faauto\ls9\rin0\lin720\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 A TImageList must be placed onto the form and filled with images \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}The property Images of the VirtualTreeview gets assigned this image list \par {\listtext\pard\plain\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \hich\af2\dbch\af0\loch\f2 o\tab}Implement an OnGetImageIndex event handler. \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par In the event OnGetImageIndex you can the index be determine which determines in turn which image form the list must be shown. \par \par Because the method is also called for the state icons but I do not want yet to state icons (but I already have assigned and image list to the property StateImages) the value for this case (Kind }{\f14\fs20\cf1\lang2057\langfe1031\langnp2057 \'e0}{ \fs20\cf1\lang2057\langfe1031\langnp2057 ikState) is -1. \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBookmarkForm.BookmarkTreeGetImageIndex(Sender: TBaseVirtualTree; \par Node: PVirtualNode; Kind: TVTImageKind; Column: Integer; }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Index: Integer); \par }{\b\f2\fs18\cf1\lang1040\langfe1031\langnp1040 var \par }{\f2\fs18\cf1\lang1040\langfe1031\langnp1040 NodeData: ^rTreeData; \par }{\b\f2\fs18\cf1\lang1040\langfe1031\langnp1040 begin \par }{\f2\fs18\cf1\lang1040\langfe1031\langnp1040 NodeData := Sender.GetNodeData(Node); \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 case}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Kind }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 of}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par ikState: }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // for the case the state icon has been requested}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Index := -1; \par ikNormal, ikSelected: }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // normal or the selected icon is required}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Index := NodeData.ImageIndex; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par Depending on whether a node is selected or not, different icons shall be shown (see step 6). \par \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.5\tab Only one node class in the record \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Since I want to avoid mixing data in the record and later then data in the node class I decided to change this record \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 type \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TTreeData = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 record}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Name: }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 string}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 [255]; }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // the identifier of the node}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par ImageIndex: Integer; }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // the image index of the node}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par pNodeData: Pointer; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par into a record which contains only one pointer to a node class. I declare therefore first a node class \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBasicNodeData = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 class}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par ... \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\f29\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par and then a structure of the form: \par \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 rTreeData = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 record}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par BasicND: TBasicNodeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par This record always needs 4 bytes for the pointer to the class. \par \par Particular attention is to direct to the event OnGetText. This event will already be called during creation of the node with Tree.AddChild(nil) in order to determine the space the new node\rquote s caption will need (but only if no columns were created). At this point however the node class could not yet be initialised (no constructor call yet). Hence for this case \par \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeD.BasicND = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 nil}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Text := ''}{\f29\fs16\cf1\lang2057\langfe1031\langnp2057 }{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par must be returned or you wrap the entire}{\fs20\cf1\lang1033\langfe1031\langnp1033 initialization}{\fs20\cf1\lang2057\langfe1031\langnp2057 into a BeginUpdate/EndUpdate block and}{\fs20\cf1\lang1033\langfe1031\langnp1033 initialized}{ \fs20\cf1\lang2057\langfe1031\langnp2057 the nodes before EndUpdate is called (e.g. by ValidateNode(Node)). \par \par Without this provision an access violation would be the result. \par \par }\pard\plain \s3\ql \fi-720\li720\ri0\sb240\sa60\keepn\nowidctlpar\tx720\faauto\outlinelevel2\rin0\lin720\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\lang2057\langfe1031\langnp2057 2.5.1\tab Example class declaration \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 unit}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TreeData; \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 interface \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 //=========================================== \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 type \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // declare common node class}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par TBasicNodeData = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 class}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 protected}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par cName: ShortString; \par cImageIndex: Integer; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 public}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 constructor}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Create; }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 overload}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 constructor}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Create(vName: ShortString; vIIndex: Integer = }{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 0}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ); }{ \b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 overload}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 property}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Name: ShortString }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 read}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 cName }{ \b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 write}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 cName; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 property}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ImageIndex: Integer }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 read}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 cImageIndex }{ \b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 write}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 cImageIndex; \par end; \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // declare new structure for node data \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 rTreeData = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 record}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par BasicND: TBasicNodeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 implementation}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 constructor}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBasicNodeData.Create; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 \{ not necessary \par cName := ''; \par cImageIndex := 0; \par \}}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 constructor}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBasicNodeData.Create(vName: ShortString; vIIndex: Integer = 0); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par cName := vName; \par cImageIndex := vIIndex; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 . \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par }\pard\plain \s3\ql \fi-720\li720\ri0\sb240\sa60\keepn\nowidctlpar\tx720\faauto\outlinelevel2\rin0\lin720\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\lang2057\langfe1031\langnp2057 2.5.2\tab Example creation of the tree \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // Tree will be created when the form is created.}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.FormCreate(Sender: TObject); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Node: PVirtualNode; \par NodeD: ^rTreeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par .... \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // create tree}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par MyTree.NodeDataSize := SizeOf(rTreeData); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 MainControlForm.filename = '' }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // create tree with top level node}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Node := MyTree.AddChild(nil); }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // adds a node to the root of the tree}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // assign data for this node}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD := MyTree.GetNodeData(Node); \par NodeD.BasicND := TBasicNodeData.Create(}{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'new project'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 else \par begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // load tree}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par ... \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\f29\fs16\cf1\lang2057\langfe1031\langnp2057 \par \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 \{______________________________MyTree_________________________________\}}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // returns the text (the identification) of the node \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.MyTreeGetText(Sender: TBaseVirtualTree; \par Node: PVirtualNode; Column: Integer; TextType: TVSTTextType; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Text: WideString); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD: ^rTreeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD := Sender.GetNodeData(Node); \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // return the identifier of the node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeD.BasicND = nil }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Text:='' \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 else}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Text := NodeD.BasicND.Name; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // returns the index for image display \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.MyTreeGetImageIndex(Sender: TBaseVirtualTree; \par Node: PVirtualNode; Kind: TVTImageKind; Column: Integer; }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Index: Integer); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD: ^rTreeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD := Sender.GetNodeData(Node); \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 case}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Kind }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 of}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par ikState: }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // for the case the state index has been requested}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Index := -1; \par ikNormal, ikSelected: }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // normal icon case}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Index := NodeD.BasicND.ImageIndex; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\f29\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.6\tab Icons for selected nodes \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\fs20\lang2057\langfe1031\langnp2057 If a node is selected a different symbol shall be shown: \par }{\fs20\lang2057\langfe1031\langnp2057 Therefore I implement a new method \par \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 function}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 GetImageIndex(focus: Boolean): Integer; }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 virtual}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\lang2057\langfe1031\langnp2057 \par which gets the normal image index or the index for focused nodes depending on whether the node has the focus or not. \par \par Call: \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Index := NodeD.BasicND.GetImageIndex(Node = Sender.FocusedNode);}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\lang2057\langfe1031\langnp2057 Implementation of the method: \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 function}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBasicNodeData.GetImageIndex(focus: Boolean): Integer; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 focus }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Result := cImageIndexFocus \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 else \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Result := cImageIndex; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par where cImageIndex has always the normal index and cImageIndex Focus the index for focused nodes. \par I assume in this case that the selected index is always one more than the normal index. To ensure this, the constructor is changed this way: \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 constructor}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBasicNodeData.Create(vName: ShortString; vIIndex: Integer = 0); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 cName := vName; \par cImageIndex := vIIndex; \par cImageIndexFocus := vIIndex + 1; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs20\cf1\lang2057\langfe1031\langnp2057 \par \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.7\tab Adding and deleting nodes \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par In order to implement and test more functions I want finally an opportunity to create the tree. By using a context menu is shall be possible to add and remove nodes. \par \par Hence I define a popup menu with two entries: [Add] and [Remove]. To have the clicked node getting the focus the option voRightClickSelect must be set to True. \par \par So if Add has been chosen a child node will be created for the focused node: \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 addClick }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 (Sender: TObject); \par }{\b\f2\fs18\cf1\lang1040\langfe1031\langnp1040 var \par }{\f2\fs18\cf1\lang1040\langfe1031\langnp1040 Node: PVirtualNode; \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeD: ^rTreeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin \par }{\f2\fs18\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // Ok, a node must be added. \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Node := MyTree.}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 AddChild}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 (MyTree.FocusedNode); }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // adds a node as the last child}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // determine data of node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeD := MyTree.GetNodeData(Node); \par NodeD.BasicND := TBasicNodeData.Create('Child'); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs20\cf1\lang2057\langfe1031\langnp2057 \par \par }{\b\fs20\ul\cf1\lang2057\langfe1031\langnp2057 Caution:}{\fs20\cf1\lang2057\langfe1031\langnp2057 What must be done if no node has the focus? \par }{\fs20\cf1 {\field{\*\fldinst SYMBOL 224 \\f "Wingdings" \\s 10}{\fldrslt\f14\fs20}}}{\fs20\cf1\lang2057\langfe1031\langnp2057 e.g. insert the new node as child of a top level nodes. \par \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 BookmarkTree.FocusedNode = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 nil}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // insert as child of the first top level node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Node := BookmarkTree.AddChild(BookmarkTree.RootNode.FirstChild); \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // determine data for node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeD := BookmarkTree.GetNodeData(Node); \par NodeD.BasicND := TFolderNodeData.Create(}{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'new folder'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 else}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // Ok, a new node must be added. \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Node := BookmarkTree.AddChild(BookmarkTree.FocusedNode); \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // determine data of the node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeD := BookmarkTree.GetNodeData(Node); \par NodeD.BasicND := TFolderNodeData.Create(}{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'new folder'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par \par If the node with the focus must be deleted the following happens: \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 delClick }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 (Sender: TObject); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // The focused node should be removed. The top level must not be deleted however. \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 MyTree.FocusedNode = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 nil}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par MessageDlg(}{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'There was no node selected.'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 , mtInformation, [mbOk], 0) \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 else}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // Note: RootNode is the internal (hidden) root node and parent of all top \par // level nodes. To determine whether a node is a top level node you also use \par }{\f2\fs18\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // GetNodeLevel which returns 0 for top level nodes. \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 MyTree.FocusedNode.Parent = MyTree.RootNode }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par MessageDlg(}{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'The project node must not be deleted.'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 , mtInformation, [mbOk], 0) \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 else}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par MyTree.}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 DeleteNode}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 (MyTree.FocusedNode); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par I want to prevent, however, that the top-lev el node gets deleted. Hence I check with the comparison MyTree.FocusedNode.Parent = MyTree.RootNode whether the focused node is not a top-level node. Here you have to consider that the property RootNode returns the (hidden) internal root node, which is th e common parent of all top-level nodes. \par \par While we are at deleting nodes: \par }\pard\plain \s17\ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\cf1\lang2057\langfe1031\cgrid\langnp2057\langfenp1031 {\fs20 Every data of the record is automatically free as soon as this is required. In this case it is not enough, however, to free the memory, which holds the pointer to the class (object in stance), but it is also necessary to free the memory, which is allocated by the class itself. This happens by calling the destructor of the class in the OnFreeNode event: \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.MyTreeFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // Free here the node data (Note: }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 type PtreeData = ^rTreeData}{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 ). \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf1\lang1040\langfe1031\langnp1040 PTreeData(Sender.GetNodeData(Node)).BasicND.Free; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs20\cf1\lang2057\langfe1031\langnp2057 \par \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.8\tab Adding folder and leafs \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Now I am ready to add folders to the tree as well as final nodes, which do not have children. For this I derive two new node classes from the base class. \par \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TFolderNodeData = class(TBasicNodeData) \par TItemNodeData = class(TBasicNodeData)}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par Depending on which kind of node the user wants to create using the context menu I store a particular class in the node record. \par \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeD.BasicND := TFolderNodeData.Create(}{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'new folder'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ); \par NodeD.BasicND := TItemNodeData.Create(}{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'new node'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 );}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par These classes contain a new property ChildrenAllowed. Based on this property you can now distinct whether the node with the focus may get children (folder) or not (items). \par \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.9\tab Storing the tree \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Now I can finally implement storing the tree. I have already thought a lot about this step. Let us see if this was worthwhile. \par \par Again a quote from }{\fs20\ul\cf2\lang2057\langfe1031\langnp2057 Preparations}{\fs20\cf1\lang2057\langfe1031\langnp2057 : \par I want to store a node, okay. I hand over the stream to the MyNodeClass.SaveToFile method and this method writes depending upon which node class it actually is automatically the value 1, 2 or 3 as a kind of class ID into the stream (alternatively you can use an enumeration type). \par \par During load I read first the value 1, 2 or 3 from the stream and decide based on it which class we deal with. Then I create an instance of this class and call its method LoadFromFile. \par \par }{\fs20\ul\cf1\lang2057\langfe1031\langnp2057 Hint:}{\fs20\cf1\lang2057\langfe1031\langnp2057 \par It would also be possible to store the class name instead of the ID for the class. During read and creation of the class one could use class references and virtual constructors and save so the case-statement as I did in the OnLoadNode event, to decide which class instance must be created (example see Delphi 5, written by Elmar W arken, Addison-Wesley, chapter 4.3.3, page 439). \par \par Before you can read something it must be written first. Hence I will first implement the necessary procedures to store the tree. Since we care ourselves that the identification of the node gets saved the opt ion toSaveCaption can be removed from StringOptions. This way data is not stored twice. \par \par For saving the tree the procedure \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBaseVirtualTree.}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 SaveToFile}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 (}{ \b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 const}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 FileName: TFileName); \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par is called. Thereby the structure of the tree is automatically stored. In order to save our additional data there is an event OnSaveNode where we can simply store our data into the provided stream. \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 property}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 OnSaveNode: }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TVTSaveNodeEvent }{ \b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 read}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 FOnSaveNode }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 write}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 FOnSaveNode;}{ \b\f2\fs20\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par If OnSaveNode is triggered then the method SaveNode of the particular node class will be called: \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.MyTreeSaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode; \par Stream: TStream); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par PTreeData(Sender.GetNodeData(Node)).BasicND.}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 SaveToFile}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 (Stream); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 In the SaveNode method of the class fields like node name, image index etc. are stored in the tree: \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBasicNodeData.SaveNode(Stream: TStream); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 size: Integer; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // save type of the node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Stream.Write(Art, SizeOf(Art)); \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // store cName \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Size := Length(cName) + 1; }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // include terminating #0}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Stream.Write(Size, SizeOf(Size)); }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // store length of the string}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Stream.Write(PChar(cName)^, Size); }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // now the string itself}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // store cImageIndex \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Stream.Write(cImageIndex, SizeOf(cImageIndex)); \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // store cImageIndexFocus \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Stream.Write(cImageIndexFocus, SizeOf(cImageIndexFocus)); \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // store cChildrenAllowed \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Stream.Write(cChildrenAllowed, SizeOf(cChildrenAllowed)); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 Now we can the tree we save also load again. This process could look like: \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 try \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // load tree \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 MyTree.LoadFromFile(MainControlForm.Filename); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 except}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par on E: Exception }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 do}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Application.MessageBox(PChar(E.Message), PChar(}{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'Error while loading.'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ), MB_OK); \par MainControlForm.Filename := }{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 ''}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par \par }{\f2\fs18\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // create tree with top level node (since loading failed) \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Node := MyTree.AddChild(}{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 nil}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ); \par NodeD := MyTree.GetNodeData(Node); \par NodeD.BasicND := TBasicNodeData.Create(}{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'new project'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 By the call of LoadFromFile the event OnLoadNode will be triggered and consequently the method LoadNode: \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBasicNodeData.LoadNode(Stream: TStream); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Size: Integer; \par StrBuffer: PChar; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // load cName}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Stream.Read(Size, SizeOf(Size)); }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // length of the string}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par \par StrBuffer := AllocMem(Size); }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // get temporary memory}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Stream.Read(StrBuffer^, Size); }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // read the string}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par cName := StrBuffer; \par }{\f2\fs18\lang2057\langfe1031\langnp2057 FreeMem(StrBuffer); \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // Alternatively you can simply use: \par // SetLength(cName, Size); \par // Stream.Read(PChar(cName)^, Size);}{\f2\fs18\lang2057\langfe1031\langnp2057 \par \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // load cImageIndex \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Stream.Read(cImageIndex, SizeOf(cImageIndex)); \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // load cImageIndexFocus \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Stream.Read(cImageIndexFocus, SizeOf(cImageIndexFocus)); \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // load cChildrenAllowed \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Stream.Read(cChildrenAllowed, SizeOf(cChildrenAllowed)); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ;}{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.10\tab Two columns in the treeview \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Now I want to show two columns in the treeview. Therefore I set the new properties of the tree in the object inspector. \par \par By using Header.Columns you can create the desired columns. After that, you only have to set Header.Options.hoVisible to True and the columns will appear in the treeview. \par \par After you have set all necessary options you can give now the text and the icon for the particular column, respectively. This happens in the already existing event handlers OnGetText and OnGetImageIndex where now also the given column index mu st be taken into account. \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.MyTree}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 GetText}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 (Sender: TBaseVirtualTree; Node: PVirtualNode; \par Column: Integer; TextType: TVSTTextType; }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Text: WideString); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD: ^rTreeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD := Sender.GetNodeData(Node); \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // return the the identifier of the node \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeD.BasicND = }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 nil}{ \f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Text := }{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 ''}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 else}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf6\lang2057\langfe1031\langnp2057 case}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 Column }{\b\f2\fs18\cf6\lang2057\langfe1031\langnp2057 of}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par -1, \par 0: }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // main column, -1 if columns are hidden, 0 if they are shown}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Text := NodeD.BasicND.Name; \par 1: \par Text := }{\f2\fs18\cf5\lang2057\langfe1031\langnp2057 'This text appears in column 2.'}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TMyForm.MyTree}{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 GetImageIndex}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 (Sender: TBaseVirtualTree; Node: PVirtualNode; \par Kind: TVTImageKind; Column: Integer; }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Index: Integer); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD: ^rTreeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD := Sender.GetNodeData(Node); \par \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf6\lang2057\langfe1031\langnp2057 Column = 0}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then} {\f2\fs18\cf1\lang2057\langfe1031\langnp2057 }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // icons only in the first column}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 case}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 Kind }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 of}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par ikState: \par Index := -1; \par ikNormal, ikSelected: \par Index := NodeD.BasicND.GetImageIndex(Node = Sender.FocusedNode); \par ikOverlay: }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // e.g. to mark a node whose content changed, \par // Note: don\rquote t forget to call ImageList.Overlay for the image.}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 if}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 NodeD.BasicND.ImageIndex = 4 }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 then}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par Index := 6; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.11\tab Accessing the columns \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par I want to demonstrate the access to the columns of a TVirtualStringTrees based on an example. In order to store global options, as in }{\fs20\ul\cf2\lang2057\langfe1031\langnp2057 Point 2.12}{\fs20\cf1\lang2057\langfe1031\langnp2057 I want to know the width of a column. This information is updated every time an OnColumnResize event is triggered: \par }{\fs16\cf1\lang2057\langfe1031\langnp2057 \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 procedure}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TBookmarkForm.BookmarkTreeColumnResize(Sender: TBaseVirtualTree; \par Column: Integer); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 var}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD: PTreeData; \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 begin}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 \par NodeD := Sender.GetNodeData(Sender.RootNode.FirstChild); \par \par }{\f2\fs18\cf2\lang2057\langfe1031\langnp2057 // Keep the new size of the column in the project node. \par }{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 TProjectNodeData(NodeD.BasicND).SetHColumnsWidth( \par }{\b\f2\fs18\cf6\lang2057\langfe1031\langnp2057 TVirtualStringTree(Sender)}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 .Header.Columns.Items[Column].Width,Column); \par }{\b\f2\fs18\cf1\lang2057\langfe1031\langnp2057 end}{\f2\fs18\cf1\lang2057\langfe1031\langnp2057 ; \par }{\fs20\cf1\lang2057\langfe1031\langnp2057 \par The exciting part is the type casting of the sender object. In TBaseVirtualTree the header property is protected and only after conversion (casting) to TVirtualTree it becomes accessible. \par \par }\pard\plain \s2\ql \fi-576\li576\ri0\sb240\sa60\keepn\nowidctlpar\tx576\faauto\outlinelevel1\rin0\lin576\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\b\i\fs28\lang2057\langfe1031\langnp2057 2.12\tab Global tree options \par }\pard\plain \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \f28\fs24\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Global options like the sizes of the columns, which are adjusted in the project, will be stored as properties of the top-level node. It contains so all project related options. \par \par In order to avoid that all derived classes inherit these fields the top-level node class will be build from a new project node class, which will be derived from the base node class. \par \par The new hierarchy looks now so: \par }\pard \ql \li0\ri0\nowidctlpar\tx284\tx567\tx851\tx3119\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \'bb\tab Base node class...\tab unites the properties of all nodes \par \tab \'bb\tab Project node class...\tab enriches the base with management of project related options \par \tab \'bb\tab Folder node classes...\tab enriches the base with default properties for all leaf nodes \par \tab \tab \'bb\tab Leaf node class...\tab the actual node class (special properties) \par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\fs20\cf1\lang2057\langfe1031\langnp2057 \par Since this involves already very application specific program details I want only make some notes. \par \par The base node class has the ability to store node data. These methods must be declared as virtual and will be overridden in the project node class to allow saving the project data. \par \par Well, now I am ready to work with VirtualTreeview. It will become interesting later again when I will try to drag data from other applications to the tree. But this is a different story... \par }}