19 Widoki list


Rozdział 19
Widoki List, Tree, Rich Edit i HTML
Obsługa danych zapisanych w formie listy za pomocą widoku List
Hierarchiczne organizowanie danych za pomocą widoku Tree
Zaawansowane edytowanie tekstu za pomocą widoku Rich Edit Aplikacja z
elementami przeglądarki sieciowej
Czym są widoki List, Tree i Rich Edit?
Widoki List, Tree i Rich Edit bazują na kontrolkach, które mogą być wykorzystywane w
oknach dialogowych. W praktyce większość ich funkcji wykonywanych jest przez te właśnie,
osadzone wewnątrz kontrolki. Trzy wspomniane tutaj widoki są jednymi z bardziej
wszechstronnych i częściej wykorzystywanych narzędzi.
Tworzenie i korzystanie z widoku List
Wiele aplikacji wykorzystuje jako centralny element różnego rodzaju listy. Oczywistym
przykładem jest tu Eksplorator Windows, który wykorzystuje widok List w prawym panelu
okna. Widok List dostarcza licznych narzędzi do zarządzania lista danych, którą wyświetla.
Poszczególne elementy mogą być wyświetlane w postaci małych lub dużych ikon albo
rozbudowanej listy podającej bardziej szczegółowe informacje na temat każdego z elementów.
Widok List pozwala również na automatyczne sortowanie danych i wybieranie większej liczby
elementów. Wszystkie te funkcje zostały zautomatyzowane, dzięki czemu możemy się
skoncentrować na tworzeniu aplikacji zamiast na żmudnej pracy pisania kodu
odpowiedzialnego za wyświetlanie listy.
PATRZ TAKŻE
Jak korzystać z kontrolki List w oknie dialogowym mówimy w rozdziale 6.
Informacje o tworzeniu okna z kilkoma widokami znaleźć można w rozdziale 20.
Jak zmienić domyślną czcionkę korzystając z funkcji SetFon t () pisaliśmy w rozdziale 17.


478_______________________________________Poznaj Visual C++ 6
Tworzenie aplikacji z widokiem List za pomocą kreatora AppWizard
Za pomocą kreatora AppWizard można utworzyć aplikację SDI opartą na widoku List.
Zbudujemy tutaj taki projekt, aby pokazać jak działa widok List.
Tworzenie aplikacji SDI bazującej na widoku List
1. Kliknij menu File i wybierz polecenie New.
2. Wybierz kartę Projects; w liście typów projektów wybierz MFC AppWizard (exe).
3. Kliknij pole Project Name i wprowadź nazwę projektu, ListV.
4. Kliknij OK. Pojawi się pierwsze okno dialogowe kreatora AppWizard.
5. Kliknij Single Document i wciskaj przycisk Next, aż dotrzesz do końcowej strony z
charakterystyczną flagą.
6. W liście klas utworzonych przez kreator AppWizard kliknij klasę CListView.
7. Lista kombinowana Base Ciass stanie się teraz aktywna. Kliknij strzałkę wskazującą w dół,
aby rozwinąć listę możliwych bazowych klas widoków.
8. Wybierz jako klasę bazową klasę CListView.
9. Kliknij przycisk Finish.
10. Kliknij przycisk OK w oknie dialogowym New Project Infonnation, a kreator
AppWizard utworzy nowy projekt i pliki źródłowe.
Powinniśmy otrzymać teraz szkielet aplikacji SDI bazującej na widoku CListView.
Moglibyśmy już teraz zbudować i uruchomić aplikację, jednak nie będzie się ona jeszcze w tej
chwili niczym różnić od aplikacji SDI bazującej na standardowym widoku cview. Aby
zauważyć różnicę, trzeba dodać od listy odpowiednie elementy.
Dodawanie elementów do listy
Każda normalna aplikacja powinna przechowywać swoje dane osobno od kodu widoku, w
klasie dokumentu (lub w innej klasie zdefiniowanej dla potrzeb przechowywania danych).
Klasa widoku powinna być wykorzystywana przede wszystkim do przechowywania operacji
ściśle związanych z działaniem widoku. Najlepszym miejscem do przechowywania danych
zawartych na liście jest wywodząca z klasy CDocument klasa CLi-stVDoc. Utwórzmy
przykładową listę złożoną z łańcuchów, której poszczególne elementy będą nazwami
pierwiastków chemicznych. W bibliotece MFC znajduje się specjalnie przystosowana do
przechowywania takich list klasa CStringList. Poniżej podajemy odpowiedni algorytm.


Widoki List.Tree, Rich Edit i HTML 479
Klasy kolekcji
Klasa CStringList z biblioteki MFCjest przykładem klas kolekcji (ang. collection). Kolekcje zarządzają
zbiorami danych określonego typu. W przypadku klasy CStringList danymi przechowywanymi w
kolekcji będą oczywiście łańcuchy, obiekty
CString.
Dodawanie zmiennych składowych z karty ClassView
1. W oknie Project Workspace wybierz kartę ClassView.
2. Otwórz klasy ListV, aby sięgnąć do klasy CListVDoc.
3. Kliknij tę klasę prawym klawiszem myszy, aby wywołać menu skrótów.
4. Wybierz opcję Add Member Variable, aby wywołać okno dialogowe Add Member Variable.
5. W polu Variable Type wpisz CStringList, następnie, aby przenieść się do kolejnego pola wciśnij
klawisz Tab.
6. W polu Variable Declaration wpisz m_listElements.
7. Wybierz opcję Pri^ate Access i kliknij OK, by dodać nową zmienną składową klasy listy łańcuchów.
W ten sposób mamy już obiekt listy łańcuchów osadzony w klasie dokumentu. W punkcie siódmym
zdefiniowaliśmy zasady dostępu do zmiennej, deklarując ją jako prywatną (ang. private), dzięki czemu
jej wartość można będzie modyfikować tylko za pomocą funkcji składowych dokumentu. Zapobiegnie to
przypadkowym, niepożądanym modyfikacjom zmiennej przez funkcje składowe innych klas. Oczywiście
jest bardzo mała szansa, że coś takiego przydarzy się w tak prostym programie jak ten, jednak w dużych
aplikacjach należy bezwzględnie udostępniać dane tylko określonej grupie zaufanych funkcji danej klasy.
Zdefiniowanie zmiennej jako publicznej (ang. public) oznacza, że sięgnąć mogą do niej funkcje dowolnej
innej klasy. Natomiast zdefiniowanie zmiennej jako chronionej (ang. protected) działa mniej więcej tak
samo jak zadeklarowanie jej jako prywatnej, z tym że w przypadku zmiennej chronionej będzie ona
dostępna również dla wszystkich klas wywiedzionych z klasy, w której została zdefiniowana.
Temat ten jest związany z programowaniem obiektowym i nie będziemy się tutaj nad nim zbytnio
rozwodzić, warto jednak wiedzieć, że definiowanie rodzaju dostępu do zmiennych ma znaczenie, gdy
sięgamy z klasy CListView do osadzonej w widoku kon-trolki List. Tak samo jak w przypadku zmiennej
składowej, zmienna nie będzie dostępna spoza klasy dokumentu. Może to sprawiać pewne kłopoty,
ponieważ będziemy zmuszeni zapełniać listę w widoku List z wnętrza listy łańcuchów. Rozwiązaniem
tego problemu jest zdefiniowanie odpowiedniej funkcji dostępu. Zadaniem funkcji dostępu jest bezpiecz-
ne zarządzanie odczytywaniem i modyfikowaniem odpowiedniej zmiennej lub zmiennych


480_____________________________________Poznaj Visual C++ 6
składowych. Jeśli do zmiennej można sięgnąć tylko za pomocą jednej ściśle określonej funkcji, w razie
problemów z tą zmienną będziemy mogli ograniczyć poszukiwania odpowiedzialnego za te problemy
błędu tylko do tej jednej funkcji.
Zapobieganie niepożądanym modyfikacjom danych poprzez deklarowanie zmiennych jako
prywatne
Należy pamiętać, że piszemy program komputerowy, czyli rzecz, która jeśli będzie miała szansę, na
pewno nawali i to najpewniej wtedy, gdy będziemy demonstrować jego działanie szefowi lub
potencjalnemu klientowi. Ograniczanie dostępu do zmiennych poprzez deklarowanie ich jako prywatne
lub chronione oraz obsługiwanie ich tylko za pomocą specjalnie w tym celu zdefiniowanych funkcji
dostępu (ang. access function), chroni nas w znacznej mierze przed takimi wypadkami.
Dodamy teraz odpowiednią funkcję składową, która odpowiedzialna będzie za odczytywanie i
modyfikowanie danych w liście łańcuchów. Poniższa instrukcja pokazuje jak utworzyć funkcję dostępu
zwracającą listę łańcuchów m_listElements.
Dołączanie do programu funkcji składowej poprzez ClassView
1. Kliknij prawym klawiszem myszy klasę CListVDoc, aby wyświetlić menu skrótów klasy.
2. Aby wyświetlić okno dialogowe Add Member Function, kliknij polecenie menu Add JMember
Function.
3. W polu Function Type wpisz const CStringList&, a następnie za pomocą klawisza Tab przejdź do
kolejnego pola.
4. W polu Function Declaration wpisz GetElements ().
5. Aby zakończyć dodawanie funkcji składowej GetElements (), kliknij OK.
Kiedy klikniemy OK w programie pojawi się nowa funkcja GetElements (). Musimy jeszcze dodać
do niej poniższą linię, aby wprowadzić odwołanie do listy elementów:
return m_listElements;
Ponieważ funkcja ta zwraca stałą, const CStringList&, funkcje spoza dokumentu sięgające do listy
będą mogły tylko odczytywać jej zawartość. Status tylko do odczytu jest efektem użycia słowa
kluczowego const. Oznacza to, że klasa widoku może modyfikować listę, ale nie jest w stanie zmieniać
jej zawartości. I oto właśnie chodzi - zależało nam bowiem na tym, aby zawartość listy można było
modyfikować tylko z klasy dokumentu.
Aby przyjrzeć się widokowi List, potrzebować będziemy przykładowych danych, dlatego w
konstruktorze klasy dokumentu dodamy kilka elementów do obiektu listy. Aby rozpocząć edycję funkcji
konstruktora, klikamy dwukrotnie klasę CListVDoc w klasie


