Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö



Samankaltaiset tiedostot
Tekstikontrollit LUKU. Tekstin ja sanomien esittäminen valintaikkunoissa. Tekstin muokkaaminen suorituksen aikana. Tiedon tarkistaminen syötön aikana

Usean näkymän luominen

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssi Y1

UpdateIT 2010: Editorin käyttöohje

MDI-sovellusten kehittäminen

Ohjelmoinnin perusteet Y Python

Käyttäjän käsikirja. LIB 500 ja LIB 510 v Releasettelutyökalu Yleistä. ,NNXQDMRNDLOPRLWWDDHWWlNRKGHRQSlLYLWHWWlYl

6.1 Tekstialueiden valinta eli maalaaminen (tulee tehdä ennen jokaista muokkausta ym.)

ASENNUS- JA KÄYTTÖOHJE

Ohjelmoinnin perusteet Y Python

Hiirisanomiin vastaaminen

Muuttujien määrittely

Visual C++ -ohjelman tekeminen ja suunnittelu

Ohjelmoinnin perusteet Y Python

Jypelin käyttöohjeet» Ruutukentän luominen

Siirtyminen Outlook versioon

Sisältö. 22. Taulukot. Yleistä. Yleistä

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

1. HARJOITUS harjoitus3_korjaus.doc

Dokumentit, näkymät ja kehykset

Luento 5. Timo Savola. 28. huhtikuuta 2006

Uutiskirjesovelluksen käyttöohje

Listarakenne (ArrayList-luokka)

Tärkeimmät toiminnot. Kertausta ja uusia toimintoja Wordistä sekä tiedostonhallinnasta. Tärkeimmät toiminnot jatkuu...

TALLENNETAAN MUISTITIKULLE JA MUISTIKORTILLE

Harjoitustyö: virtuaalikone

Sisältö. 2. Taulukot. Yleistä. Yleistä

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

Tilastokeskuksen rajapintapalveluiden käyttöönotto QGISohjelmistossa

Tehtävän V.1 ratkaisuehdotus Tietorakenteet, syksy 2003

Ohjelmoinnin perusteet Y Python

Kehitysympäristö LUKU. Developer Studio kehitysympäristön alkeet. Liikkuminen projektin työtilassa ja sen eri näkymissä

Ohjelmoinnin perusteet Y Python

Tekstinkäsittelyn jatkokurssi