Widoki List,Tree, Rich Edit i HTML_____________________________481
CListVDoc (konstruktor nosi tę samą nazwę co klasa, którą konstruuje). Jak dodawać elementy do listy
pokazaliśmy na listingu 19.1.
Listing 19.1. LST20_1.CPP - dodawanie nazw pierwiastków do klasy konstruktora dokumentu
CListVDoc ____ ____
l CListVDoc::CListVDoc() 2 (
// TODO: Tu dodaj kod konstruowania klasy
II ** Dodaj nazwy pierwiastków do listy łańcuchów
m_listElements.AddTail("Carbon") ;
m_listElements.AddTail("Uranium") ;
m_listElements.AddTail("Gold") ;
m_listElements.AddTail("Osmium") ;
m_listElements.AddTail("Oxygen") ;
10 m_listElements.AddTail("Lead") ;
11 }___________________________________________________
W liniach 5-10 listingu 19.1 dodajemy do listy m_listElements nazwy pierwiastków wpisując jako
parametr funkcji składowej klasy cstringList odpowiednie teksty łańcuchów. Funkcja AddTail () dodaje
przesłany jej łańcuch na końcu listy.
Kolejną rzeczą, która trzeba tutaj zrobić, jest załadowanie składających się na listę danych do widoku
List, w momencie, gdy jest on wyświetlany po raz pierwszy. Do listy łańcuchów sięgać możemy tylko za
pomocą funkcji dostępu GetElements (). Dlatego musimy odwołać się do niej w metodzie
OninitialUpdateO widoku. Funkcja Onini-tialUpdate () przyzywana jest, gdy widok jest wyświetlany po
raz pierwszy. Funkcję OninitialUpdateO można znaleźć klikając w panelu CIasYiew okna Project
Works-pace funkcję składową klasy CListWiew, OninitialUpdate (). Kod zawarty na listingu 19.2
kopiuje elementy listy z dokumentu do widoku List.
Listing 19.2. LST20_2.CPP - dodawanie elementów do widoku List za pomocą funkcji Insert-Item()
1 void CListWiew:: OninitialUpdate ()
2 {
3 CListView::OninitialUpdate() ;
4
5 // TODO: możemy zapełnić LlstView elementami
6 // jego kontrolki List za pomocą, funkcji GetListCtrl ()
7
8 // ** Zdobądź wskaźnik dokumentu
9 CListVDoc* pDoc = GetDocument(); O
10 // ** Upewnij się, że dokument został inicjowany
11 ASSERT_VALID(pDoc);


12
13 II** Ustal pozycje nagłówka listy łańcuchów
14 POSITION pos =
15 pDoc->GetElements().GetHeadPosition() ;
16
17 // ** Jeśli pozycja jest NULL, dodawaj elementy
18 while(pos)
19 (
20 // ** Weź następny element z listy
21 CString strEiement SB
22 pDoc->GetElements().GetNext(pos) ;
23
24 // ** Dodaj go do widoku
25 GetListCtrl().Insertltem(0.strEiement);
26 }
27 )
O Dokument można zawszę .odaaleźć za.pomocąnależącej do widoku funkcji Get-
DocuroentO. ' .,;^, : '. ^ ' :. . - . .' . '...:., .".-1'11/;--:..:,:^.'1
@ Tutaj dodajemy elementy do listy za pomocą funkcji Insertitęms ().
Tak jak to pokazaliśmy w linii 9, wskaźnik dokumentu można zdobyć za pomocą
funkcji GetDocument (), zwracającej zawsze dokument będący własnością widoku.
Makroinstrukcja ASSERT_VALID w linii 11 sprawdza, czy dokument (w tym przypad-
ku CListVDoc) istnieje i czy można się do niego bezpiecznie odwołać.
Jak za pomocą makroinstrukcji ASSERT rozpoznawać problemy zanim się pojawią
Makroinstrukcje ASSERT i ASSERT_VALID pozwalają wykrywać błędy zaraz po ich po-
jawieniu się. Makroinstrukcję ASSERT można wykorzystać do sprawdzenia, czy zdefi-
niowany przez nas warunek jest prawdziwy (True). Przykładowo makroinstrukcja ASSERT
(a>l0) ostrzeże nas, jeśli wartość a będzie mniejsza niż .10.
W liniach 14 i 15 przyzywamy funkcję dostępu GetElements (), aby sięgnąć do listy
łańcuchów i należącą do klasy CStringList funkcję GetHead Position (), aby przypisać
nagłówkowi listy zmienną definiującą pozycję (POSITION) pos. Pętla while w Uniach 17-23
wykonywana jest dopóty, dopóki zmienna pos nie przyjmie wartości O, informując, że
dotarliśmy do końca listy.
Wewnątrz pętli w linii 21 łańcuchowi strEiement przypisywana jest wartość łańcu-
cha uzyskanego za pomocą funkcji GetNext (). Funkcja ta podaje wartość następnego


Widoki ListTree, Rich Edit i HTML 483
łańcucha listy (lub pierwszego, gdy jesteśmy jeszcze w nagłówku listy). Przy ostatnim
elemencie listy zmiennej pos przypisywana jest wartość zero i wykonywanie pętli zostaje
zakończone.
Na koniec nowy element łańcucha dołączany jest za pomocą funkcji insertltem() do
kontrolki List. Parametry tej funkcji to pozycja (numer kolumny, tutaj zero) i łańcuch, który
ma zostać dodany. Warto zauważyć, że do osadzonej wewnątrz kontrolki sięgamy tutaj za
pomocą funkcji GetListCtriO, która podobnie jak funkcja GetElements() zwraca odwołanie do
prywatnego elementu składowego (ang. private member) osadzonego wewnątrz, chroniąc jego
zawartość przed nieodpowiednimi modyfikacjami.
Jeśli po wprowadzeniu kodu przedstawionego na listingu 19.2 zbudujemy i uruchomimy
aplikację, powinniśmy zobaczyć widok List, taki jak na rysunku 19.1, wyświetlający w bardzo
nieskomplikowany sposób zawartość listy.
Lead 0ygen Osmium Gold Uranium Carbon
Rysunek 19.1. Prosty widok List, wyświetlający listę danych
Zmiana stylu listy
Lista w przykładzie powyżej została wyświetlona w sposób bardzo prymitywny. Do-
myślny styl rozmieszcza elementy w poziomych rzędach. Wybranie innego stylu spowoduje,
że lista będzie wyglądać atrakcyjniej. Przykładowo, aby uzyskać pionową listę, należy wybrać
styl LVS_LIST. Cztery dostępne style listy podane są w tabeli 19.1.
Podświetlanie całego wiersza honirolki List;' ''/:,'':'.;' . ^.K^";:^, : \:1\"^ ^?^:^:'1,
Standardowo gdy w trybie raportu (ang. repori modę) wybierzemy element, listy,
podświetlony zostanie tylko tekst w pierwszej kolumnie. Aby podświetlić także i pozostałe
informacje o elemencie, należy ustawić znacznik LVS_EX_FULLROWSEI,ECT. W tym
przypadku wiersz zostanie podświetlony również, gdy kiikniemy któryś z po-delementów
opisujących element listy.


484___________________________________Poznaj Visual C++ 6
Tabela 19.1. Style widoku List
Styl widoku List Opis stylu
LVS_LIST Prosty styl pionowej listy
LVS_REPORT Podobny do poprzedniego, tylko z nagłówkami nad poszczególnymi kolumnami
podelementów
LWS_ICON Duże ikony poukładane w rzędach od lewej do prawej LVS_SMALLICON
Małe ikony poukładane w rzędach od lewej do prawej
Listing 19.3 pokazuje zmiany, które należy wprowadzić, by zmienić domyślny styl LVS_ICON na styl
LVS_LIST. W tym celu pobieramy wartość stylu przypisaną oknu, zmieniamy ją i zmienioną zwracamy
temu oknu.
Listing 19.3. LST20_3.CPP - zmieniamy domyślny styl widoku List za pomocą funkcji Get-
WindowLong() i SetWindowLong()
1 GetListCtrK).Insertltem(0,strElement);
2 } .
3
4 // ** Pobierz bieżący znacznik stylu
5 DWORD dwStyle =
6 GetWindowLongfGetListCtrl().GetSafeHwnd(), O
7 GWL_STYLE) ;
8
9 // ** Usuń bieżący znacznik stylu
10 dwStyle &= ~LVS_TYPEMASK;
11
12 // ** Dodaj styl pionowej listy
13 dwStyle 1= LVS_LIST; @
14
15 // ** Zwróć znacznik do widoku List
16 SetWindowLong(GetListCtrl().GetSafeHwnd(),
17 GWL_STYLE,dwStyle);
18
19 // ** Odmaluj widok
20 SetRedraw(TRUE);
21 }
O W linii 6 pobieramy z kontrolki List bieżący styl.
@ Tutaj modyfikujemy styl.
W linii 16 odsyłamy zmodyfikowany styl do kontrolki List.