,QWHUQHWVHODLPHQNl\WWlPLQHQ±,QWHUQHW([SORUHU

TAULUKKO, KAAVIO, SMARTART-KUVIOT

Ohjelmoinnin perusteet Y Python

Verkkosivut perinteisesti. Tanja Välisalo

Fonttien käyttö LUKU. Tekstin esittäminen värein ja tyylein. Fonttien käyttö sovelluksen viimeistelyyn OSA IV LUKU 17.

FrontPage Näkymät

KÄYTTÖOHJE. Servia. S solutions

Muistitikun liittäminen tietokoneeseen

Valintanauhan komennot Valintanauhan kussakin välilehdessä on ryhmiä ja kussakin ryhmässä on toisiinsa liittyviä komentoja.

Google-dokumentit. Opetusteknologiakeskus Mediamylly

Nettiposti. Nettiposti käyttöohje

Osoitin ja viittaus C++:ssa

Opera Hotel Edition. Arvonlisäverokantojen muutos Operaan Finland. Toukokuu 2010 MICROS-Fidelio Finland Oy, Hotel Systems HelpDesk

ITKP102 Ohjelmointi 1 (6 op)

Väitöskirja -mallipohja

MICROSOFT EXCEL 2010

ActiveX-kontrollien käyttö

Ohjelmointikielet ja -paradigmat 5op. Markus Norrena

ULKOISET KÄYTTÄJÄT / YHTEISTYÖMAAPALVELUT...

TIETOKONEEN ASETUKSILLA PARANNAT KÄYTETTÄVYYTTÄ

Ohjelmoinnin perusteet Y Python

ITKP102 Ohjelmointi 1 (6 op)

Web Services tietokantaohjelmoinnin perusteet

KÄYTTÖÖN. Koulukirjat tietokoneelle PIKAOHJEET PAPERPORT -OHJELMAN. Sisällysluettelo

Ylläpitoalue - Etusivu

Skype for Business pikaohje

Esimerkkiprojekti. Mallivastauksen löydät Wroxin www-sivuilta. Kenttä Tyyppi Max.pituus Rajoitukset/Kommentit

OHJE EXCEL-MAKRON LUOMISEKSI JA MAKRON KÄYTÖSTÄ

Kirkkopalvelut Office365, Opiskelijan ohje 1 / 17 IT Juha Nalli

Verkkojulkaiseminen Minna Väisänen. HTML5-tehtävä

Tik Tietojenkäsittelyopin ohjelmatyö Tietotekniikan osasto Teknillinen korkeakoulu KÄYTTÖOHJE. LiKe Liiketoiminnan kehityksen tukiprojekti

Matlabin perusteita Grafiikka

Tekstinkäsittely ja opinnäytetyö I sisällysluettelo ja sivunumerointi. Word 2007


Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

PlanMan Project projektihallintaohjelmisto koulutusohjeistus

6 XML-työkalut 1. 6 XML-työkalut

Tekstinkäsittelyn jatko. KSAO Liiketalous 1

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

1.1 Pino (stack) Koodiluonnos. Graafinen esitys ...

Maastotietokannan torrent-jakelun shapefile-tiedostojen purkaminen zip-arkistoista Windows-komentojonoilla

Ohjelmoinnin peruskurssi Y1

Condes. Quick Start opas. Suunnistuksen ratamestariohjelmisto. Versio 8. Quick Start - opas Condes 8. olfellows 1.

UpdateIT 2010: Uutisten päivitys

3.3 Kurssin palauttaminen

Ohjelmoinnin perusteet Y Python

OpenOffice.org Impress 3.1.0

VSP webmail palvelun ka yttö öhje

Sisällys. 18. Abstraktit tietotyypit. Johdanto. Johdanto

Javan perusteita. Janne Käki

Käyttöohje. Energent MagiCAD plugin

Ohjelmoinnin perusteet Y Python

GeoGebra-harjoituksia malu-opettajille

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2

Haaga-Helia/IltaTiko ict2tcd005: Ohjelmiston suunnittelutaito 1/7 Anne Benson. Tällä opintojaksolla käytämme VS:n kolmen kokonaisuuden luomiseen:

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Zeon PDF Driver Trial

VERKKOVELHO-YLLÄPITOTYÖKALUN KÄYTTÖOHJE

18. Abstraktit tietotyypit 18.1

ASENNUS JA KÄYTTÖOHJE

TAULUKOINTI. Word Taulukot

Kirjaudu sisään palveluun klikkaamalla Omat kartat -painiketta.

SATAKUNNAN AMMATTIKORKEAKOULU. Hakala Toni Varpelaide Heidi TEKSTINKÄSITTELYN OHJEET CASE: OPINNÄYTETYÖN RAPORTOINTI WORDILLA

Transkriptio:

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö OSA V 439 LUKU 19 19 LUKU Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö Luettelon tietojen ylläpito List View näkymässä Tiedon järjestäminen hierarkkisesti Tree View näkymässä Monipuolisen tekstinmuokkauksen toteutus Rich Edit View näkymällä Webbiselailun toteuttaminen sovelluksessasi

440 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö Mitä ovat List, Tree ja Rich Edit - näkymät List, Tree ja Rich Edit näkymät perustuvat valintaikkunoissa käytettäviin vastaaviin kontrolleihin. Niiden toimintaperiaatteena on ollut kontrollin toimintojen upottaminen itse näkymään. Näkymänä käytettäessä nämä toiminnat muodostavat sovellukselle hyvin vahvan perustan. List View näkymän luominen ja käyttö Monet sovellukset perustuvat luetteloiden käyttöön. Esimerkiksi Resurssienhallinta (Explorer) käyttää List View -näkymää sovellusikkunan oikeanpuoleisessa ruudussa. List View näkymässä käyttäjä voi jopa hieman vaikuttaa luettelon esitystapaan. Luettelon alkiot voidaan esimerkiksi esittää pienin tai suurin kuvakkein tai saraketietojen kera. Luettelo voidaan järjestää eri sarakkeiden mukaan ja luettelosta voidaan kerralla valita vain yksi tai monta alkiota. Kaikki nämä toiminnot ovat valmiina käytettävissä, joten voit keskittyä itse sovelluksen tekemiseen luettelon esittämiskoodin sijaan. KATSO MYÖS Luettelokontrolli valintaikkunassa luvun 6 alussa. Monen näkymän käyttö Resurssienhallinnan tapaan luvussa 20. Oletusfontin muuttaminen SetFont():illa luvussa 17. List View sovelluksen luominen AppWizardilla Voit luoda helposti tavallisen näkymän sijaan List View näkymää käyttävän SDI-sovelluksen AppWizardilla. Teemme sovellusrungon ja tutkimme esimerkin avulla List-näkymän ominaisuuksia. List View näkymään perustuvan SDI-sovellusrungon luominen 1. Valitse File-valikosta New. 2. Valitse Projects-välilehti ja projektityyppien luettelosta MFC AppWizard (exe).

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö 3. Napauta nyt Project Name ruutua ja anna nimeksi ListV. 4. Napauta OK. MFC AppWizard Step1 ikkunan pitäisi tulla esiin. 5. Valitse tässä ikkunassa Single Document ja napauta Nextpainiketta, kunnes päädyt viimeiseen vaiheeseen (Step 6, ikkunassa ruutulipun kuva). 6. Napauta AppWizardin luotavien luokkien luettelosta CListVView-luokkaa. 7. Nyt Base Classes yhdistelmäruudun pitäisi olla käytössä. Avaa ruudun luettelo nuolesta ja näet käytettävissä olevat kantaluokat. 8. Valitse näistä CListView kuvan 18.1 tapaan. 9. Napauta Finish. 10. Napauta New Project Information ikkunassa OK ja AppWizard tekee uuden projektin lähdekooditiedostoineen. Nyt sinulla on SDI-sovelluksen runko ja sen päänäkymä perustuu CListView-luokkaan. Voisit kääntää ja ajaa sovelluksen, mutta koska luettelo on vielä tyhjä, ei sovellus poikkeaisi ulkoisesti tavallisesta CView-sovelluksesta. Joudumme lisäämään luetteloon muutamia alkioita ennen näyttämistä. OSA V LUKU 19 441 Alkioiden lisääminen Oikeat sovellukset joutuvat pitämään datansa erossa näkymästä dokumenttiluokan (tai jonkun oman luokan) avulla. Näkymäluokka tulisikin jättää ainoastaan näkymään liittyville toiminnoille. Oikea paikka luettelon jäsenille onkin CDocument-kantaluokasta peritty CListVDoc. Teemme sovelluksen datan tekstiluettelosta, esimerkiksi alkuaineiden nimistä. Tätä varten sopii mainiosti MFC:n CListString-luokka. Voit lisätä yhden luokan olion dokumenttiin seuraavasti. Kokoelmaluokat MFC:n CStringList on esimerkki kokoelmaluokista (collection class). Kokoelmaluokka hallitsee tietyntyyppistä tietojoukkoa. Esimerkiksi CStringList-luokassa tämä tietojoukko on luonnollisesti luettelo CString-olioita. Jäsenmuuttujan lisääminen ClassView-sivulta 1. Valitse projektin työtilaikkunassa ClassView. 2. Avaa ListV-sovelluksen luokat löytääksesi luokan CListVDoc. 3. Napauta luokkaa hiiren oikealla painikkeella saadaksesi esiin pikavalikon.

442 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö 4. Valitse Add Member Variable -komento ja saat esiin vastaavan ikkunan. 5. Syötä muuttujan tyypiksi (Variable Type) CStringList ja siirry seuraavaan kenttään sarkaimella. 6. Syötä Variable Declaration ruutuun m_listelements. 7. Valitse Private Access asetus ja lisää uusi tekstiluettelojäsen OK:lla. Vahinkojen ehkäiseminen saantifunktioilla ja yksityisillä jäsenmuuttujilla Tietokoneohjelmia kirjoitettaessa mikä tahansa voi mennä vikaan - ja todennäköisemmin meneekin, etenkin demotilanteessa. Jäsenmuuttujien suojaaminen ja saantifunktioiden käyttö vähentää onnettomuusriskiä. Nyt projektissa on tekstiluettelo (String List) upotettuna dokumenttiluokkaan. Private Access asetus saa aikaan sen, että luetteloon pääsevät käsiksi ainoastaan dokumenttiluokan funktiot. Tällä estetään muuttujan arvon muuttaminen vahingossa muista luokista. Se ei tosin näin pienessä sovelluksessa ole todennäköistä, mutta on hyvä opetella tapa suurempien sovelluksien varalle. Tarkoitus on antaa muuttujan käsittelyoikeus ainoastaan luotettaville saman dokumenttiluokan funktioille. Public Access tarkoittaisi, että kaikkien luokkien funktiot saisivat käsitellä muuttujaa ja Protected melkein samaa kuin Private. Tosin Private tyyppiset jäsenet on suojattu kaikkien muiden luokkien käsittelyltä, mutta Protected -jäseniin päästään käsiksi johdetuissa luokissa. Kyseessä on olio-ohjelmointiin liittyvä toiminta enkä aio vaivata sillä liiaksi, mutta tämä on tärkeää käsiteltäessä upotettua luettelokontrollia CListVView-luokasta. Jäsenmuuttujaamme ei siis voida käsitellä dokumentin ulkopuolelta. Tämä saattaisi muodostua ongelmaksi, koska list view näkymä joudutaan täyttämään dokumentissa olevan tekstiluettelon tiedoilla. Vastaus löytyy kuitenkin saantifunktioista (access function). Näiden tarkoitus on taata luotettava yksityisten (private) jäsenmuuttujien käsittely. Kun tiedät, ettei muuttujaan pääse käsiksi kuin tietyllä funktiolla, voit ongelmatilanteessa jäljittää syyn vain funktiota tutkimalla. Lisäämme siis saantifunktion dokumentin jäsenfunktioksi tekstiluettelon käsittelemiseksi. Seuraa siis ohjeita m_listelementstekstiluettelon palauttavan saantifunktion lisäämiseksi. Jäsenfunktion lisääminen ClassView-sivulla 1. Napauta hiiren oikealla painikkeella CListVDoc-luokkaa saadaksesi esiin luokan pikavalikon. 2. Valitse Add Member Function komento ja saat esiin vastaavan valintaikkunan.

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö 3. Syötä Function Type ruutuun const CStringList& ja siirry seuraavaan ruutuun sarkaimella. 4. Syötä Function Declaration ruutuun GetElements(). 5. Lisää uusi jäsenfunktio GetElements() OK-painikkeella. OK:n napautuksen jälkeen saat esiin GetElements()-funktion editorin ikkunaan. Lisää funktioon seuraava elementtiluettelon palauttava rivi: return m_listelements; Koska funktio palauttaa tyypin const CStringList&, pääsevät dokumenttiluokan ulkopuoliset funktiot ainoastaan lukemaan tekstiluetteloa. Tämä määrätään const-avainsanalla. Näkymäluokka voi siis lukea luetteloa, muttei muokata sitä. Tämä sopii hyvin, koska luetteloa onkin tarkoitus muokata ainoastaan dokumenttiluokassa. List view näkymän kokeilemiseksi tarvitaan sovellukseen hieman dataakin. Alustamme siis dokumenttiluokan muodostimessa luettelon alkioiksi. Pääset muokkaamaan dokumenttiluokan muodostinta kaksoisnapauttamalla CListVDoc-luokan CListVDoc-funktiota (muodostimen nimi on aina sama kuin luokan nimi). Lisää elementit testaamista varten listauksen 19.1 mukaisesti. LISTAUS 19.1 LST19_1.CPP alkioiden nimien lisääminen luetteloon dokumenttiluokan muodostimessa CListVDoc 1 CListVDoc::CListVDoc() 2 { 3 // TODO: add one-time construction code here 4 // ** Add Element names to the String List 5 m_listelements.addtail("carbon"); 6 m_listelements.addtail("uranium"); 7 m_listelements.addtail("gold"); 8 m_listelements.addtail("osmium"); 9 m_listelements.addtail("oxygen"); 10 m_listelements.addtail("lead"); 11 } OSA V LUKU 19 443 Listauksen 19.1 riveillä 5 10 alkiot lisätään m_listelementsluetteloon syöttämällä CStringList-luokan AddTail()-funktiolle vastaava teksti. Funktio lisää alkion luettelon viimeiseksi. Seuraavaksi joudut lataamaan testidatan List view näkymään näkymää ensimmäistä kertaa näytettäessä. Pääset käsiksi luetteloon ainoastaan GetElements()-saantifunktiolla, joten joudut kutsumaan sitä näkymän OnInitialUpdate()-funktiossa. OnInitialUpdate()-

444 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö funktiota kutsutaan ainoastaan kerran, ennen näkymän näyttämistä ensimmäistä kertaa. Löydät funktion ClassView-sivulta CListVViewluokan alta kaksoisnapauttamalla OnInitialUpdate()-funktion nimeä. Lisää sitten listauksen 19.2 rivit funktioon saadaksesi kopioitua alkiot dokumenttiluokan luettelosta List view näkymäluokkaan. LISTAUS 19.2 LST19_2.CPP Alkioiden lisääminen List view näkymään InsertItem()-funktiolla 1 Dokumentti löydetään näkymäluokasta käsin GetDocument()-funktiolla. 2 Tässä alkio lisätään luetteloon InsertItem()-funktiolla. ASSERT-makroja käyttämällä saadaan ongelma esiin ennen sen ilmaantumista ASSERT() ja ASSERT_VALID()- makrot auttavat löytämään ohjelmavirheet aikaisessa vaiheessa. ASSERT-makrolla voidaan varmistaa, että ehtolause on tosi (TRUE). Esimerkiksi ASSERT(a>19) antaa näkyvän virheilmoituksen, jos a on 10 tai alle. 1 void CListVView::OnInitialUpdate() 2 { 3 CListView::OnInitialUpdate(); 4 5 // TODO: You may populate your ListView with items 6 // its list control through a call to GetListCtrl() 7 8 // ** Get a pointer to the document 9 CListVDoc* pdoc = GetDocument(); 1 10 // ** make sure it is a valid document 11 ASSERT_VALID(pDoc); 12 13 // ** Find the head position of the string list 14 POSITION pos = 15 pdoc->getelements().getheadposition(); 16 17 // ** While the position is not NULL, add elements 18 while(pos) 19 { 20 // ** Get the next element in the list 21 CString strelement = 22 pdoc->getelements().getnext(pos); 23 24 // ** Insert it into the list view at position 0 25 GetListCtrl().InsertItem(0,strElement); 2 26 } 27 } Saat osoittimen dokumenttiin rivillä 9 esitettyyn tapaan GetDocument()-funktiolla. Tämä palauttaa osoittimen näkymän omistavaan dokumenttiin. Rivin 11 ASSERT_VALID()-makro tarkistaa, että osoitettava olio on voimassa (siis CListVDoc-dokumentti). Riveillä 14 ja 15 käytetään uutta GetElements()-saantifunktiotasi hakemaan tekstiluettelo (string list) ja kyseisen CStringList-tyyppisen olion funktiolla GetHeadPosition() asetetaan POSITIONtyyppinen pos-muuttuja osoittamaan luettelon alkuun. while-

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö silmukka (riviltä 18) suorittaa rivien 20 25 lauseita niin kauan, kuin pos-muuttuja pysyy nollasta poikkeavana eli luettelossa on vielä jäljellä jäseniä. Silmukan sisällä rivillä 21 asetetaan strelement-merkkijono GetNext()-funktion palauttamaksi merkkijonoksi. GetNext()-funktio palauttaa käsiteltävää merkkijonoa seuraavan alkion luettelosta tai ensimmäisen luettelon alusta alettaessa. Kun viimeinen jäsen on haettu, pos-muuttuja asetetaan nollaksi ja while-silmukka loppuu seuraavalla kierroksella. Viimeisenä silmukassa asetetaan uusi merkkijono luettelokontrolliin InsertItem()-jäsenfunktiolla. Tämä funktio käyttää ensimmäisenä parametrinään paikkaa luettelossa (tässä nolla) ja lisättävää merkkijonoa. Huomaa vielä, että sain upotetun luettelokontrollin näkymästä GetListCtrl()-funktiolla, joka on täysin omaa GetElements()- funktiotani vastaava, eli se palauttaa viittauksen upotettuun yksityiseen (private) jäseneen suojaten jäsentä vahingossa tehtävältä muokkaamiselta. Käännettyäsi ja ajaessasi sovelluksen listauksen 19.2 muutosten tekemisen jälkeen, pitäisi esiin tulla kuvan 19.1 kaltainen List view luettelonäkymä, jossa näkyy muutamien alkuaineiden nimiä hyvin yksinkertaisessa asettelussa. OSA V LUKU 19 445 KUVA 19.1 Alkuaineita esitettynä yksinkertaisessa luettelonäkymässä. Luettelokontrollin koko rivin korostaminen Luettelon tyylin muuttaminen Tässä vaiheessa luettelonäkymä on vielä ulkoasultaan varsin karkea. List view näkymän oletustyyli näyttää luettelon alkiot levitettynä koko riville. Saat aikaan paremman näköistä jälkeä muuttamalla näkymän tyyliä. Jos esimerkiksi haluat esittää luettelon alkiot päällekkäin, voit käyttää LVS_LIST-tyyliä. Taulukossa 19.1 on esitetty valittavissa olevat 4 eri tyyliä. Alkion valitseminen luettelokontrollista raporttitilassa esittää ainoastaan rivin ensimmäisen sarakkeen korostettuna. Voit korostaa koko rivin asettamalla LVS_EX_FULLROWSELECTlipun. Tämä mahdollistaa myös rivin valitsemisen mitä tahansa sen saraketta napauttamalla.

446 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö TAULUKKO 19.1 List view näkymän tyylit Tyyli LVS_LIST LVS_REPORT LVS_ICON LVS_SMALLICON Kuvaus Paljas, luettelomainen tyyli Kuten LVS_LIST, mutta mukana myös sarakeotsikot Suuret kuvakkeet, järjestettyinä ensin vasemmalta oikealle ja seuraaville riveille tarpeen mukaan. Pienet kuvakkeet, järjestettyinä ensin vasemmalta oikealle ja seuraaville riveille tarpeen mukaan. Listauksessa 19.3 esitetään tarpeelliset lisäykset koodiin tyylin muuttamiseksi luettelomaiseksi (LVS_LIST) kuvakepohjaisesta oletustyylistä (LVS_ICON). Temppu tehdään lukemalla ensin ikkunaan liitetyt tyyliominaisuudet, muuttamalla niiden arvoja ja asettamalla ne uudelleen ikkunan tyyleiksi. LISTAUS 19.3 LST19_3.CPP List view näkymän oletustyylin muuttaminen GetWindowLong()- ja SetWindowLong()- funktioilla 1 Rivillä 6 luetaan luettelokontrollin nykyinen tyyli. 2 Tässä tyyliä muokataan. 3 Rivillä 16 asetetaan muokattu tyyli takaisin luettelokontrolliin. 1 GetListCtrl().InsertItem(0,strElement); 2 } 3 4 // ** Get the current style flags 5 DWORD dwstyle = 6 GetWindowLong(GetListCtrl().GetSafeHwnd(), 7 GWL_STYLE); 1 8 9 // ** Remove the current style flags 10 dwstyle &= ~LVS_TYPEMASK; 11 12 // ** Add the List style 13 dwstyle = LVS_LIST; 2 14 15 // ** Set it back into the list view 16 SetWindowLong(GetListCtrl().GetSafeHwnd(), 17 GWL_STYLE,dwStyle); 3 18 19 // ** Redraw the list view 20 SetRedraw(TRUE); 21 } Listauksen 19.3 rivit lisätään OnInitialUpdate()-funktioon whilesilmukan jälkeen. Tyylin asettamiseksi täytyy aluksi lukea ikkunan sen hetkinen tyyli, mikä tehdään GetWindowLong()-funktiolla.

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö Syöttämällä hakufunktiolle GWL_STYLE-lipun saat siltä paluuarvona tyylilippujen ohessa paljon muutakin tietoa. Näitä et kuitenkaan halua muuttaa vaan ainoastaan LVS-tyylilippuja. SetWindowLong()-funktion palauttama arvo talletetaan rivillä DWORD-tyyppiseen muuttujaan dwstyle. Rivin 10 koodi poistaa tästä arvosta tyyliliput käyttäen C++:n & (JA) sekä ~-operaattoreita. LVS_TYPEMASK-maskin arvot komplementoidaan ~-operaattorilla (eli ykköset nolliksi ja päinvastoin). OSA V LUKU 19 447 Käytetty maski pitää luetut List view -tyylit ennallaan ja käänteinen maski asettaa kaikki muut bitit maskattuja lukuun ottamatta. Kun tämän jälkeen suoritetaan looginen AND-operaatio tyylimaskin ja vanhojen asetusten kesken, saadaan kaikki List view -näkymän tyyliasetukset poistettua. Nyt tyylit voidaan määritellä puhtaalta pöydältä käyttäen ORoperaattoria ( ), kuten rivillä 13 on tehty. Tämä lisää annetun lipun sen hetkisiin lippuasetuksiin. Kun tyylin asettaminen on tehty, kirjoitetaan asetukset takaisin ikkunaan SetWindowLong()-funktiolla. Funktiolle syötetään sen ikkunan kahva, johon kirjoitetaan, kirjoitettavat asetukset (GWL_STYLE) sekä muokattu asetusarvo (rivi 16). Lopuksi rivin 20 SetRedraw() List view ikkuna määrätään piirtämään itsensä uudelleen. Kun olet tehnyt muutokset, käännä ja aja sovelluksesi. Tuloksen pitäisi näyttää kuvan 19.2 mukaiselta. List view -näkymän värien muuttaminen Voit muuttaa List view -näkymän tekstin edustaväriä SetTextColor()-funktiolla ja tekstin taustaväriä SetTextBkColor()-funktiolla. Koko näkymän taustaväri voidaan muuttaa SetBkColor()-funktiolla. KUVA 19.2 List view luettelonäkymän alkiot esitettynä LVS_LISTtyylillä. Sarakkeiden ja sarakeotsikoiden lisääminen Voit lisätä helposti vaihtuvalevyisiä sarakkeita otsikoineen käyttämällä LVS_REPORT-tyyliä. Saat ohjelmasta vielä kiintoisamman lisäämällä

448 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö ylimääräisiin sarakkeisiin alkuaineen kemiallisen merkin sekä atomiluvun. Aluksi joudut lisäämään näyttöön data-alkioita. Suuremmassa sovelluksessa nämä tiedot kannattaisi pitää ehkä aivan omassa luokassaan. Tässä ne on yksinkertaisuuden vuoksi lisätty jo käytössä olevien merkkijonojen jatkeeksi pilkulla erotettuina, kuten listauksesta 19.4 ilmenee. Pääset muokkaamaan luokan muodostinfunktiota kaksoisnapauttamalla projektin työtilaikkunan ClassView-sivulla CListVDoc-luokan alta CListVDoc()-funktiota. LISTAUS 19.4 LST19_4.CPP Kemiallisten merkkien ja atomi lukujen lisääminen merkkijonoihin 1 CListVDoc::CListVDoc() 2 { 3 // TODO: add one-time construction code here 4 5 // ** Elements names with symbols 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,os,76"); 10 m_listelements.addtail("oxygen,o,8"); 11 m_listelements.addtail("lead,pb,82"); 12 } Nyt, kun data on muutettu, joudut lisäämään uusien alkioiden sarakeotsikot. Voit tehdä tämän CListView-kantaluokasta perityn CListVView-luokkasi OnInitialUpdate()-funktiossa, joka on esitetty kokonaisuudessaan listauksessa 19.5. LISTAUS 19.5 LST19_5.CPP OnInitialUpdate()-funktio sarakkeiden näyttämiseen 1 void CListVView::OnInitialUpdate() 2 { 3 CListView::OnInitialUpdate(); 4 // TODO: You may populate your ListView with items 5 // its list control through a call to GetListCtrl() 6 // ** Insert the columns and headings 7 GetListCtrl().InsertColumn(0,"Element Name", 8 LVCFMT_LEFT,120); 9 GetListCtrl().InsertColumn(1,"Symbol", 10 LVCFMT_CENTER,70);

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö 11 GetListCtrl().InsertColumn(2,"Atomic Number", 12 LVCFMT_RIGHT,130); 13 // Get a pointer to the document 14 CListVDoc* pdoc = GetDocument(); 15 // make sure it is a valid document 16 ASSERT_VALID(pDoc); 17 // Find the head position of the string list 18 POSITION pos = 19 pdoc->getelements().getheadposition(); 20 // While the position is not NULL, add elements 21 while(pos) 22 { 23 // Get the next element in the list 24 CString strelement = 25 pdoc->getelements().getnext(pos); 26 // ** Find the name part of the string 27 CString strname = 28 strelement.left(strelement.find(",")); OSA V LUKU 19 449 29 // ** Find the symbol & Number part 30 CString strsymbol = 31 strelement.mid(strelement.find(",")+1); 1 32 // ** Find the atomic number part 33 CString stratomicnumber = 34 strsymbol.mid(strsymbol.find(",")+1); 1 Tässä osassa merkkijono pilkotaan pilkkujen kohdalta ja jokainen sarake saadaan omaksi merkkijonokseen. 35 // ** Cut the atomic number from the end 36 strsymbol = 37 strsymbol.left(strsymbol.find(",")); 38 // ** Insert it into the list view at 0 39 GetListCtrl().InsertItem(0,strName); 40 // ** Set the second column text to the symbol 41 GetListCtrl().SetItemText(0,1, 42 strsymbol); 43 // ** Set the third column text to the symbol 44 GetListCtrl().SetItemText(0,2, 45 stratomicnumber); 46 } 47 // Get the current style flags 48 DWORD dwstyle = 49 GetWindowLong(GetListCtrl().GetSafeHwnd(), 50 GWL_STYLE);

450 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö 51 // Remove the current style flags 52 dwstyle &= ~LVS_TYPEMASK; 2 LVS_REPORT-tyyli lisää tavalliseen luettelonäkymään skaalattavat sarakeotsikot. 53 // ** Add the List style 54 dwstyle = LVS_REPORT; 2 55 // Set it back into the list view 56 SetWindowLong(GetListCtrl().GetSafeHwnd(), 57 GWL_STYLE,dwStyle); 58 59 // Redraw the list view 60 SetRedraw(TRUE); 61 } Sarakkeiden tuhoaminen Voit tuhota sarakkeita niiden lisäämisen jälkeen DeleteColumn()-funktiolla antamalla parametrinä poistettavan sarakkeen numeron. Listauksessa 19.5 sarakkeet lisätään luettelokontrollin InsertColumn()-funktiolla riveillä 7, 9 ja 11. Funktiolle syötetään sarakkeen numero, otsikko, muotoilulippu sekä sarakkeen haluttu oletusleveys. Kullekin sarakkeelle voidaan erikseen määrätä, tasataanko sarakkeen teksti vasempaan tai oikeaan reunaan vai keskitetäänkö se. Tätä varten käytetään lippuja LVFMT_LEFT, LVFMT_RIGHT ja LVFMT_CENTER. Kun sarakkeille on saatu otsikot, tarvitaan niihin myös tekstisisältöä. Sitä ennen joudut kuitenkin käsittelemään merkkijonoja rivien 24 37 mukaisesti. Näillä riveillä haetaan merkkijonoista pilkut ja pilkotaan niiden perusteella merkkijono kolmeen osaan, joissa kussakin on kyseisen sarakkeen tiedot: strname (alkuaine), strsymbol (kemiallinen merkki) ja stratomicnumber (atomiluku). Sarakkeen data asetetaan kullekin sarakkeelle näistä muuttujista. Huomaa, että ensimmäinen sarake lisätään yhä InsertColumn()-funktiolla rivillä 39, mutta seuraavat SetItemText()-funktiolla. SetItemText()- funktiolle syötetään parametreinä alkion paikka, sarake ja asetettava teksti. Lopuksi tarvitset vielä LVS_REPORT-tyyliä sarakeotsikoiden näyttämiseen. Tämä vaihto LVS_LIST-tyylistä uudeksi tehdään rivillä 54. Muutosten tekemisen jälkeen voit kääntää ja ajaa ohjelmasi, jolloin saat luetteloosi skaalattavat sarakkeet kuvan 19.3 tapaan.

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö OSA V LUKU 19 451 KUVA 19.3 List view näkymä ja sarakkeet. KATSO MYÖS List view näkymän muokkaaminen ajon aikana myöhemmin tässä luvussa. Valitun luettelon lukeminen List view luettelonäkymässä halutaan käyttäjän usein valitsevan yhden tai useamman luettelon alkioista. Voit käyttää GetNextItem()- funktiota hakemaan alkioita asetetun lipun perusteella. Ensimmäinen funktion parametreistä on indeksi, josta haku aloitetaan. Tässä voit valita aloituspaikaksi minkä tahansa luettelon riveistä tai 1 arvolla luettelon alun. Toinen parametri määrää, mitä alkioita luettelosta haetaan. Käytettävissä olevat liput on esitetty luettelossa 19.2. Kuten taulukosta huomaat, joukossa on myös suhteelliseen paikkaan viittaavia lippuja, kuten LVNI_TOLEFT. Näitä tarvitaan, koska seuraavan määrittely kuvakenäkymissä saattaa olla hankalaa. Tällä funktiolla voit hoitaa kaikki tällaiset tapaukset sekä tietenkin itse valittujen alkioiden hakemisen. LVNI_SELECTED-lippu ilmaisee, että funktion on haettava seuraava valittu arvo. Kun syötät GetNextItem()-funktiolle aloitusindeksiksi viimeisimmän löytyneen alkion paikan, saat haettua yksi kerrallaan hakukriteereihisi sopivat alkiot. Kun olet saanut alkion indeksin GetNextItem()-funktiolla, voit lukea alkion tekstin GetNextItem()-funktiolla. Funktio tarvitsee parametriksi pyydetyn tekstin indeksin ja sarakkeen ja palauttaa tekstin CString-muodossa.

452 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö TAULUKKO 19.2 GetNextItem()-funktion käyttämät liput Lippu LVNI_SELECTED LVNI_FOCUSED LVNI_ALL LVNI_ABOVE LVNI_BELOW LVNI_TOLEFT LVNI_ABOVE Kuvaus Alkio on valittu Alkion ympärillä on katkoviivalla esitetty valintasuorakulmio Oletuslippu, hakee vain seuraavan alkion Hae alkio annetun indeksin yläpuolelta Hae alkio annetun indeksin alapuolelta Hae alkio annetun indeksin vasemmalta puolen Hae alkio annetun indeksin oikealta puolen Voisimme kirjoittaa koodia, joka esittäisi näiden funktioiden avulla sovelluksen otsikkopalkissa luettelon valituista alkioista. Aluksi joudut tutkimaan, missä tämä luettelo päivitettäisiin. Paras hetki olisi käyttäjän napauttaessa luetteloa. Juuri tällöin valinta olisi todennäköisimmin muuttunut. Voit käsitellä luettelon napautuksen ilmoitussanoman ja tehdä ClassWizardilla käsittelijäfunktion rungon. Ilmoitussanoman käsittelijän lisääminen 1. Käynnistä ClassWizard näppäilemällä Ctrl+W. 2. Valitse Message Maps sivu ja varmista, että Class Name ruudussa on oikea luokka (kuten CListVView). Ellei ole, valitse se. 3. Varmista, että Object IDs luetteloruudussa on valittu CListVView. 4. Etsi nyt Messages-sanomaluettelosta =NM_CLICKED-sanoma. 5. Kaksoisnapauta =NM_CLICKED-sanomaa ja saat esiin Add Member Function ikkunan, jossa uuden jäsenfunktion nimenä on OnClick(). 6. Lisää uusi käsittelijäfunktio OK:lla. 7. Aloita koodin muokkaaminen Edit Code painikkeella. 8. Nyt sovelluksessa on OnClick()-funktio, jota kutsutaan aina käyttäjän napauttaessa List view näkymässä. Saat ohjelmasi hakemaan valitut rivit ja näyttämään ne otsikkopalkissa lisäämällä listauksen 19.6 rivit.

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö LISTAUS 19.6 LST19_6.CPP Valittujen alkioiden hakeminen GetNextItem()-funktiolla OSA V LUKU 19 453 1 void CListVView::OnClick(NMHDR* pnmhdr, LRESULT* presult) 2 { 3 // TODO: Add your control notification handler code here 4 5 *presult = 0; 6 7 // ** String to hold selected items 8 CString strselecteditems; 9 10 // ** Initial GetNextItem() index must be zero 11 int nselected=-1; 12 do 13 { 14 // ** Find the next selected item 15 nselected = GetListCtrl().GetNextItem( 16 nselected,lvni_selected); 1 17 18 // ** Is there a selected item 19 if (nselected!= -1) 20 { 21 // ** Add its text to the list 22 strselecteditems += " " + 23 GetListCtrl().GetItemText(nSelected,0); 2 24 } 25 } while(nselected!= -1); 26 27 // ** Set the document title to the selected items 28 GetDocument()->SetTitle( 29 "Selected:" + strselecteditems); 30 } 1 GetNextItem() hakee alkion määrätetyn ehdon perusteella. Tässä LVNI_SELECTED määrittää haettavaksi seuraavan valitun alkion. 2 Lisätään valitut alkiot valittujen luetteloon. Rivillä 8 määriteltyyn merkkijonoon strselecteditems talletetaan valitut alkiot. Huomaa rivillä 11 määritelty nselected-muuttuja, jonka alkuarvoksi asetetaan 1. Tämä arvo syötetään GetNextItem()- funktiolle indeksinä, josta haku aloitetaan (rivi 15). GetNextItem()- funktio saa myös LVNI_SELECTED-lipun, jolloin luettelosta haetaan ainoastaan valitut alkiot. Ensimmäisellä kerralla nselected saa siis arvon 1, joten GetNextItem()-funktio aloittaa List view -näkymän alusta. Jos luettelosta on valittu alkioita, seuraavan valitun alkion indeksi saadaan ja talletetaan nselected-muuttujaan. Rivillä 19 tarkistetaan vielä iflauseella, onko nselected-muuttuja yhä 1 (jos on, kaikki valitut alkiot on jo tutkittu). Jos valittuja alkioita on jäljellä, rivillä 23 kutsutaan GetItemText()-funktiota indeksin ja sarakkeen 0 arvolla. Tästä

454 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö paikasta löydetty teksti lisätään sitten (välilyönnin kera) strselecteditems-merkkijonossa olevaan tekstiin. Rivillä 25 while-lauseen perusteella koko do-silmukka toistetaan jos lisää valittuja alkioita löytyi. Muussa tapauksessa kaikki valitut alkiot on jo löydetty ja teksti voidaan kirjoittaa otsikkopalkkiin (rivi 28). Tehtyäsi muutokset ja käännettyäsi ja ajettuasi ohjelman, pitäisi valittujen alkioiden näkyä otsikkopalkissa kuvan 19.4 tapaan. KUVA 19.4 Valitut alkiot haetaan ja näytetään otsikkopalkissa. Puunäkymien luominen ja käyttö List view luettelonäkymä sopii mainiosti tavallisten luetteloiden esittämiseen. Toisinaan tarvitsee kuitenkin esittää myös tiedon hierarkia tällöin kannattaa käyttää Tree view puunäkymää. Tutuin esimerkki puunäkymästä lienee Resurssienhallinnan vasen ikkuna. Tässä näytetään levyn sisältö joukkona kansioita, joita avaamalla saadaan esiin lisää kansioita tai tiedostoja. KATSO MYÖS Puukontrollin käyttö valintaikkunassa luvussa 6. Useiden näkymien käyttö Resurssienhallinnan tapaan luvussa 20. Oletusfontin muuttaminen SetFont()-funktiolla luvussa 17.

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö Tree view sovelluksen luominen AppWizardilla Voit luoda AppWizardilla automaattisesti Tree view näkymää tukevan SDI-sovelluksen rungon. Vaiheet ovat miltei samat kuin List view näkymää luotaessa; tässä valitaan vain CTreeView näkymän kantaluokaksi CListView-luokan sijaan. Tarkemmat ohjeet löydät aiempaa tästä luvusta. Jos haluat seurata esimerkkejä tarkasti, anna projektin nimeksi TreeV. OSA V LUKU 19 455 Puunäkymän tyylien muuttaminen List view näkymien tavoin Tree view näkymilläkin on useita tyylilippuja. Tree view tyylit lisäävät List view näkymästä poiketen näkymään komponentteja. Nämä komponentit muodostavat viivoja lapsi- ja isäalkioiden välille ja näkyvät puun haaroja sulkevina ja avaavina painikkeina. Mukana on myös lippuja, jotka mahdollistavat vedä-ja-pudota toiminnan ja antavat mahdollisuuden alkioiden välittömään muokkaamiseen. Eri lippuja on esitetty taulukossa 19.3. TAULUKKO 19.3 Tree view näkymän tyyliliput Lippu TVS_HASLINES TVS_LINESATROOT TVS_HASBUTTONS TVS_SHOWSELALWAYS TVS_DISABLEDRAGDROP Kuvaus Piirtää viivan lapsialkion ja sen isäalkion välille Piirtää viivat yhdistämään juuritason alkiot Piirtää pienet painikkeet haaran laajentamiseksi tai sulkemiseksi Pitää valinnan, vaikka toinen ikkuna valittaisiin aktiiviseksi Estää alkioiden raahaamisen pois puusta Useimmiten puunäkymissä käytetään useaa näistä tyyleistä tutun Resurssienhallinnan kaltaisen puun näyttämiseksi. Aivan List view näkymän tavoin Tree view näkymänkin tyylejä muutetaan hakemalla vanhat arvot GetWindowLong()-funktiolla, muuttamalla bittejä ja kirjoittamalla asetukset takaisin ikkunaan SetWindowLong()- funktiolla. Listauksessa 19.7 asetetaan tyyleiksi TVS_HASLINES + TVS_HASBUTTONS + TVS_LINESATROOT riveillä 55 63. Puunäkymä saa siis viivat lasten ja isäalkion väliin, haaran laajentamis- ja sulkemispainikkeet sekä viivat juurialkioiden väliin. Puukontrollin koko rivin valitseminen Oletuksena puukontrollista näytetään valitusta alkiosta korostettuna ainoastaan tekstiosa. Koko rivi kuvat mukaanlukien voidaan korostaa asettamalla TVS_FULLROWSELECT-lippu. Huomaa, että tämän lipun käyttö sulkee pois TVS_HASLINESasetuksen ja päinvastoin.

456 Sovelluksen tietojen liittäminen puun alkioon Joskus on hyödyllistä liittää puun alkioihin olio-osoitin. Tämä tehdään funktioilla SetItemData() ja GetItemData(). Puun alkioiden tuhoaminen Puusta voidaan tuhota alkioita DeleteItem()-funktiolla; funktion parametrinä tarvitaan lisätyn alkion HTREEITEM-kahva. Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö Alkioiden lisääminen Tree view puunäkymää on parasta ajatella luettelona laajennettavia luetteloita. Kontrollin hakemiseen näkymästä on käytössä GetTreeCtrl()-saantifunktio. Kontrollin saatuasi voit kutsua sen InsertItem()-funktiota, jolla saat lisättyä puuhun alkion. InsertItem()-funktiosta on useita versioita, jotka käyttävät useita parametrejä. Yksinkertaisimmassa versiossa parametrejä on kolme: lisättävä teksti, uuden alkion isäalkion kahva sekä kahva asemaan, jonka jälkeen uusi alkio lisätään. Aivan välttämätön näistä on ainoastaan lisättävä teksti oletuksena isäalkio on puun juurialkio ja oletuspaikka luettelon loppu. Oletusarvoja käyttäessäsi saat kuitenkin vain luettelon, etkä pääse näin hyödyntämään puun ominaisuuksia. InsertItem()-funktio palauttaa lisätyn alkion kahvan, jota voit hyödyntää seuraavissa InsertItem()-kutsuissa lisättävän alkion isäalkiona tai alkiona, jonka perään uusi alkio lisätään. Puuta muodostettaessa ensimmäisen alkion isäalkioksi tulee määrittää TVI_ROOT eli puun juurialkio. Seuraaville lisättäville alkioille voidaan määrittää edellinen alkio isäalkioksi, jolloin puuhun muodostuu haara ja uudesta alkiosta tulee edellisen alkion lapsi. Kolmas parametri InsertItem()-funktiolle antaa mahdollisuuden muuttaa uusien sijoitettavien alkioiden järjestystä. Oletusarvo tälle on TVI_LAST eli luettelon loppu. Voit kuitenkin sijoittaa uuden alkion esimerkiksi jonkun aiemmin sijoitetun alkion jälkeen tai voit syöttää lipun TVI_SORT, jolloin alkio sijoitetaan aakkosjärjestyksessä paikalleen haaran sisällä. Nyt voit lisätä eri lippuja hyödyntävää koodia ja lisätä alkioita eri puolille puunäkymää (listaus 19.7). AppWizard on tehnyt projektiin valmiiksi OnInitialUpdate()-funktion, jossa voit lisätä alkiot Tree view näkymään juuri ennen sen näyttämistä. LISTAUS 19.7 LST19_7.CPP Alkioiden lisääminen Tree view puunäkymään 1 void CTreeVView::OnInitialUpdate() 2 { 3 CTreeView::OnInitialUpdate(); 4 5 // TODO: You may populate your TreeView with items by directly 6 // accessing its tree control through a call to GetTreeCtrl(). 7 8 // ** Declare a shortcut to the tree control 9 CTreeCtrl& tree = GetTreeCtrl(); 10

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö 11 // ** Insert a root level item 12 HTREEITEM hanimals = tree.insertitem("animals"); 13 14 // ** Insert a sub item, using the root item as a parent 15 HTREEITEM hverts = 16 tree.insertitem("vertibrates",hanimals); 17 18 // ** Insert sub items using,the hverts sub item as a parent 19 tree.insertitem("whales",hverts,tvi_sort); 20 tree.insertitem("dogs",hverts,tvi_sort); 21 tree.insertitem("humans",hverts,tvi_sort); 22 23 // ** Insert a sub item, using the root item as a parent 24 HTREEITEM hinverts = 25 tree.insertitem("invertibrates",hanimals); 26 27 // ** Insert sub items, hinverts sub item is parent 28 tree.insertitem("jellyfish",hinverts,tvi_sort); 29 tree.insertitem("worms",hinverts,tvi_sort); 30 tree.insertitem("snails",hinverts,tvi_sort); 31 32 // ** Insert a root level item after hanimals 33 HTREEITEM hplants = 34 tree.insertitem("plants",tvi_root,hanimals); 35 36 // ** Insert a sub item,root item is parent 37 HTREEITEM hfruit = 38 tree.insertitem("fruit",hplants); 39 40 // ** Insert sub items, hfruit sub item is parent 41 tree.insertitem("apples",hfruit,tvi_sort); 42 tree.insertitem("plums",hfruit,tvi_sort); 43 tree.insertitem("pears",hfruit,tvi_sort); 44 45 // ** Insert a sub item,root item is parent 46 HTREEITEM hcereal = 47 tree.insertitem("cereal",hplants); 48 49 // ** Insert sub items, hcereal sub item is parent 50 tree.insertitem("wheat",hcereal,tvi_sort); 51 tree.insertitem("rye",hcereal,tvi_sort); 52 tree.insertitem("rice",hcereal,tvi_sort); 53 54 // ** Get the current style flags 55 DWORD dwstyle = 56 GetWindowLong(GetTreeCtrl().GetSafeHwnd(), 57 GWL_STYLE); 58 59 // ** Add the List style 60 dwstyle = TVS_HASLINES + TVS_HASBUTTONS + TVS_LINESATROOT; 1 61 62 // ** Set it back into the list view OSA V LUKU 19 1 Tyyliliput asetetaan. 457

458 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö 63 SetWindowLong(GetTreeCtrl().GetSafeHwnd(), 64 GWL_STYLE,dwStyle); 65 66 // ** Redraw the list view 67 SetRedraw(TRUE); 68 } Listauksen 19.7 rivillä 9 määritellään tree-olio CTreeCtrl&- viittaukseksi. Tämä on lyhyempi tapa toimia kuin GetTreeCtrl()- funktion käyttö joka kerta näkymään upotettuun puukontrolliin viitattaessa. Rivillä 12 lisättävälle ensimmäiselle alkiolle tarvitaan ainoastaan yksi parametri InsertItem()-funktiolle, joka tässä on Animals. Toisena parametrinä käytetään oletusarvoa TVI_ROOT, onhan alkio tarkoitus sijoittaa puun juureen. Kolmaskin parametri kelpuutetaan oletusarvolla TVI_LAST, koska ensimmäiselle alkiolle järjestyksellä ei ole väliä. Rivillä 16 lisätty Vertibrates -alkio (selkärankaiset) määrittää isäalkioksi hanimals-kahvan eli siitä tulee nyt Animals -alkion lapsialkio. Riveillä 19 21 lisätään puuhun joukko selkärankaisten eläinten nimiä. Huomaa, että nämä käyttävät isäalkionaan hverts-kahvaa ja järjestysparametrinä TVI_SORT-lippua, jolloin alkiot järjestetään aakkosjärjestykseen. Riveillä 23 52 lisätään uusia alkioita, jolloin puuhun saadaan lisää haaroja ja syvyyttä. Välttämättömät (aiemmin mainitut) tyyliliput asetetaan riveillä 56 66. Kun käännät ja ajat sovelluksen muutosten tekemisen jälkeen, pitäisi sovelluksen näyttää kuvan 19.5 kaltainen Tree view ikkuna. Saatat joutua laajentamaan puun haaroja nähdäksesi kaikki alkiot.

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö OSA V LUKU 19 459 KUVA 19.5 Puunäkymä laajennettuna. Valitun solmun hakeminen Löydät Tree view puunäkymästä valitut alkiot (eli solmut) puukontrollin GetSelectedItem()-funktiolla, joka palauttaa valitun alkion HTREEITEM-kahvan. Vaihtoehtoisesti voit käyttää List view näkymän tapaan GetNextItem()-funktiota. Tree view näkymän versio käyttää kahta parametriä: ensimmäinen on HTREEITEM ja toinen lippuarvo, jolla määrätään, mihin rakenteisiin haku kohdistetaan. Nämä mahdolliset lippuarvot on esitetty taulukossa 19.4. GetNextItem()-funktio palauttaa lopuksi määrätyn alkion tai NULLkahvan, mikäli haluttua alkiota ei löydy. TAULUKKO 19.4 Tree view näkymän GetNextItem()-funktion liput Lippu TVGN_CARET TVGN_ROOT TVGN_PARENT TVGN_CHILD TVGN_NEXT TVGN_PREVIOUS TVGN_PREVIOUSVISIBLE TVGN_FIRSTVISIBLE Kuvaus Palauttaa valittuna olevan alkion Palauttaa annetun alkion juurialkion Palauttaa määrätyn alkion isäalkion Palauttaa ensimmäisen lapsialkion, ensimmäisen (alkion kahva) parametrin on oltava NULL Palauttaa seuraavan lapsialkion Palauttaa edellisen lapsialkion Palauttaa ensimmäisen näkyvän alkion ennen annettua alkiota Palauttaa ensimmäisen näkyvän alkion

460 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö Voit asettaa alkion myös ohjelmasta käsin SelectItem()-funktiolla syöttämällä kyseisen alkion HTREEITEM-kahvan funktion parametriksi. Saatuasi sitten alkion kahvan GetNextItem()- tai GetSelectedItem()-funktiolla, voit lukea alkion tekstin GetItemText()-funktiolla. Listauksessa 19.8 on esitetty valitun alkion hakeva ja sen tekstin esittävä koodi. List view näkymän tavoin TVN_SELCHANGED heijastetut ilmoitussanomat käsitellään näkymäluokan OnSelchanged()-funktiossa, jonka saat lisättyä ClassWizardin Message Maps sivulta. LISTAUS 19.8 LST19_8.CPP tekstin hakeminen valitusta alkiosta 1 void CTreeVView::OnSelchanged(NMHDR* pnmhdr, LRESULT* presult) 2 { 3 NM_TREEVIEW* pnmtreeview = (NM_TREEVIEW*)pNMHDR; 4 5 // ** Find the handle of the selected item 6 HTREEITEM hselected = 7 GetTreeCtrl().GetSelectedItem(); 8 9 // ** Ensure there is a selected handle 10 if (hselected >= 0) 11 { 12 // ** Get the text from the selected item 13 CString strselected = 14 GetTreeCtrl().GetItemText(hSelected); 15 16 // ** Set the title to the Windows' title bar 17 GetDocument()->SetTitle(strSelected); 18 } 19 20 *presult = 0; 21 } Valitun alkion kahva haetaan listauksessa 19.8 rivillä 6 GetSelectedItem()-funktiolla ja tämän oikeellisuus tarkistetaan rivillä 10. Jos kahva kelpaa, alkion teksti luetaan rivillä 14 GetItemText()-funktiolla ja se asetetaan dokumentin otsikoksi rivillä 17. Lisättyäsi listauksen koodin, käännettyäsi ohjelman ja ajettuasi sitä pitäisi valitun alkion nimen näkyä otsikkopalkissa.

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö OSA V LUKU 19 461 Näkymässä muokkaamisen käsittely Olet jo ehkä nähnyt sovelluksia, joissa puunäkymässä voidaan muokata tekstiä sitä napauttamalla ja tekemällä muutokset paikan päällä. Kyseessä on tekstin muokkaaminen paikallaan, inline editing. Voit ottaa tämän ominaisuuden käyttöön helposti määrittämällä Tree view näkymän tyylilipun TVS_EDITLABELS ja käsittelemällä pari ilmoitussanomaa. Sanomat ovat TVN_BEGINLABELEDIT ja TVN_ENDLABELEDIT, joille voit lisätä vastaavat sanomankäsittelijät OnBeginlabeledit() ja OnEndlabeledit() ClassWizardilla. Paikallaanmuokkaus luettelonäkymissä Saat luettelonäkymään samat paikallaaneditointiominaisuudet lisäämällä LVS_EDITLABELStyylin. Lisättyäsi Tree view näkymän tyyleihin TVS_EDITLABELS-lipun, käyttäjä voi aloittaa puunäkymän alkion muokkaamisen varovasti kaksoisnapauttamalla puun tekstialkiota. Tällöin kutsutaan OnBeginlabeledit()-käsittelijääsi; funktiosta voit kutsua GetEditControl()-funktiota muokataksesi puuhun upotettua tekstikontrollia sallimaan paikallaan muokkaamisen. Tekstiruudun osoittimella voit halutessasi muuttaa tekstin väriä tai rajoittaa tekstin enimmäispituuden. Käyttäjä voi sitten kirjoittaa haluamansa tekstin ja lopettaa muokkaamisen Enterillä tai tekstiruudun ulkopuolella napauttamalla. Tässä vaiheessa kutsutaan OnEndlabeledit()- käsittelijää. Joudut hakemaan tekstikontrollin vielä kerran GetEditControl()-funktiolla muokatun tekstin lukemiseksi. Voit tarkistaa, kelpaako teksti ja kirjoittaa sen mahdollisesti uudelleen puuhun. Ellei tekstiä kirjoiteta puuhun, tehdyt muutokset kumoutuvat ja teksti jää alkuperäiseen, muuttamattomaan muotoonsa. Teksti kirjoitetaan puuhun SetTextItem()-funktiolla. Voit lisätä puun tyyleihin TVS_EDITLABELS-lipun esimerkiksi näin (kts. listaus 19.7): dwstyle = TVS_HASLINES + TVS_HASBUTTONS + TVS_LINESATROOT + TVS_EDITLABELS; OnBeginlabeledit() ja OnEndlabeledit() funktioiden toteutus on esitetty listauksessa 19.9. Jos lisäät nämä käsittelijät ja käännät sekä ajat sovelluksesi, pääset muokkaamaan kaksoisnapautuksella puun alkioita suoraan puusta kuvan 19.6 tavoin. Paikallaanmuokkaamisen käynnistäminen Puunäkymässä paikallaanmuokkaamisen aloittaminen on hieman mutkikasta: joudut kaksoisnapauttamaan alkiota, mutta pitämään pienen tauon napautusten välillä.

462 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö LISTAUS 19.9 LST19_9.CPP - OnBeginlabeledit() ja OnEndlabeledit() käsittelijät puun alkion suoraan muokkaamiseen 1 Tekstiruudussa olevan tekstin koko rajataan. 2 Muutettu teksti asetetaan takaisin puun alkioon. 1 void CTreeVView::OnBeginlabeledit(NMHDR* pnmhdr, 2 LRESULT* presult) 3 { 4 TV_DISPINFO* ptvdispinfo = (TV_DISPINFO*)pNMHDR; 5 // TODO: Add your control notification handler code here 6 7 GetTreeCtrl().GetEditControl()->LimitText(20); 1 8 9 *presult = 0; 10 } 11 12 void CTreeVView::OnEndlabeledit(NMHDR* pnmhdr, LRESULT* presult) 13 { 14 TV_DISPINFO* ptvdispinfo = (TV_DISPINFO*)pNMHDR; 15 // TODO: Add your control notification handler code here 16 17 // ** Get the modified text from the edit control 18 CString strtext; 19 GetTreeCtrl().GetEditControl()-> 20 GetWindowText(strText); 21 22 // ** Might do some text validation here 23 24 // ** Check string isn't empty 25 if (strtext.getlength()>0) 26 { 27 // ** Get the selected item handle 28 HTREEITEM hselected = ptvdispinfo->item.hitem; 29 30 // ** Set the modified text 31 GetTreeCtrl().SetItemText(hSelected,strText); 2 32 } 33 34 *presult = 0; 35 } OnBeginlabeledit()-käsittelijä on varsin yksinkertainen: ainoa rivi, joka ei ole ClassWizardin tekemä, on rivi 7, jossa tekstikontrolliin syötettävän tekstin enimmäispituudeksi asetetaan 20 merkkiä. OnEndlabeledit()-funktio on edellistä monipuolisempi; riveillä 19 ja 20 haetaan tekstiruudun teksti. Kun luetussa merkkijonossa on merkkejä (tarkistetaan rivillä 25), valittu alkio saadaan käsittelijän saamasta TV_DISPINFO-tietorakenneosoittimesta. Tämän jälkeen valitun alkion kahvan avulla asetetaan muokattu teksti tekstiruudusta alkioon rivillä 31.

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö OSA V LUKU 19 463 KUVA 19.6 Suora alkion tekstin muokkaus Tree view näkymässä. Rich Edit näkymien luominen ja käyttö Rich Edit näkymän avulla saat luotua hyvinkin tehokkaita ja räätälöitäviä tekstikäyttöliittymiä käyttäjälle varsin vähäisellä ohjelmointiponnistelulla. Tässä näkymässä toimii OLE täysin, eli voit pudottaa tekstin sekaan kuvia, videoleikkeitä ja äänitallenteita. Ominaisuuksia on enemmän kuin tähän sopii, mutta toivottavasti saamme edes raapaistua pintaa asiassa. Rich Edit näkymien luominen Voit luoda AppWizardilla CRichEditView-pohjaisen näkymäluokan omaavan SDI-sovelluksen aivan Tree view ja List view näkymien luomisen tavoin. Muista taas vaihtaa näkymän kantaluokaksi AppWizardin viimeisessä ikkunassa CRichEditView. Esimerkkinä voimme luoda RichV-nimisen SDI-sovelluksen, jotta pääsemme tutkimaan Rich Edit näkymän ominaisuuksia. Napautettuasi AppWizardin Finish-painiketta valintaikkunassa pyydetään painamaan OK-painiketta, mikäli haluat projektiisi tuen OLE-säilöille (OLE container). Tätä ei kysytä, mikäli vastaat AppWizardin Step 3 vaiheessa What Compound Document Support Would You Like to Include? kysymykseen Container. Edit-näkymä On olemassa myös rich edit - näkymää yksinkertaisempi Editnäkymä, joka perustuu moniriviseen tekstiruutuun. Siinä ei ole kaikkia Rich Edit -näkymän muokkaus- ja OLE-ominaisuuksia, mutta se on hyvin sopva tilanteisiin, joissa ei tarvita Rich edit -näkymän tehoa. Tämä näkymä on CEditView ja se voidaan määritellä AppWizardin Finish-sivulla.

464 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö Nyt voit kääntää ja ajaa Rich Edit -näkymäsovelluksesi koodia muokkaamatta: saat silti käyttöösi edistykselliset tekstinmuokkausominaisuudet. KATSO MYÖS Ole-säilöt yksityiskohtaisemmin luvussa 25. Näkymän tekstin lataaminen ja tallentaminen Syötä nyt valikoimatonta tekstiä Rich Edit näkymäsovelluksessasi, napauta File-valikkoa ja valitse siitä Save-komento. Voit antaa haluamasi tiedostonimen ja tallentaa tekstin. Sulje sovellus ja avaa se uudelleen. Napauta uudelleen File-valikkoa ja valitse tällä kertaa Open-komento, hae tallentamasi tiedosto ja napauta OK. Huomaat, että editori jopa tallentaa ja hakee tekstisi ilman lisäkoodausta. Näkymässä ovat mukana myös tulostaminen (Print) ja tulostuksen esikatselu (Preview). Nämä toimivat, koska OLE-säilön ominaisuudet lisätään omiin asetuksiisi. Kun Rich Edit näkymä on aktiivinen, tiedostoasetukset tulevat näkymästä ja ne on toteutettu jo automaattisesti. KATSO MYÖS Lisätietoja tiedoston tallentamisesta ja lataamisesta luvusta 23. OLE-säilöjen yleiskatsaus luvussa 25. Kappaleen muotoileminen Huomaa, että Rich edit näkymässä ei tueta kappaleiden muotoilemista. Näkymä tarjoaa kyllä perustekstinkäsittelytoiminnot vakiona, mutta käyttöliittymä ja näiden toimintojen kutsuminen kuuluvat sovelluksen räätälöijälle. Voit määrittää käyttöliittymän muotoilemaan valitun kappaleen. Työkalurivin kolme uutta painiketta edustavat kappaleen tasaamista vasemmalle, oikealle ja sen keskittämistä. Lisää nämä painikkeet työkaluriviisi luvussa 14 annettujen ohjeiden avulla. Voit suunnitella näille tasaustoiminnoille myös omat kuvat painikkeisiin. Omat versioni näkyvät kuvassa 19.7. Näkymässä esitetty suuri bittikarttakuva (.bmp) on sen sijaan taiteellisemmalta tuttavaltani. Monipuolisen sisällön lisääminen tekstin sekaan käy siis helposti. Voit kokeilla esimerkiksi kuvan lisäämistä valitsemalla Editvalikosta Insert New Object komennon.

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö OSA V LUKU 19 465 KUVA 19.7 Rich edit näkymä toiminnassa. Lisättyäsi työkaluriviin kuvakkeet, anna niille ID-tunnukset ID_ALIGNLEFT, ID_ALIGNRIGHT ja ID_ALIGNCENTER. Voit sitten luoda komennonkäsittelijäfunktiot painikkeille CRichVView-luokkaan ClassWizardilla nimeltään OnAlignLeft(), OnAlignRight() ja OnAlignCenter(). Kappaleen muotoilukoodi on varsin yksinkertainen (kuten listaus 19.10 osoittaa). Rich Edit näkymä käyttää PARAFORMAT-tietorakennetta eri muotoilutoimintoihin. Maskijäsen dwmask asetetaan rivillä 6 määrättyyn toimintoon. Taulukossa 19.5 on lueteltu käytettävissä olevat toiminnot ja liput useimmat käsittelevät jollain lailla sisentämistä. Maskiliput esittävät käytössä olevia PARAFORMAT-tietorakenteen jäseniä. Näin voit asettaa kerralla joko yhden lipun (kuten esimerkissä) tai tarvittaessa useampia yhdistämällä.

466 Kehittyneet dokumentti/näkymä -tekniikat Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö TAULUKKO 19.5 PARAFORMAT-tietorakenteen dwmaskjäsenen arvot Lippu PFM_ALIGNMENT PFM_NUMBERING PFM_TABSTOPS PFM_OFFSET PFM_OFFSETINDENT PFM_RIGHTINDENT PFM_STARTINDENT Toiminto Valittu kappale tasataan vasempaan tai oikeaan reunaan tai keskitetään walignment-lipun mukaan Valittu kappale numeroidaan aloittaen wnumbering-arvosta. Sarkaimet asetetaan ctabstops-määrän ja rgxtabs-vektorin mukaan Rivejä sisennetään ensimmäisen rivin suhteen dxoffset-arvon verran Sisennetään dxstartoffset-arvon verran Sisennetään dxrightindent-arvon verran oikeasta reunasta Kaikkia muutettuja kappaleita sisennetään dxstartindent-arvon verran. LISTAUS 19.10 LST19_10.CPP Kappalemuotoilun toteutus Rich Edit näkymässä 1 Asetetaan kappaleen keskelle tasauksen liput 2 Asetetaan kappaleen vasemmalle tasauksen liput 3 Asetetaan kappaleen oikealle tasauksen liput 1 void CRichVView::OnAligncenter() 2 { 3 // TODO: Add your command -handler code here 4 5 PARAFORMAT pf; 6 pf.dwmask = PFM_ALIGNMENT; 7 pf.walignment = PFA_CENTER; 1 8 SetParaFormat(pf); 9 } 10 11 void CRichVView::OnAlignleft() 12 { 13 // TODO: Add your command -handler code here 14 15 PARAFORMAT pf; 16 pf.dwmask = PFM_ALIGNMENT; 17 pf.walignment = PFA_LEFT; 2 18 SetParaFormat(pf); 19 } 20 21 void CRichVView::OnAlignright()

Luettelo-, puu-, parannetun tekstiruutu- sekä HTML-näkymän käyttö 22 { 23 // TODO: Add your command -handler code here 24 25 PARAFORMAT pf; 26 pf.dwmask = PFM_ALIGNMENT; 27 pf.walignment = PFA_RIGHT; 3 28 SetParaFormat(pf); 29 } OSA V LUKU 19 467 Tässä asetetaan ainoastaan PF_ALIGNMENT-lippu ja vastaava tietorakenteen jäsenmuuttuja walignment riveillä 6 ja 7. Tämän jälkeen tietorakenne välitetään muotoilufunktiolle SetParaFormat(), joka muotoilee kappaleen dwmaskin edustamien tietorakenteeseen asetettujen arvojen mukaan (rivi 8). Huomaa, että OnAlignleft()- ja OnAlignright()-funktioiden toteutus on miltei identtinen OnAligncenter()-funktion kanssa ainoa ero on PFA_CENTER-lipun tilalle vaihdettu PFA_LEFT tai PFA_RIGHT-lippu. Käännettyäsi ja ajettuasi ohjelmaa muutosten tekemisen jälkeen pääset muotoilemaan kappaletta valitsemalla sen ja napauttamalla tämän jälkeen jotain kolmesta uudesta työkalurivin painikkeesta. OLE-objektien lisääminen Koska Rich Edit näkymä tukee OLE-objektien käyttöä näkymässä, voit lisätä siihen kuvia ja medialeikkeitä tavallisella valikon OLEkomennosta. Voit kokeilla tätä valitsemalla Edit-valikosta Insert New Object komennon. Tällöin saat esiin tutun Insert Object ikkunan. Ikkunassa on todennäköisesti hyvin monentyyppisiä objektityyppejä, joista minkä tahansa voit sijoittaa Rich Edit näkymään. KATSO MYÖS OLE- ja COM-yleiskatsaus luvussa 25.