Widoki List.Tree, Rich Edit i HTML 485
Kod przedstawiony na listingu 19.3 należy dodać na końcu funkcji OninitialUpda-te() po
pętli while. Aby zdefiniować nowy styl, należy najpierw pobrać bieżący styl okna za pomocą
funkcji GetWindowLongO. Parametr GWL_STYLE informuje, że chcemy pobrać z parametrów
stylu okna bity ustawień stylu. Funkcja GetWindowLong () zwraca różne znaczniki związane z
oknem, a my chcemy zmienić tylko znacznik związany ze stylami LVS_, pozostałe
pozostawiając nietknięte. Uzyskana wartość przechowywana jest (linia 5) w zmiennej dwStyle
typu DWORD. W Unii 10 usuwany jest znacznik stylu za pomocą operatorów bitowych C++:
&= i ~. Za pomocą operatora ~ przed LVS_TYPEMASK odwracamy wartość bitów maski (zera
stają się jedynkami, a jedynki zerami).
Ponieważ bity maski przechowują wartości wszystkich stylów widoku List, odwrócenie
wartości bitów spowoduje, że wszystkie style oznaczone zostaną jako niewybrane. Teraz za
pomocą operatora &= wykonujemy operację logiczną AND na parametrach dwStyle i masce, w
wyniku czego bieżący styl widoku List zostaje wymazany.
Następnie za pomocą operatora l = wykonujemy w linii 13 operację logiczną OR, dodając
w ten sposób nowy znacznik do bieżących ustawień znaczników. Gdy już odpowiedni styl
zostanie ustawiony, należy go za pomocą funkcji SetWindowLong () przestać z powrotem do
zapisanych w oknie ustawień stylów. Parametrami funkcji SetWindow-LongO są. identyfikator
obsługi okna (ang. window handle), znacznik kontekstowy (GWL_STYLE) i zmodyfikowany
styl. Funkcja ta jest przyzywana w linii 16. Na koniec w linii 20 za pomocą funkcji SetRedraw
() polecamy widokowi List, żeby odmalował się ponownie na ekranie.
Zmienianie kolorów w widoku List ' ;' .. ':
Kolor tekstu w widoku List zmienić można za pomocą funkcji 3etTextColor (), kolor Ha
tekstu za pomocą funkcji setTxtBkColor (), a kolor tła całego widoku List za pomocą funkcji
SetBkColor'(),-.;: ;'.;;.-.,. ^L' :' .
Po zbudowaniu i uruchomieniu programu pojawi się Usta elementów taka jak na rysunku
19.2.
yEtKWf^SISPWWSfS . Fiie Eciit Yiew
Ue!p
f,D]^lyj'Jj^f@l^
Lead
Oxygen
Osmium
Gold
Uranium
Carbon
Rysunek 19.2. Widok List po zastosowaniu stylu LVS_LIST


Informacje o dodawaniu do widoku List ikon i innych elementów graficznych znaleźć można
w rozdziale 11.
Kolumny i nagłówki kolumn
Styl LVS_REPORT pozwala dodać do listy kolumny podelementów i nagłówki kolumn.
Prezentowany tutaj program byłby ciekawszy, gdyby do każdego z pierwiastków chemicznych
występujących w liście dodać jego symbol chemiczny i liczbę atomową.
Pierwszą zmianą, którą należy wprowadzić, jest uzupełnienie listy o dodatkowe in-
formacje. W dużych aplikacjach może pojawić się potrzeba przechowywania poszczególnych
informacji w ich własnych klasach. W tym przypadku aby program pozostał możliwie prosty,
dodatkowe informacje dodane zostaną na końcu każdego łańcucha, oddzielone od siebie
przecinkami (patrz listing 19.4). Aby edytować funkcję konstruktora dokumentu, należy w
panelu ClasView okna Project Workspace kliknąć dwukrotnie funkcję składową CListYDoc
klasy CListYDoc.
Listing 19.4. LST20_4.CPP - dodawanie do danych listy symbolu chemicznego i liczby ato-
mowej pierwiastka
1 CListYDoc::CListVDoc()
2 (
3 // TODO: tutaj dodaj kod konstruujący dokument
4
5 // ** Nazwy pierwiastków z symbolami chemicznymi i liczbami atomowymi
6 m_listElements.AddTail("Carbon,C,6") ;
7 m_listElements.AddTail("Uranium,U,92") ;
8 m_listElements.AddTail("Gold,Au,79") ;
9 m_listElements.AddTail("Osmium,0s,76") ;
10 m_listElements.AddTail("Oxygen,O,8") ;
11 mJ.istElements.AddTail("Lead,Pb,82") ;
12 }_________________________________________________________
Teraz, gdy dane zawarte w liście zostały zmienione, trzeba dodać nagłówki do nowych
kolumn listy. Można to zrobić wewnątrz funkcji Oninitialupdate () klasy CList-Wiew
wywiedzionej z klasy CListView. Jak widać z listingu 19.5, funkcja ta zrobiła się już całkiem
długa.


Widoki List/Tree, Rich Edit i HTML____________________________487
Listing 19.5. LST20_5.CPP - funkcja OninitialUpdate () dodająca do listy nowe kolumny





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void CListWiew: :OnXnitialUpdate () (
CListView::OninitialUpdate() ;
// TODO: Tutaj zapełniamy ListView odpowiednimi danymi II z
jego kontrolki List za pomocą funkcji GetListCtrl ()
II ** Dodaj kolumny i nagłówki
GetListCtrl().InsertCoiumn(O,"Element Name",
LVCFMT_LEFT,120);
GetListCtrl().InsertCoiumn(l,"Symbol",
LVCFMT_CEMTER,70);
GetListCtrl().InsertCoiumn(2,"Atomie Number",
LVCFMT_RIGHT,130);
// Pobierz wskaźnik dokumentu CListYDoc*
pDoc = GetDocument();
// Upewnij się, ze dokument jest legalny
ASSERT_VALID(pDoc) ;
// Ustal pozycję nagłówka listy łańcuchów
POSITION pos
pDoc->GetElements().GetHeadPosition () ;
// Póki pozycja nie jest NULL, dodawaj elementy
while(pos)
(
// Pobierz następny element listy
CString strElement =
pDoc->GetElements(),GetNext(pos) ;
// ** Wydobądź z łańcucha nazwę pierwiastka CString
strName =
strElement.Left(strElement.Find(",")) ;
// ** Wydobądź symbol chemiczny i liczbę atomową CString
strSymbol =
strElement.Mid(strElement.Find(",")+1); O
// ** Wydobądź liczbę atomową CString
strAtomicNumber =
strSymbol.MidfstrSymbol.Find(",")+!);


488______________ Poznaj Visual C++ 6





44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 }
// ** Odetnij liczbę atomową na końcu
strSymbol =
strSymbol.Left(strSymbol.Find(","));
// ** Dodaj do widoku listy na pozycji O
GetListCtrl().Insertitem(O,strName) ;
// ** Do drugiej kolumny wpisz symbol
GetListCtrl().SetItemText(O,l,
strSymbol) ;
// ** Do trzeciej kolumny wpisz liczbę atomową
GetListCtrl().SetItemText(O,2,
strAtomicNumber) ;
// Pobierz bieżący znacznik stylu DWORD
dwStyle ==
GetWindowLong(GetListCtrl().GetSafeHwnd(),
GWL_STYLE) ;
// Usuń bieżący znacznik stylu dwStyle
&= ~LVS_TYPEMASK;
// ** Dodaj styl raportu
dwStyle |= LVS_REPORT; @
// Prześlij nowy styl do widoku List
SetWindowLong(GetListCtrl().GetSafeHwnd(),
GWL_STYLE,dwStyle) ;
// Odmaluj ponownie widok
SetRedraw(TRUE) ;





O Tutaj rozcinamy łańcuch w miejscu przecinków, aby uzyskać osobne łańcuchy dla każdej
z kolumn.
Styl LVS_REPORT dodaje do widoku List dodatkowe kolumny z dającymi się rozciągać
nagłówkami.


Widoki List,Tree, Rich Edit i HTML 489
Na listingu 19.5 kolumny dodawane są za pomocą funkcji składowej insertColumn ()
kontrolki List w liniach 9,11 i 13. Parametrami tej funkcji są: numer kolumny, tytuł nagłówka,
znacznik formatowania i szerokość kolumny w pikselach. Każda z kolumn może być
sformatowana tak, aby tekst był wyjustowany do lewej, do prawej lub centralnie. Służą do
tego odpowiednio znaczniki: LVCFMT_LEFT, LVCFMT_RIGHT i LVCFMT_ CENTER.
Usuwanie kolumn
Po dołączeniu kolumn można usuwać je za pomocą funkcji DeieteColumn () podając numer
kolumny, którą należy usunąć.
Po dołączeniu do listy nagłówków kolumn trzeba dodać do każdej kolumny odpowiedni tekst. W
tym celu, tak jak to pokazaliśmy w liniach 29-46, należy najpierw wykonać odpowiednie krojenie
łańcucha na mniejsze części: strName, strSymbol i strAto-micNumber, które zostaną później wpisane do
odpowiednich kolumn. Warto zauważyć, że pierwsza kolumna jest zapełniana w linii 49 za pomocą
funkcji lnsertltem(), ale następne kolumny już za pomocą funkcji SetlfcemText (). Parametrami tej
funkcji są: pozycja elementu,' numer kolumny i dodawany tekst.
Na koniec trzeba skorzystać ze stylu LVS_REPORT, aby wyświetlić nagłówki kolumn. Dzieje się to w
linii 70 po usunięciu poprzedniego stylu LVST_LIST.
Po zbudowaniu i uruchomieniu programu pojawi się lista taka jak na rysunku 19.3.
fyS -t:.; !". '".{< .' ^.^'.iWiKi
iWW.^t^i^.^.i:;;.^,^^^:..;.;,^.,.:^';',^'1 .^w&
Fils Edit Yiew He!p
Symbol Atomie Numtaer





Lead
Ocygań
Osmiu
m
Gold
Ulanium
Carbon
Pb
O
Os
Au
U C
62






Rysunek 19.3. Widok List z trzema kolumnami
PATRZ TAKŻE
^ Ręczne edytowanie elementów widoku List opisane zostało w rozdziale 18


490___________________________________Poznaj Visual C++ 6
Odnajdywanie wybranych przez użytkownika elementów na liście
Jedną z typowych funkcji dostępnych w widoku List jest możliwość wybierania przez
użytkownika poszczególnych elementów na listy. Elementy oznaczone specjalnym znacz-
nikiem można odnajdywać za pomocą funkcji GetNextltem(). Funkcja ta ma dwa parametry -
pierwszy jest indeksem elementu, od którego funkcja rozpoczyna poszukiwania. W ten sposób
możemy zacząć szukać elementu poczynając od innego arbitralnie ustalonego elementu albo
jeśli przypiszemy temu parametrowi wartość -l, od początku listy. Drugi parametr jest
znacznikiem informującym, do jakiej kategorii należy element poszukiwany przez funkcję.
Lista znaczników podana jest w tabeli 19.2. Jak widać z tabeli 19.2, dostępnych jest kilka
znaczników, takich jak LVNI_TOLEFT pozwalających poszukiwać element według pewnych
kryteriów geometrycznych. Znaczniki te przydają się w przypadku, gdy widok List korzysta z
jednego z dwóch stylów wyświetlających ikony elementów. Funkcja GetNextltem() obsługuje
wszystkie te nietypowe przypadki, potrafi również odnaleźć element listy wybrany przez
użytkownika. Ten ostatni przypadek związany jest ze znacznikiem LVNI_SELECTED. Jeśli
wezwiemy funkcję GetNextltem() podając jej jako punkt wyjściowy ostatni zwrócony indeks,
funkcja odnajdzie następny element spełniający kryteria definiowane przez znacznik.
Mając indeks poszukiwanego elementu możemy użyć funkcji kontrolki List Getitem-Text
(), żeby zdobyć tekst tego elementu. Funkcja ta wymaga jako parametrów indeksu i numeru
kolumny poszukiwanego tekstu, a zwraca obiekt cstring zawierający poszukiwany tekst
elementu.
Tabela 19.2. Znaczniki wykorzystywane w funkcji GetNextltem ()
Znacznik Opis kategorii
LVNI_SELECTED Element wybrany przez użytkownika
LVNI_FOCUSED Element, na którym w danym momencie się koncentrujemy
(obramowany kropkowanym prostokątem)
LVNI_ALL Następny element, znacznik domyślny
LVNI_ABOVE Element ponad tym, od którego zaczynamy poszukiwania
LVNI__BELOW Element znajdujący się pod nim
LVNI_TOLEFT Element na lewo od niego
LVNI_TORIGHT Element na prawo od niego
W ten sposób można na przykład wyświetlić na pasku tytułowym listę aktualnie wy-
branych przez użytkownika elementów. W tym celu należy najpierw ustalić, kiedy tekst na
pasku tytułowym będzie uaktualniany. Najlepiej wykonać to, kiedy użytkownik kliknie w
obrębie listy. W tym momencie najpewniej zmieni się zestaw wybranych elementów. Należy
teraz przechwycić odpowiedni komunikat informujący o kliknięciu i za pomocą kreatora
CIassWizard utworzyć szkieletową funkcję obsługi.


Widoki List/Irce, Rich Edit i HTML 491
Dodawanie do programu funkcji obsługi zmieniającej tekst paska tytułowego
1. Wciśnij Ctri+W, aby uruchomić kreatora CIassWizard.
2. Wybierz kartę MessageMaps, upewniając się uprzednio, że lista kombinowana Cłass
Name wyświetla nazwę odpowiedniej klasy (tutaj CListWiew). Jeśli nie, wybierz
odpowiednią klasę.
3. Upewnij się, czy klasa CListWiew została wybrana w polu listy Object IDs.
4. Teraz znajdź w liście komunikatów Messages komunikat =NM_CLICK.
5. Kliknij dwukrotnie odnaleziony komunikat, a pojawi się okno dialogowe Add Mem-ber
Function z funkcją składową OnClick.
6. Aby dodać do programu nową funkcję obsługi, kliknij OK.
7. Kliknij Ędit Code, aby rozpocząć edycję nowej funkcji.
Do programu dołączona została w ten sposób nowa funkcja obsługi OnClick (), która
będzie wzywana za każdym razem, gdy użytkownik kliknie myszą w obrębie widoku List.
Żeby program wyświetlał w pasku tytułowym listę wybranych przez użytkownika ele-
mentów, należy umieścić wewnątrz funkcji fragment kodu przedstawiony na listingu 19.6.
Listing 19.6. LST20_6.CPP - odnajdywanie wybranych przez użytkownika elementów na
liście za pomocą funkcji GetNextItem ()





2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void CListWiew: : OnClick (NMHDR* pNMHDR,
LRESULT* pResult) {
// TODO: Tutaj dodaj własny kod obsługi kontrolki
*pResult = 0;
// ** Łańcuch przechowujący wybrane elementy
CString strSelectedItems;
// ** Startowy indeks funkcji GetNextItem() powinien być zerem
int nSelected=-l;
do
(
// ** Znajdź następny wybrany element nSelected =
GetListCtrl().GetNextItem( O
nSelected,LVNI_SELECTED); O
// ** Sprawdź, czy jakiś element został wybrany
if (nSelected != -l)
(


492_____________________________________Poznaj Visual C-K- 6
21 II ** Dodaj jego tekst do łańcucha
22 strSelectedItems += _" " +
23 GetListCtrl().GetItemText(nSelected,0); @
24 }
25 } while(nSelected != -l);
26
27 // ** Przypisz tytułowi dokumentu wartość łańcucha
28 GetDocument()->SetTitle(
29 "Selected:" + strSelectedItems);
30 }
O Funkcja GetNextitem() poszukuje elementów określonej kategorii. Tutaj znacznik
LVNI_SELECTED informuje ją, że ma poszukiwać elementów, które zostały wybrane przez
użytkownika. :
@ Dodajemy wybrany element do łańcucha z listą wybranych elementów. : :
Łańcuch strSelectedItems zadeklarowany w linii 8 wykorzystywany jest do prze-
chowywania listy wybranych przez użytkownika elementów. Warto zauważyć, że zmiennej
nSelected przypisana została w linii 11 wartość -l. Zmienna ta jest następnie wykorzystywana
jako indeks w przywoływanej w linii 15 funkcji GetNextltem(). Dodatkowo funkcji
GetMextltem() przesyłany jest znacznik LVNI_SELECTED informujący, że ma poszukiwać
elementów wybranych przez użytkownika.
Za pierwszym razem zmienna całkowita nSelected jest definiowana jako -l, aby funkcja
rozpoczęła poszukiwania od początku listy. Jeśli lista zawiera jeszcze wybrane elementy,
indeks kolejnego z nich jest przypisywany zmiennej nSelected. Wyrażenie warunkowe if z linii
19 sprawdza, czy zmienna nSelected nie przyjęła ponownie wartości -l (wartość -l oznacza, że
w liście nie ma już więcej wybranych elementów). Po odnalezieniu kolejnego wybranego
elementu, program przyzywa w linii 23 funkcję GetItemText przesyłając jej jako parametry
indeks odnalezionego parametru i kolumnę, w której się znajduje (w tym przypadku O, czyli
pierwszą kolumnę). Pobrany przez funkcję tekst jest dodawany razem z oddzielającą go od
poprzedniego elementu spacją do łańcucha strSelectedItems.
Warunek while w linii 25 powtarza całą pętlę zaczynającą się od słowa kluczowego do
dopóty, dopóki udaje się nam odnajdywać kolejne wybrane elementy. Gdy już wszystkie
zostaną odnalezione, w linii 28 definiujemy tytuł dokumentu.
Po zbudowaniu i uruchomieniu programu korzystającego z przedstawionej powyżej
funkcji, zobaczymy okno widoku List wyświetlające na pasku tytułowym listę wybranych
przez użytkownika elementów (rysunek 19.4).


Widoki ListTree, Rich Edit i HTML 493




nt>Wi^Mtllral^nłim:^&h^nR1":^^!^lN

Eii
? Q

E
&'

;d
il
Q

yie

W

U
e
K6

P














Element Name

Symbol



AtomicNumber



Lead

^'b



82















0



8



, Os

76



l Gold Au

79



iBE

iB
B

l







u



92



Carbon

c



6



|



















t8



Rysunek 19.4. Nazwy wybranych elementów wyświetlane są na pasku tytułowym
Widok Tree
Widoki List są bardzo przydatne, gdy trzeba wyświetlać i operować prostymi listami
elementów. Jednak czasami zachodzi potrzeba wyświetlenia danych ułożonych w hierar-
chiczną strukturę, w tym przypadku należy skorzystać z widoku Tree. Znakomitym przy-
kładem wykorzystania widoku Tree jest lewy panel Eksploratora Windows. W panelu tym
wyświetlona jest lista folderów, które można otwierać, by uzyskać listę folderów zawartych
wewnątrz nich.
PATRZ TAKŻE
O kontrolce Tree wewnątrz okna dialogowego pisaliśmy w rozdziale 6.
Informacje o tworzeniu okien z kilkoma widokami, takich jak okno Eksploratora Windows,
można znaleźć w rozdziale 20.
^ Informacje o tym jak zmienić domyślną czcionkę za pomocą funkcji Set Font () znaleźć
można w rozdziale 17.
Tworzenie widoku Tree za pomocą kreatora AppWizard
Kreator AppWizard pozwala na automatyczne utworzenie szkieletu aplikacji SDI opartej
na widoku Tree. Postępujemy w tym przypadku dokładnie tak samo jak przy tworzeniu
aplikacji opartej na widoku List, z tą tylko różnicą, że zamiast klasy CListview wybieramy
klasę CTreeView. Dlatego możemy bez obaw skorzystać z algorytmu "Tworzenie aplikacji
SDI bazującej na widoku List" wspomnianego wcześniej w tym rozdziale,


494 Poznaj Visual C++ 6
zmieniając tylko klasę CListview na CTreeYiew. Projekt wykorzystywany w prezento-
wanych w tym rozdziale przykładach nosi nazwę TreeV.
Style widoku Tree
Podobnie jak widok List, widok Tree również posiada odpowiedni zbiór znaczników
definiujących style. Jednak inaczej niż w widoku List, znaczniki te nie definiują sposobu
wyświetlania danych, a raczej różne komponenty, które można dodawać do wyświetlanego
drzewa, by wzbogacić jego wygląd. Te komponenty to linie między starszymi i potomnymi
elementami hierarchii i przyciski pozwalające zwijać lub rozwijać fragmenty hierarchii.
Istnieją również znaczniki pozwalające na zablokowanie możliwości przeciągania elementów
między różnymi punktami hierarchii i umożliwiające na ich ręczną edycję. Ważniejsze ze
znaczników podane są w tabeli 19.3.
Tabela 19.3. Znaczniki stylów widoku Tree


Znacznik
TVS_HASLINES
TVS_LIMESATROOT
TVS_HASBUTTONS
TVS_SHOWSELALWAYS TVS
DISABLEDRAGDROP
Opis działania
Rysuje linie między elementami potomnymi i ich rodzicami
Rysuje linie między bazowym elementem całej hierarchii a jego
elementami potomnymi
Rysuje przyciski pozwalające na zwijanie i rozwijanie
fragmentów hierarchii
Wybrany element pozostaje wybrany, nawet gdy inne okno stanie
się oknem aktywnym
Wyłącza możliwość przeciągania elementów w hierarchii






Większość aplikacji korzystających z widoku Tree korzysta z kilku z wymienionych
tutaj stylów, aby utworzyć interfejs podobny do tego, który oglądać możemy w Eksploratorze
Windows. Tak samo jak w widoku List, style te mogą być zmieniane poprzez pobranie
bieżących ustawień stylów za pomocą funkcji GetWindowLong (), zmodyfikowanie
odpowiednich bitów i zwrócenie ich oknu za pomocą funkcji SetWindowLongO. Na listingu
19.7 w liniach 56-63 ustawione zostały znaczniki TVS_HASLINES + TVS_HAS-BUTTONS +
TVS_LINESATROOT odpowiedzialne odpowiednio: za rysowanie linii do elementów
potomnych, wyświetlanie przycisków rozwijających gałęzie i rysowanie linii do głównego
elementu hierarchii (ang. root item).
Podświetlanie rzędu kontrolki Tree
Standardowo element drzewa jest podświetlany, gdy zostanie wybrany. Cały rząd włącznie z
elementami graficznymi można podświetlić ustawiając znacznik TVS_ FULLROW-SELECT.
Styl ten nie może występować równocześnie ze stylem TVS_ HASLINES.


Widoki List,Tree, Rich Edit i HTML 495
Łączenie elementu drzewa z danymi przechowywanymi w aplikacji
Czasami wygodnie jest połączyć każdy z elementów drzewa ze wskaźnikiem do
obiektu. Stużą do tego funkcje SetitemData ()',i GetItemData O.
Dodawanie elementów do drzewa
O widoku Tree najlepiej myśleć jako o liście zawierającej jako elementy dające się
rozwijać podlisty. Do wydobywania z widoku Tree odpowiedniej kontrolki służy funkcja
GetTreeCtrl (). Kiedy już wydobędziemy kontrolkę, możemy polecić funkcji insertl-tem()
dodanie do drzewa nowego elementu. Funkcja lnsertltem() występuje w kilku odmianach
wymagających przestania różnych parametrów, a w najprostszej wersji posiada trzy parametry.
Te parametry to: dodawany łańcuch, identyfikator (ang. handle) rodzica nowego elementu i
identyfikator elementu, po którym nowy element ma zostać dodany. Możemy przestać funkcji
tylko jeden parametr, wtedy dwa pozostałe zostaną zdefiniowane domyślnie tak, aby nowy
element został dodany pod elementem głównym i na końcu listy. Niemniej, takie dodawanie
elementów jest raczej bezcelowe, jako że otrzymamy w ten sposób zwykłą listę.
Funkcja lnsertltem() zwraca identyfikator dodanego elementu. Można go potem użyć w
zależności od potrzeb albo jako identyfikator rodzica, albo jako identyfikator elementu, po
którym nowy element ma zostać dodany. Rozpoczynając tworzenie drzewa należy pierwszemu
elementowi zadeklarować rodzica za pomocą znacznika TVI_ROOT. Znacznik ten określa, że
jego rodzicem będzie element główny. Dodając następny element możemy zdefiniować jako
rodzica pierwszy dołączony element, w ten sposób drzewo uzyska nową gałąź.
Trzeci parametr definiuje pozycję w gałęzi, w której dodany ma być nowy element.
Domyślnie parametrowi temu przypisywana jest wartość TVI__LAST, polecająca dołączyć go
na końcu listy. Można jednak przypisać mu identyfikator elementu listy, po którym chcemy
dodać nowy element lub znacznik TVI_SORT polecający funkcji wstawienie elementu do listy
w porządku alfabetycznym.
Usuwanie elementów drzewa
Do usuwania elementów drzewa służy funkcja składowa Deleteltem (). Funkcja ta pobiera
identyfikator HTREEITEM z dodawanego elementu.
Korzystając z wspomnianych znaczników można, tak jak pokazaliśmy na listingu 19.7,
dodawać nowe elementy w różnych miejscach hierarchii widoku Tree. Funkcja
Oninitialupdate () dodawana jest do programu przez kreator AppWizard w momencie


496___________________________________Poznaj Visual C++ 6
tworzenia projektu. Korzystając z niej można dodać odpowiednie elementy do drzewa tuż przed
wyświetleniem widoku.
Listing 19.7. LST20J7.CPP - dodawanie elementów do widoku Tree





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void CTreeWiew: :OnInitialUpdate () {
CTreeView::OnInitialUpdate() ;
// TODO: TreeView można zapełnić elementami / / z kontrolki Tree wzywając
funkcję GetTreeCtrl ()
11 ** Zadeklaruj skrót do kontrolki Tree CTreeCtrl& tree =
GetTreeCtrlO;
// ** Dodaj element na poziomie bazowym HTREEITEM hAnimals =
tree.Insertitem("Animals");
// ** Dodaj podelement do elementu z poziomu bazowego HTREEITEM hVerts =
tree.Insertitem("Yertibrates",hAnimals) ;
// ** Dodaj pode Jemen ty do elementu hVerts
tree.Insertitem("Whales",hVerts,TVI_SORT) ;
tree.Insertitem("Dogs",hVerts,TVI_SORT) ;
tree.Insertitem("Humans",hVerts,TVI_SORT) ;
// ** Dodaj podelement do elementu z poziomu bazowego HTREEITEM hlnverts =
// ** Dodaj podelementy do elementu hlnverts
tree.Insertitem("Jellyfish",hlnverts,TVI_SORT) ;
tree.Insertitem("Worms",hlnverts,TVI_SORT) ;
tree.Insertltem("Snails",hlnverts,TVI SORT) ;
// ** Dodaj element na poziomie bazowym po hAnimals
HTREEITEM hPlants =
tree.Insertitem("Plants",TVI_ROOT,hAnimals) ;
// ** Dodaj podelement do elementu z poziomu bazowego
HTREEITEM hFruit =
tree.Insertitem("Fruit",hPlants) ;
// ** Dodaj podelementy do elementu hFruit


Widoki List,Tree, Rich Edit i HTML 497





41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 )
tree.Insertitem("Apples",hFruit,TVI__SORT) ;
tree.Insertitem("Plums",hFruit,TVI_SORT);
tree.Insertitem("Pears",hFruit,TVI_SORT) ;
// ** Dodaj poćtelement do elementu z poziomu bazowego
HTREEITEM hCereal =
tree.Insertitem("Cereal",hPlants);
// ** Dodaj podelementy do elementu hCreal
tree.InsertItem("Wheat",hCereal,TVI_SORT) ;
tree.Insertitem("Rye",hCereal,TVI_SORT) ;
tree.Insertitem("Rice",hCereal,TVI_SORT) ;
// ** Pobierz bieżący znacznik stylu DWORD dwStyle =
GetWindowLong(GetTreeCtrl().GetSafeHwndO, GWL_STYLE) ;
// ** Dodaj własne style O dwStyle |=
TVS_HASLINES +
TVS_HASBUTTONS + TVS_LINESATROOT;
// ** Zwróć je z powrotem do widoku Tree
SetWindowLong(GetTreeCtrK).GetSafeHwndO,
GWL_STYLE,dwStyle) ;
// ** Odmaluj widok
SetRedraw(TRUE);





Ustawianie znaczników styli.
W linii 9 listingu 19.7 deklarowany jest obiekt tree będący odwołaniem do klasy
CTreeCtris. W ten sposób tworzymy skrót, który oszczędza nam wzywania funkcji Get-
TreeCtrl () za każdym razem, gdy musimy sięgnąć do osadzonej wewnątrz widoku kon-
trolkiTree.
Dla pierwszego elementu dodawanego w linii 12 musimy zdefiniować tylko jeden pa-
rametr, łańcuch "Animals" (zwierzęta). Drugi parametr zdefiniowany jest domyślnie jako
TVI_ROOT. Trzeci parametr również domyślnie jest definiowany jako TVI_AFTER, jednak
ponieważ jest to pierwszy element, kolejność nie ma tutaj znaczenia.


498 Poznaj Visual C++ 6
W linii 16 dodawany jest element "Vertibrates" (kręgowce) definiujący jako swojego
rodzica hAnimals, w ten sposób staje się elementem potomnym (ang. child item) elementu
"Animals".
Zwierzęta będące kręgowcami są następnie dodawane w liniach 19-21. Warto zauważyć,
że podają one jako identyfikator rodzica hverts i korzystają ze znacznika TVI_SORT, aby ułożyć
się w porządku alfabetycznym.
W liniach 23-52 dodawane są w podobny sposób pozostałe elementy drzewa. W ten
sposób powstanie hierarchiczny, złożony z kilku gałęzi widok Tree. Odpowiednie znaczniki
styli drzewa definiowane są w liniach 56-66.
Po zbudowaniu i uruchomieniu aplikacji pojawi się okno z widokiem Tree, takim jak na
rysunku 19.5. Żeby zobaczyć wszystkie dołączone elementy, należy rozwinąć gałęzie za
pomocą przycisków.
fr fcaf., "ns* -aap - ,1- !' ' , . ./ !- ., .

^'"i^Mftói''11 ' 11 : ^"''^ :: 1!

.-. Wlir-
a^
'-, Vrtbwi> : : ,-Ooyf li i : : Hwnans :: i ' Whale \ | B
Im/ertibrates I: ' i-Jell^tsh : ' !- Snails : ^ '-Womu : S Plants l SFruit : i \
Apples : : i-Pears i - Rums ' B-Cereal i ' Rice 1 j.-Rye . Wheat :



Rysunek 19.5. Widok Tree z rozwiniętymi gałęziami
Odnajdywanie wybranego węzła drzewa
Wybrany węzeł drzewa odnaleźć można za pomocą funkcji składowej kontrolki Get-
SelectedltemO zwracającej identyfikator HTREEITEM wybranego przez użytkownika elementu.
Można również skorzystać z funkcji GetNextltem(), która działa tak samo jak analogiczna
funkcja GetNextitem() widoku List. Wersja funkcji dostępna w widoku Tree ma dwa
parametry - pierwszym jest identyfikator HTREEITEM, a drugim znacznik definiujący kategorię
elementów, które mają być poszukiwane. Możliwe wartości tego znacznika podane zostały w
tabeli 19.4. Funkcja GetNextitem() zwraca elementy należące do poszukiwanej kategorii lub
jeśli nie odnajdzie żadnego elementu, wartość NULL.


Widoki ListJree, Rich Edit i HTML____________________________499
Tabela 19.4. Znaczniki funkcji GetNextltem () widoku Tree
Znacznik Opis efektu
TVGN_CARET Znajduje elementy wybrane przez użytkownika
TVGN_ROOT Zwraca element poziomu bazowego odpowiadający danemu elementowi
TVGN_PAREMT Zwraca rodzica danego elementu
TVGN_CHILD Zwraca pierwszy element potomny; bieżącemu elementowi trzeba
przypisać wartość NULL
TVGN_NEXT Znajduje poprzedni element potomny
TVGNJ?REVIOUS Znajduje następny element potomny
TVGN_PREVIOUS_VI s IBLE Zwraca poprzedni widoczny element
TVGN_FIRST_VXSIBLE Znajduje następny widoczny element
Przywołując funkcję SelectItemO i podając identyfikator HTREE l TEM elementu, który
chcemy wybrać, możemy wybrać element z poziomu programu. Zdobywszy odpowiedni
identyfikator HTREEITEM elementu za pomocą funkcji GetSelectitemO lub GetNextltem ()
można korzystając z funkcji GetltemText () zdobyć tekst wybranego elementu.
Na listingu 19.8 przedstawiona jest funkcja ustalająca, który element drzewa został
wybrany przez użytkownika i pobierająca tekst tego elementu. Podobnie jak w widoku List,
funkcja obsługi OnSelchanged () wykorzystywana jest do przechwytywania odbitego
komunikatu powiadamiającego (ang. reflected nofification message) TVN_SELCHANGED w
klasie widoku. Funkcję tę można dodać do programu z karty CIassWizard Message Maps.
Listing 19.8. LST20_8.CPP - pobieranie tekstu z elementu wybranego przez użytkownika
1 void CTreeWiew: : OnSelchanged (NMHDR* pNMHDR, LRESULT*
pResuit)
2 (
3 NM_TREEVIEW* pNMTreeYiew = (NM_TREEVIEW*)pNMHDR;
4
5 // ** Znajdź identyfikator wybranego elementu
6 HTREEITEM hSelected =
7 GetTreeCtrl().GetSelectedItem() ;
8
9 // ** Sprawdź, czy identyfikator został znaleziony
10 if (hSelected >= 0)
11 (
12 // ** Pobierz tekst wybranego elementu
13 CString strSelected =


500_____________________________________Poznaj Visual C++ 6
14 GetTreeCtrl().GetItemText(hSelected) ;
15
16 // ** Przypisz ten tekst tytułowi dokumentu
17 GetDocument()->SetTitle(strSelected) ;
18 }
19
20 *pResult = 0;
21 }
W linii 6 listingu 19.8 wykorzystujemy funkcję GetSelectedItemO, by uzyskać
identyfikator wybranego przez użytkownika elementu. Następnie w linii 9 upewniamy się, że
w ogóle jakiś element został wybrany, czyli czy udało nam się pobrać identyfikator. Jeśli tak,
w linii 14 za pomocą funkcji GetItemText () pobieramy w linii 14 tekst wybranego elementu i
w linii 17 przypisujemy go tytułowi dokumentu.
Po uruchomieniu programu, do którego została załączona przedstawiona tu funkcja,
zobaczymy okno widoku Tree, w którym na pasku tytułowym pojawiać się będzie nazwa
wybranego elementu.
Ręczne edytowanie elementów drzewa
Niektóre aplikacje pozwalają na modyfikowanie tekstu elementów widoku Tree poprzez kliknięcie
wybranego elementu i ręczne wpisanie nowego tekstu. Operację taką możemy nazwać ręcznym
edytowaniem (ang. iniine editing). Obsługę ręcznego edytowania można bardzo łatwo zaimplementować
w programie korzystając ze znacznika stylu TVS_EDITLABELS i obsługując kilka komunikatów
powiadamiających (ang. notification messages). Znaczniki tych komunikatów to TVS_BEGINLABELEDIT i
TVN_ENDLABELEDIT. Za pomocą kreatora CIassWizard można im przypisać odpowiednie funkcje obsługi
OnBe-ginLabeledit() i OnEndLabeledit().
Ręczne edytowanie w widoku List
Aby wprowadzić możliwość ręcznego edytowania do widoku List. należy skorzystać
Ze Stylu LVS_EDITLABELS.
Gdy dodamy już do widoku Tree styl TVS_EDITLABELS, użytkownik będzie mógł uruchomić ręczne
edytowanie tekstu elementu po prostu klikając odpowiedni element drzewa. Następnie wzywana jest
funkcja obsługi OnBeginLabeledit (). Wewnątrz funkcji obsługi wzywana jest funkcja GetEditControl (),
która umożliwia modyfikowanie dynamicznie tworzonej kontrolki Edit dodawanej do drzewa, aby
możliwa była ręczna edycja elementów. Uzyskany w ten sposób wskaźnik kontrolki można wykorzystać
na przykład do zmieniania koloru czy ograniczania długości wprowadzanego tekstu.


Widoki List,Tree, Rich Edit i HTML 501
Po zmianie tekstu elementu aby zakończyć edytowanie, należy wcisnąć Enter lub kliknąć
klawiszem myszy poza obszarem kontrolki Edit. W tym momencie przyzywana jest funkcja
obsługi OnEnabledit (). Teraz za pomocą funkcji GetEditControl () ponownie sięgamy do
kontrolki Edit, tym razem zwracając zmodyfikowany tekst. W tym momencie można
zatwierdzić zmieniony tekst i wysłać go z powrotem do drzewa. Jeśli w tym momencie tekst
nie zostanie odesłany do drzewa, wprowadzane zmiany zostaną utracone i element powróci do
stanu, w jakim był przed rozpoczęciem edycji. Do odsyłania tekstu elementu do drzewa służy
funkcja SetltemText ().
Styl TVS_EDITLABELS można dodać do bieżących styli drzewa w następujący sposób:
// ** Dodaj listę stylów
dwStyle |= TVS_HASLINES + TVS_HASBUTTONS + TVS_LINESATROOT +
TYSJEDITLABELS;
// ** Dodaj możliwość edytowania etykiety
Funkcje obsługi OnBeginLabeledit () i OnEndLabeledit () pokazane zostały na listingu
19.9.
Uruchomienie ręcznej edycji,' . " ' ' ; .
Uruchomienie edycji dementu.jest odrobinęskomplikowane. Należy kUknąć element drzewa
dwa razy, jednak z krótką pauzą między kolejnymi tdiknię.cianzi. .
Po odpowiednim zdefiniowaniu stylu, dodaniu przedstawionych tutaj funkcji obsługi,
zbudowaniu i uruchomieniu aplikacji otrzymamy widok Tree, w którym po dwukrotnym
kuknięciu można będzie edytować tekst dowolnego elementu, tak jak to pokazano na rysunku
19.6.
Listing 19.9. LST20_9.CPP - funkcje OnBeginLabeledit () i OnEndLabeledit () umożli-
wiające ręczną edycję elementów
1 void CTreeWiew: :OnBeginlabeledit (NMHDR* pNMHDR,
2 LRESULT* pResult)
3 {
4 TV_DISPINFO* pTVDisp!nfo = (TV_DISPINFO*)pNMHDR;
5 // TODO: Tu dodaj własną, funkcję obsługi komunikatów
6
7 GetTreeCtrl() .GetEditControl()->LimitText(20); O
8
9 *pResult = 0;
10 }
11
12 void CTreeWiew: :OnEndlabeledit (NMHDR* pNMHDR, LRESULT* pResult)




13 (
14 TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
15 // TODO: Tu dodaj własną funkcję obsługi komunikatów
16
17 // ** Pobierz zmodyfikowany tekst z kontrolki Edit
18 CString strText;
19 GetTreeCtrl().GetEditControl()->
20 GetWindowText(strText);
21
22 // ** Tutaj można sprawdzić i zatwierdzić tekst kontrolki
23
24 // ** Sprawdź, czy łańcuch nie jest pusty
25 if (strText.GetLength()>0)
26 {
27 // ** Pobierz identyfikator wybranego elementu
28 HTREEITEM hSelected = pTVDispInfo->item.hitem;
29
30 // ** Odeślij zmodyfikowany tekst @
31 GetTreeCtrl().SetItemText(hSelected,strText) ;
32 '}
33
34 *pResult = 0;
35 }







Ograniczanie długości teksiu edytowanego w kontrolce Edit. @ Zwracanie
zmodyfikowanego tekstu z powrotem do elementu drzewa.
Kod funkcji obsługi OnBeginLabeleditO jest dość prosty. Jedyny fragment kodu nie
dodany przez kreatora CIassWizard znajduje się w linii 7, gdzie rozmiar tekstu przyj-
mowanego przez kontrolkę Edit ograniczany jest do 20 znaków.
Funkcja OnEndLabeleditO jest bardziej skomplikowana. W liniach 19 i 20 tekst elementu
pobierany jest z kontrolki Edit. Jeśli długość łańcucha jest różna od zera (co sprawdzamy w
linii 25), z przesłanego funkcji wskaźnika struktury TV_DISPINFO pobierany jest identyfikator
edytowanego elementu. Identyfikator ten jest następnie w linii 31 wykorzystywany do
odsyłania zmodyfikowanego tekstu do wybranego elementu.
Widok Rich Edit
Widok Rich Edit pozwala przy stosunkowo małym wysiłku włożonym w programowanie
aplikacji utworzyć zaawansowany i dający się dostosowywać do naszych potrzeb interfejs
użytkownika. Widok ten jest całkowicie OLE-aktywny (ang. OLE-enabled), co


Widoki ListJree, Rich Edit i HTML 503
oznacza, że możemy swobodnie dołączać do tekstu rysunki, filmy oraz efekty dźwiękowe.
Jest to dość obszerny temat, dlatego w tym miejscu tylko krótko go zarysujemy.
A/Wi.3f"
Płonił eFiuB .
AppłBianilOrangit
:. -Psa?
? jpiums im
B-Celem -
Ric . Rye
Mnal
Rysunek 19.6. Ręczne edytowanie w widoku Tree
Tworzenie widoku Rich Edit
Aplikację SDI bazującą na widoku Rich Edit tworzy się za pomocą kreatora AppWi-zard
w ten sam sposób jak aplikacje SDI bazujące na widokach Tree i Edit. Trzeba tylko na
ostatniej karcie kreatora wybrać w kombinowanej liście widoków klasę CRichEditView.
Utworzymy teraz przykładowy projekt RichV demonstrujący możliwości widoku Rich
Edit.
Kiedy kukniemy przycisk Finish, pojawi się okno pytające, czy chcemy dołączyć do
aplikacji obsługę kontenera OLE (ang. OLE container). W tym miejscu należy kliknąć OK,
ponieważ widok Rich Edit działa jak kontener OLE. Sprawę można yałatwić wcześniej
wybierając na trzeciej stronie kreatora AppWizard, pod pytaniem What Compound
Document Support Would You Like to Include?, opcję fiontainer.
Widok Edit , , .. , .: , - . -' , - ^\ :
Istnieje również prostszy służący do edycji tekstu widok Edit, bazujący na wielo-wierszowej
kontrolce Edit. Nie ma on lych możliwości edycyjnych i nie obsługuje technologii OLE
tAjak widok Rich Edit, może się jednak przydać, jeśli potrzebujemy stosunkowo prostego i
łatwego do zaprogramowania edytora. Ten widok jest reprezentowany przez klasę
CEdifcView, którą definiujemy na ostatniej stronie kreatora AppWizard./ ',,;, - , ^ 1, "
1"':' ^'-^ ^.;1 ''\";:-;^,-,:1 ':;;''';../ ' 1


504___________________________________Poznaj Visual C++ 6
Po wciśnięciu przycisku OK wystarczy zbudować i uruchomić aplikację. Otrzymamy w
ten sposób zaawansowany edytor tekstu, bez konieczności żadnego dodatkowego pro-
gramowania.
PATRZ TAKŻE
Kontenery OLE opisane zostały dokładnie w rozdziale 25.
Zachowywanie i ładowanie tekstu
Jeśli w utworzonej aplikacji wpiszemy do widoku Rich Edit tekst, możemy zachować go
klikając w menu File polecenie Save i wpisując nazwę pliku. Po zamknięciu i ponownym
uruchomieniu aplikacji zachowany tekst będzie można odtworzyć klikając w menu File
polecenie Open, następnie wybierając nazwę zachowanego pliku i klikając OK. Jak widać,
edytor obsługuje zachowywanie i ładowanie plików bez żadnego wkładu z naszej strony.
Podobnie drukowanie i podgląd wydruku implementowane są do aplikacji automatycznie.
Dzieje się tak dlatego, że do programu załączone zostały funkcje plikowe kontenera OLE. Gdy
widok Rich Edit jest aktywny związane z nim odpowiednie opcje obsługi plików są
uaktywniane i automatycznie implementowane do programu.
PATRZ TAKŻE
Więcej informacji na temat ładowania plików znaleźć można w rozdziale. 23.
Przegląd kontenerów OLE znaleźć można w rozdziale25.
FornialoYi.ynif akapiió','.' tckylis
Warto zauważyć, że wśród załączonych opcji me ma obstugi formatowania akapitów
tekstu. Widok Rich Edit dostarcza licznych bardziej podstawowych funkcji edytora tekstu, ale
pozostawia programiście możliwość dostosowywała ik- w^isnych pon/A b;-dziej
zaawansowanych opcji interfejsu użytkownika.
Możemy oczywiście dodać odpowiednie elementy mscriejsu pozwalające iomiatować
wybrane akapity tekstu. Do paska narzędziowego dodaliśmy trzy nowe przyciski pozwalające
formatować do prawej, do lewej lub wycentrowywać tekst akapitu. Przyciski te dodajemy do
paska narzędziowego, tak jak to opisaliśmy w instrukcji w rozdziale 14.
Można zdefiniować własną oprawę graficzną tych trzech dołączanych przycisków. Moje
niezdarne wysiłki w tym kierunku obejrzeć można na pasku narzędziowym widocznym na
rysunku 19.7. Mój bardziej uzdolniony artystycznie przyjaciel stworzył wspaniałą mapę
bitową (.bmp), która dołączona do tekstu wewnątrz widoku Rich Edit pokazuje możliwości
edycyjne utworzonego w ten sposób edytora. Rysunki można dołączać do tekstu za pomocą
polecenia Insert New Object znajdującego się w menu Edit.


Widoki ListJree, Rich Edit i HTML 505
This Image was Inserted trom the Edlt menu by selecting the Insert New Object menu option.

The powerful Rich Edlt View In ActlonI
Rysunek 19.7. Widok Rich Edit w czasie pracy
Po dodaniu ikon przycisków należy każdemu z nich przypisać odpowiedni identyfikator definiujący
ich funkcję: ID_ALIGNLEFT, ID_ALIGNCENTER i ID_ALIGNRIGHT. Teraz za pomocą kreatora CIassWizard
dodajemy funkcje obsługi poleceń przycisków: OnAlign-Left(), OnAlignCenter () i OnAlignRight ().
Funkcje te należy utworzyć w klasie
CRichWiew.
Kod funkcji formatujących akapity tekstu jest banalnie prosty (listing 19.10). Widok Rich Edit
korzysta ze struktury PARAFORMAT, aby zdefiniować kilka operacji formatowania. Zmienna składowa
dwMask będąca maską dla znaczników operacji jest w linii 6 wykorzystywana do definiowania, która z
nich ma być wykonana. Dostępne operacje podane zostały w tabeli 19.5. Większość z nich związana jest
z definiowaniem odstępów. Maski znaczników mogą reprezentować każdą ze zmiennych składowych
struktury PARAFORMAT, która ma zastosowanie dla danego akapitu. W ten sposób możemy definiować
zmienne pojedynczo (jak w tym przykładzie) lub kilka naraz, dodając odpowiednie znaczniki przy-
pisywane masce.


506___________________________________Poznaj Visual C++ 6
Tabela 19.5. Wartości masek zmiennej składowej dwMask struktury PARAFORMAT
Ustawienie znacznika Wykonywana operacja maski
PFM_ALIGNMENT Akapit tekstu jest justowany odpowiednio w zależności od znacznika
zapisanego w zmiennej wAlignment
PFM_NUMBERING Akapit tekstu jest numerowany wartością zapisaną w zmiennej
wNumbering
PFM_TABSTOPS Za pomocą cTabStop i tablicy rgxTabs można zdefiniować rozkład
tabulatorów
PFM_OFFSET Zmienna dx0ffset definiuje szerokość odstępu dla akapitu
PFM_OFFSETINDENT Zmienna dx3tart0ffset definiuje szerokość odstępu w czasie
formatowania
PFM_RIGHTINDENT Zmienna dxRight!ndent definiuje odstęp względem prawego marginesu
PFM_STARTINDENT Zmienna dxStartlndex definiuje szerokość dodawaną do każdego
zmienianego akapitu
Listing 19.10. LST20_10.CPP - formatowanie akapitów tekstu w widoku Rich Edit
1 void CRichWiew: :OnAiigncenter ()
2 {
3 // TODO: Tutaj dodaj własną funkcję obsługi polecenia
4
5 PARAFORMAT pf;
6 pf.dwMask = PFM_ALIGNMENT;
7 pf.wAiignment = PFA_CESTER; @
8 SetParaFormat(pf) ;
9 }
10
11 void CRichWiew: :OnAlignlef t ()
12 (
13 // TODO: Tutaj dodaj własną funkcję obsługi polecenia
14
15 PARAFORMAT pf;
16 pf.dwMask = PFM_ALIGNMENT;
17 pf.wAiignment = PFA__LEFT; @ (
18 SetParaFormat(pf) ;
19 }
20
21 void CRichWiew: :OnAlignright ()
22 (


Widoki List.Tree, Rich Edit i HTML 507
23 // TODO: Tutaj dodaj własna funkcję obsługi polecenia
24
25 PARAFORMAT p f;
26 pf.dwMask = PFM_ALIGNMENT;
27 pf.wAlignment = PFA_RIGHT; @
28 SetParaFormat(pf) ;
29 }
O Przypisywanie zmiennej znacznika centrowania.
@ Przypisywanie zmiennej znacznika justowania do lewej.
Przypisywanie zmiennej znacznika justowania do prawej.
W liniach 6 i 7 definiowany jest tylko znacznik PFM_ALIGNMENT i zmienna składowa struktury
wAlignment. Następnie struktura jest przesyłana do funkcji składowej SetParaFormat (), która formatuje
akapit w zależności od wartości zapisanych w strukturze (linia 8).
Funkcje'OnAlignLef t () i OnAlignRight () są prawie identyczne, z tą tylko różnicą, że znacznik
PFA_CENTER jest zastępowany odpowiednio znacznikami PFA_LEFT i
PFA_RIGHT.
Po dodaniu tych funkcji, zbudowaniu i uruchomieniu programu będziemy mogli ju-stować
akapity tekstu klikając odpowiednie przyciski paska narzędzi.
Dodawanie obiektów OLE
Ponieważ widok Rich Edit obsługuje kontener OLE, możemy dodawać do tekstu rysunki
i efekty medialne, korzystając ze standardowych opcji menu OLE. Aby to przetestować,
wystarczy kliknąć menu Edit i wybrać opcję Insert New Object. Pojawi się wtedy
standardowe okno dialogowe Insert Object. W oknie będzie dostępna szeroka gama różnych
typów OLE. Typy te można swobodnie załączać do widoku Rich Edit.
PATRZ TAKŻE
Informacje na temat technik OLE i COM można znaleźć w rozdziale 25.
HTML - widok do budowania przeglądarki
Podobnie jak widok Rich Edit, widok HTML jest bardzo rozbudowanym widokiem
pozwalającym udostępnić tworzonej przez nas aplikacji pełnię możliwości przeglądarki
sieciowej Microsoft Intemet Explorer 4. Tworząc ten widok należy zaprogramować od-
powiednie elementy interfejsu i połączyć je z przeglądarką - resztę pracy wykona za nas


508___________________________________Poznaj Visual C++ 5
kompilator. Tak samo jak poprzednio, temat ten jest dość rozległy i tutaj tylko opiszemy go
pobieżnie.
Co oznacza skrót HTML?
HTML jest skrótem nazwy języka Hypertext Markup Laneuage. Język ten jest standardowym językiem
wykorzystywanym do prezentowania zawartości stron interne-towych. Język ten wykorzystuje do
definiowania informacji dotyczących formatu znaczniki (ang. tags), a ponadto pozwala na stosowanie
grafiki i tabulacji.
Tworzenie widoku HTML
Aplikację opartą na widoku HTML inożn;.i utworzyć ::i\ pomoc;' kreato':;'- AppWiz-ird,
wybierając na ostatniej stronie jako klasę bazową (B^se ciass) klasę CHtmlView. Kreator
AppWizard utworzy standardowy szkielet aplikacji, w którym główna klasa widoku wy-
wiedziona będzie z klasy CHtmlView. Tutaj pokażemy jak korzystać z różnych możliwości i
funkcji oferowanych przez widok HTML.
Co to jest URL?
URL (Universal Resource Locator) może być adresem strony internetowej na przykład hktp:
.//chaos l .demon.co.uk. Może być również lokalną stroną internetową utworzoną w naszym
programie, plikiem tekstowym, archiwum FTP lub dowolnym innym akceptowanym przez
przeglądarkę zasobem. :
Definiowanie adresu URL
Aby rozpocząć przeglądanie, należy wezwać funkcję Navigafce2 () klasy CHtmlView
przesyłając jej odpowiedni URL.
Przeglądarka znajdzie teraz, jeśli to tylko możliwe, poszukiwaną stronę i wyświetli ją
wewnątrz widoku. Poprzez zdefiniowany przez nas pasek narzędzi można wzywać różne
funkcje usprawniające działanie przeglądarki: GoFoward (), GoBack (), GoSearch (), GoHo-
me () czy Refresh (). Funkcje te wykonują te same czynności co odpowiednie przyciski w
większości przeglądarek.
Funkcja ExecWB () umożliwia korzystanie z różnych poleceń OLE (część z nich została
przedstawiona w tablicy 19.6), pozwalających zmieniać rozmiar czcionki, czy drukować
bieżącą stronę. Funkcja ta korzysta z kilkunastu znaczników poleceń i zmiennej typu
CO!eVariant, w której przesyłany jest odpowiedni parametr.


Widoki List.Tree, Rich Edit i HTML_____________________________509
Przykładowo, by zmienić rozmiar czcionki, trzeba odwołać się do niej w następujący sposób:
C01eVariant vaFont3ize(9);
ExecWB(OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &
vaFontSize, NULL) ;
Typ C01eVariant jest typem definiującym obiekt, który może przechowywać w jednej zmiennej
zarówno łańcuchy, liczby całkowite, daty, jak i liczby zmiennoprzecinkowe. Obiekty takie są dość często
wykorzystywane w COM i OLE do przesyłania do wspólnych funkcji danych niezdefiniowanego typu.
Funkcji ExecWB () można przesłać różnorodne polecenia umożliwiające wykonanie dowolnej funkcji
przeglądarki.
Tabela 19.6. Znaczniki poleceń OLE dla funkcji ExecWB ()
Znacznik polecenia OLE Opis
OLECMDID_SAVEAS Zachowaj bieżącą stronę OLECMDID_PRINT Wydrukuj
bieżącą stronę OLECMDID_ZOOM Zdefiniuj wartość powiększenia OLECMDID_FIND
Znajdź tekst bieżącej strony OLECMDID_STOP Przerwij sprowadzanie strony OLECMDI D_COPY
Kopiuj stronę do schowka OLECMDID_ENABLE_INTERACTION Włącz lub wyłącz interakcję z
użytkownikiem
Obsługa zdarzeń przeglądarki
Prawdopodobnie w tworzonej aplikacji pojawi się potrzeba zareagowania na różne zdarzenia
przeglądarki, takie jak kliknięcie przez użytkownika hipertącza. Zdarzenia obsługujemy pokrywając
odpowiednie funkcje wirtualne.
Funkcji OnBeforeNavigate2 () przesyłany jest łańcuch z adresem URL. Można tutaj sprawdzić
legalność łańcucha lub wykorzystać funkcję do uruchomienia animacji (takiej jak obracająca się kula
ziemska w Intemet Explorerze). Prototyp tej funkcji (ang. prototype) wygląda tak:
void OnBeforeNavigate2(LPCTSTR IpszURL, DWORD nFlags,
LPCTSTR IpszTargetFrameName, CByteArrayS baPostedData, LPCTSTR IpszHeaders,
BOOL* pbCancel);
Inaczej niż w przypadku innych wirtualnych funkcji, pokrywanie tej funkcji nie wymaga odwołania
do klasy bazowej. Przyzywając tę funkcje można przerwać nawigowanie przypisując zmiennej
*pbCancel wartość True.
Odpowiednie zdarzenie kończące nawigację to OnNawigateComplete2 (), którego prototyp wygląda
tak:


510___________________________________Poznaj Visual C-H- 6
virtual void OnNavigateComplete2(LPCTSTR strURL) ;
Jeśli w funkcji OnBeforeNavigate () uruchomiliśmy animacje lub inny proces, w tym
właśnie miejscu możemy go przerwać.
Tekst informacji o statusie normalnie wyświetlany na dole okna przeglądarki można
pobrać za pomocą funkcji OnStatusTextchanged (), która jest definiowana tak jak poniżej:
virtual void OnStatusTextChange(LPCTSTR lpszText);
Parametr lpszText przechowuje wskaźnik do tekstu nowej informacji o statusie.
Funkcja OnProgressChange () przywoływana jest przy kolejnych postępach ładowania
strony. Funkcja wirtualna jest zdefiniowana w następujący sposób:
virtual void OnProgressChange(long nProgress,
long nProgressMax) ;
Zmienna nProgress określa jaka część operacji ładowania (nProgressMax) została wykonana do tej
pory. Rozmiar ładowanego obiektu (nProgressMax) można zdefiniować za pomocą funkcji ExecWB (),
przesyłając razem z definiowanym rozmiarem znacznik
OLECMDID_SETPROGRESSMAX.
Funkcje OnDownIoadBeginf) i OnDownIoadComplete () są przyzywane, kiedy odpo-
wiednio rozpoczyna się lub kończy proces ściągania pliku. Można wykorzystać je do wyświe-
tlania odpowiednich komunikatów ostrzegawczych lub zawieszenia procesu ściągania pliku.
Inne dostępne w widoku pokrywalne funkcje obsługi zdarzeń powiadamiających po-
zwalają na dołączenie do przeglądarki możliwości przechwytywania lub sprawdzania
legalności poleceń, zanim zostaną wykonane. Pozwalają również ustalić, kiedy polecenia
zostaną wykonane. Niestety jest to temat zbyt obszerny, by go tutaj omawiać i wspomnieliśmy
o nim tylko po to, żeby pokazać możliwości klasy CHtmlview.


Wyszukiwarka

Podobne podstrony:
19 Nowy Testament List do Zydow
3 19 Dokumenty, widoki i SDI (2)
TI 99 08 19 B M pl(1)
show list
19 Nauka o mózgu
[W] Badania Operacyjne Zagadnienia transportowe (2009 04 19)
track list
anonymous ftp sites list nl 2
anonymous ftp sites list org 7

więcej podobnych podstron