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



Samankaltaiset tiedostot
Hiirisanomiin vastaaminen

UpdateIT 2010: Editorin käyttöohje

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

Ohjelmoinnin perusteet Y Python

Piirtopinnalle piirtäminen

Tulostaminen ja esikatselu

1. HARJOITUS harjoitus3_korjaus.doc

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

Usean näkymän luominen

Kynien ja siveltimien käyttö

Sisällysluettelo T A R R A O P A S

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

CSS-kielen avulla määritellään HTML-dokumentin tyyli. CSS avulla voidaan tarkemmin määritellä eri elementtien ominaisuuksia.

CSS - tyylit Seppo Räsänen

Planssit (layouts) ja printtaus

Harjoitustyö: virtuaalikone

ITKP102 Ohjelmointi 1 (6 op)

Opinnäytteen nimi ja mahdollinen alaotsikko (tämä pohja toimii parhaiten Word2010-versiolla)

1. ALKUSANAT TUNNUS VÄRIT MERKKI JA LOGOTYYPPI SUOJA-ALUE TUNNUKSEN KÄYTTÖ MONIVÄRI...

Fonttimuotoilut. Fontin tyyppi ja fonttikoko

Muita kuvankäsittelyohjelmia on mm. Paint Shop Pro, Photoshop Elements, Microsoft Office Picture Manager

Ohjelmoinnin peruskurssi Y1

Tämän värilaatuoppaan tarkoitus on selittää, miten tulostimen toimintoja voidaan käyttää väritulosteiden säätämiseen ja mukauttamiseen.

MDI-sovellusten kehittäminen

Muuttujien määrittely

TAULUKOINTI. Word Taulukot

Pong-peli, vaihe Koordinaatistosta. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 2/7. Tämän vaiheen aikana

TAULUKKO, KAAVIO, SMARTART-KUVIOT

Siirtyminen Outlook versioon

KÄYTTÖOHJE. Servia. S solutions

2. Aloitus -välilehti, leikepöytä- ja fontti -ryhmät

JAVA on ohjelmointikieli, mikä on kieliopiltaan hyvin samankaltainen, jopa identtinen mm. C++

Jypelin käyttöohjeet» Ruutukentän luominen

6. Harjoitusjakso II. Vinkkejä ja ohjeita

FrontPage Näkymät

Pong-peli, vaihe Aliohjelman tekeminen. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 3/7. Tämän vaiheen aikana

CSS. Tekstin muotoilua

Pong-peli, vaihe Aliohjelmakutsu laskureita varten. 2. Laskurin luominen. Muilla kielillä: English Suomi

valitsin on useimmiten html-elementti, jolle tyyli halutaan luoda

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

11. oppitunti III. Viittaukset. Osa. Mikä on viittaus?

Visual C++ -ohjelman tekeminen ja suunnittelu

Kylänetti projektin sivustojen käyttöohjeita Dokumentin versio 2.10 Historia : 1.0, 1.2, 1.6 Tero Liljamo / Deserthouse, päivitetty 25.8.

Racket ohjelmointia osa 2. Tiina Partanen Lielahden koulu 2014

KUVAN TUOMINEN, MUOKKAAMINEN, KOON MUUTTAMINEN JA TALLENTAMINEN PAINTISSA

Ohjelmoinnin perusteet Y Python

Taulukot. 1. Taulukon rakenne: ICT01D Elina Ulpovaara

Kyläsivujen InfoWeb-ohje

Ohjelmoinnin perusteet Y Python

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

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

Wordpad ohjelman - käyttöliittymä

AUTOCAD-TULOSTUSOHJE. Tällä ohjeella selitetään Autocadin mittakaavatulostuksen perusasiat (mallin mittayksikkönä millimetrit)

Tekstinkäsittelyn jatkokurssi

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

LOAD R1, =2 Sijoitetaan rekisteriin R1 arvo 2. LOAD R1, 100

Taulukot Päivi Vartiainen 1

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

Tapahtumapohjainen ohjelmointi. Juha Järvensivu 2007

TYYLIT. Word Tyylit

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

Kuvat. 1. Selaimien tunnistamat kuvatyypit

1 Funktiot, suurin (max), pienin (min) ja keskiarvo

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

KOTISIVUKONE ULKOASUEDITORI

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli

XNA grafiikka laajennus opas. Paavo Räisänen. Tämän oppaan lähdekoodit ovat ladattavissa näiden sivujen Ladattavat osiossa.

Osoitin ja viittaus C++:ssa

Ohjeita. Datan lukeminen

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

Luento 5. Timo Savola. 28. huhtikuuta 2006

Ohjeet Finna- julisteen PowerPoint- pohjan muokkaamiseen

Graafisen käyttöliittymän ohjelmointi

Google-dokumentit. Opetusteknologiakeskus Mediamylly

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

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

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

Tietueet. Tietueiden määrittely

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

HARJOITUKSIA ios-ohjelmointiin LIITTYEN

Kuva 1. GIMP:in uuden kuvan luominen. Voit säätää leveyttä ja korkeutta ja kokeilla muitakin vaihtoehtoja. Napsauta sitten "OK".

Java layoutit. Juha Järvensivu 2007

Harjoitus 3: Flash-komponenttiarkkitehtuuri ( )

T Olio-ohjelmointi Osa 5: Periytyminen ja polymorfismi Jukka Jauhiainen OAMK Tekniikan yksikkö 2010

Windowsin sanomanvälitys. Juha Järvensivu 2007

Toinen harjoitustyö. ASCII-grafiikkaa

Viivakoodin viiteopas

Sukupuu -ohjelma. Ossi Väre ( ) Joni Virtanen ( )

Alkuun HTML5 peliohjelmoinnissa

HTML-ohjeet. Sivun perusrakenne <HTML> <HEAD> <STYLE TYPE="text/css"> ...tänne tulee CSS-koodi eli sivun ulkonäkö määritykset...

Kun olet valmis tekemään tilauksen, rekisteröidy sovellukseen seuraavasti:

1. Taustatietoa näppäimistönkuuntelusta

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

Värijärjestelmät. Väritulostuksen esittely. Tulostaminen. Värien käyttäminen. Paperinkäsittely. Huolto. Vianmääritys. Ylläpito.

Listarakenne (ArrayList-luokka)

TIETOKONEEN ASETUKSILLA PARANNAT KÄYTETTÄVYYTTÄ

Kuvan pienentäminen Paint.NET-kuvankäsittelyohjelmalla

1 Yleistä Web-editorista Web-editori -dokumentin luominen Pikatoimintopainikkeet Tallenna... 3

Delegaatit ja tapahtumakäsittelijät

Transkriptio:

OSA IV 389 LUKU 17 17 LUKU Tekstin esittäminen värein ja tyylein sovelluksen viimeistelyyn

390 Grafiikan piirtäminen William Caxtonin keksittyä painetun sanomalehden olemme olleet pääsemättömissä painotuotteista. Alkuaan lehtipainoihin suunnitellut fontit, kirjasimet, ovat monipuolistuneet ja tapaamme niitä mitä erilaisimpina ympäriltämme. Oikeiden fonttien valinta on sovelluksesi ulkoasun kannalta merkittävä päätös. Windows tukee täysin tekstin esittämistä eri fontein ja tyylein. Tekstinpiirtofunktiot Windowsin GDI-järjestelmän keskeisiä tavoitteita on ollut alusta pitäen tukea erilaisia korkeatasoisia graafisia laitteita. WYSIWYG (what you see is what you get) oli 80-luvun taikasana nyt sitä pidetään jo itsestäänselvyytenä. Yhdennäköisen tekstin piirtäminen erilaisille näytöille ja tulostimille onkin ollut vaativa tehtävä ohjelmistosuunnittelijoille. Onneksi siinä on onnistuttu ja laajan fonttivalikoiman sekä tehokkaiden tekstintulostusfunktioiden avulla voit esittää tekstisi luottaen sen tarkkaan esittämiseen eri laitteilla. KATSO MYÖS Lisätietoa piirtopinnoista luvun 15 alussa. Laitteen ominaisuuksien lukeminen luvussa 15. Muita TextOut()-funktioita TextOut():in kaltaisia funktioita on muitakin. TabbedTextOut() osaa tulikita sarkainmerkit sille syötetyn sijaintiluettelon mukaan. PolyTextOut() näyttää monta merkkijonoa taulukosta yhdellä funktiokutsulla. ExtTextOut()- funktiolle voidaan määrittää mutkikkaampia piirtoasetuksia tekstin ulkoasua varten. Yksinkertainen tekstitulostus Piirtopinnan TextOut()-funktio on kenties nopein ja helpoin tapa tekstin piirtämiseen. Funktiolle annetaan x- ja y-koordinaatit paikan asettamiseksi sekä esitettävä teksti CString-oliona. SDI-sovellus muodostaa hyvän tyhjän piirtoalustan. Tee siis AppWizardilla SDI-sovellus hyväksyen kaikki oletusasetukset (kuten teimme luvussa 12). Tällä SDI-sovelluksella voimme kokeilla eri tekstifunktioita. Valitse projektin työtilaikkunassa (workspace) ClassView-sivu. Löydät luettelosta varmasti myös CSimpTextView-luokan. Napauta plusmerkkiä nähdäksesi kaikki projektin luokat ja jäsenfunktiot. Kaksoisnapauta OnDraw()-funktiota ja lisää funktioon listauksen 17.1 koodi oletustoteutukseen. Näillä riveillä piirretään yksinkertainen tekstirivi.

LISTAUS 17.1 LST17_1.CPP Tekstin piirtäminen TextOut()- funktiolla OSA IV LUKU 17 391 1 void CSimpTextView::OnDraw(CDC* pdc) 2 { 3 CSimpTextDoc* pdoc = GetDocument(); 4 ASSERT_VALID(pDoc); 5 6 // TODO: add draw code for native data here 7 8 CString strtext = "Water under the bridge."; 9 pdc->textout(100,100,strtext); 1 10 } 1 TextOut() piirtää merkkijonomuuttujan tekstin paikkaan 100 pistettä vasemmalta ja 100 yläreunasta. Listauksessa 17.1 teksti sijoitetaan strtext-merkkijonoon ja syötetään TextOut()-funktiolle näyttämistä varten. TextOut()-funktiolle tulee myös antaa tulostettavan tekstin paikka, joka tässä on rivillä 9 annettu (100,100). Käännettyäsi ohjelman muutosten tekemisen jälkeen ja ajaessasi sen näet ikkunassa oletusfontilla ja värillä (musta teksti valkealla pohjalla) tulostetun tekstin lähellä ikkunan vasenta yläkulmaa. Tekstin tasauksen asettaminen Saat tasattua (align) tulostettavan merkkijonon usealla eri tavalla SetTextAlign()-funktiolla. Tälle piirtopinnan funktiolle voidaan syöttää useita erilaisia lippuja oletustasauksen ja tekstin piirtämisen jälkeisen piirto-osoittimen paikan asettamiseksi. Syötettävät liput viittaavat siihen, miten annettu piste sijoittuu tulostettavaan tekstiin nähden tämä saattaa kuulostaa aluksi hieman sekavalta. TA_RIGHT lipun saattaisi kuvitella sijoittavan tekstin pisteen oikealle puolen, mutta itse asiassa syötetty piste sijoittuu tekstin oikealle puolen eli teksti pisteen vasemmalle puolen. Taulukossa 17.1 esitetään SetTextAlign()-funktiolle syötettävät liput. TAULUKKO 17.1 SetTextAlign()-funktion käyttämät tekstin sijoitteluliput Käytössä olevien tekstintasausasetusten selvittäminen Piirtopinnan tekstintasausasetukset saadaan selville GetTextAlign()-funktiolla. Paluuarvo koostuu samoista lipuista kuin jotka voidaan syöttää tasausasetuksina SetTextAlign()- funktiolle. Lippu TA_LEFT TA_RIGHT TA_CENTER TA_TOP Vaikutus tekstiin Teksti sijoitetaan pisteen oikealle puolen Teksti sijoitetaan pisteen vasemmalle puolen Teksti keskitetään pisteen suhteen Teksti sijoitetaan pisteen alle

392 Grafiikan piirtäminen Lippu TA_BOTTOM TA_BASELINE TA_UPDATECP TA_NOUPDATECP Vaikutus tekstiin Teksti sijoitetaan pisteen yläpuolelle Tekstin alareuna on pisteen tasalla Piirto-osoittimen paikka päivitetään jokaisen TextOut()-kutsun jälkeen, annetut koordinaatit hylätään ja uusi teksti piirretään entisen perään. Piirto-osoitinta ei päivitetä jokaisen TextOut()- kutsun jälkeen. Saamme tekstin tasauksen vaikutuksen esiin piirtämällä ristin paikkaan (200,200) ja valitsemalla eri arvoja tekstin tasauslipuksi. Kokeilemme näitä nyt muuttamalla OnDraw()-funktion koodin listauksen 17.2 mukaiseksi. LISTAUS 17.2 LST17_2.CPP Tekstin tasauksen asettaminen 1 void CSimpTextView::OnDraw(CDC* pdc) 2 { 3 CSimpTextDoc* pdoc = GetDocument(); 4 ASSERT_VALID(pDoc); 5 // TODO: add draw code for native data here 1 Teksti tasataan oletuksena oikealla, mutta tässä asetus on mukana selkeyden vuoksi. 2 Voit yhdistellä tarvittavia lippuja. Tässä teksti keskitetään ja sijoitetaan annetun sijainnin päälle. 6 // ** Align point to the right of the text 7 pdc->settextalign(ta_right); 1 8 9 // ** Draw the Text 10 pdc->textout(200,200,"<-right->"); 11 12 // ** Align point to the left of the text 13 pdc->settextalign(ta_left); 14 pdc->textout(200,200,"<-left->"); 15 16 // ** Align point to the center and below the text 17 pdc->settextalign(ta_center + TA_BOTTOM); 2 18 pdc->textout(200,200,"<-left->"); 19 20 pdc->moveto(150,200); // ** Move 21 pdc->lineto(250,200); // ** Draw horizontal line 22 pdc->moveto(200,150); // ** Move 23 pdc->lineto(200,250); // ** Draw vertical line 24 25 }

Jokainen TextOut()-kutsu sijoitetaan samoihin koordinaatteihin, mutta tasausta muutetaan joka kerta, jotta saisimme tekstin ristillä merkityn pisteen eri puolille. Käännettyäsi ohjelman muutosten tekemisen jälkeen sen pitäisi näyttää kuvan 17.1 mukaiselta. OSA IV LUKU 17 393 KUVA 17.1 Erilaisia tekstin tasausasetuksia. KATSO MYÖS Yksityiskohtia viivojen ja muotojen piirtämisestä luvusta 16. Merkin ja taustan värin muuttaminen Tekstin oletusvärit ovat musta ja valkoinen, mutta voit muuttaa näitä SetTextColor()- ja SetBkColor()-funktioilla. Molemmille riittää syötteenä yksi parametri, halutun tekstin tai taustan värin tunnus (COLORREF). Funktiot myös palauttavan edellisen käytössä olleen värin väritunnuksena. Saat lisättyä OnDraw()-toteutuksen värien käytön lisäämällä SetTextColor()- ja SetBkColor()-funktiokutsut ennen TextOut()- funktiota. Tämä on esitetty listauksessa 17.3. Mikä teksti- ja taustaväri on käytössä? Saat selville käytössä olevan tekstin värin GetTextColor() ja taustan värin GetBkColor()- funktiolla. Molemmat palauttavat värin COLORREF-arvona.

394 Grafiikan piirtäminen LISTAUS 17.3 LST17_3.CPP Tekstin värin asettaminen SetTextColor()- ja SetBkColor()-funktioilla 1 Tällä rivillä asetetaan piirrettävän tekstin edustaväri. 2 Tällä rivillä asetetaan piirrettävän tekstin taustaväri. 1 // ** Set the Foreground to Blue 2 pdc->settextcolor(rgb(0,0,255)); 3 pdc->textout(200,200,"<-right->"); 4 5 pdc->settextalign(ta_left); 6 7 // ** Set the Foreground to Red 8 pdc->settextcolor(rgb(255,0,0)); 1 9 pdc->textout(200,200,"<-left->"); 10 11 // Align point to the center and below the text 12 pdc->settextalign(ta_center + TA_BOTTOM); 13 14 // ** Set the Foreground to Yellow 15 pdc->settextcolor(rgb(255,255,0)); 16 17 // ** Set the Background to Dark Blue 18 pdc->setbkcolor(rgb(0,0,128)); 2 19 pdc->textout(200,200,"<-left->"); Listauksessa 17.3 rivin 2 SetTextColor() muuttaa tekstin siniseksi, rivillä 8 punaiseksi ja rivillä 15 keltaiseksi. Rivillä 18 tausta asetetaan tummansiniseksi. Käännettyäsi ohjelman muutosten tekemisen jälkeen ja ajaessasi sen näet aiemman tekstin värikkäänä - myös tausta on värikäs. KATSO MYÖS Lisätietoja väritunnuksista ja RGB-makrosta luvun 16 alusta. Läpinäkyvän ja näkymättömän tekstin piirtäminen Toisinaan saattaa sovelluksessa olla tarvetta esittää teksti selvästi alla olevan alueen päällä. Joskus taasen tekstin on suotavaa sulautua alla olevaan piirrokseen. Voit valita tekstin esittämisen näiden tapojen välillä SetBkMode()-funktiolla. Sille syötetään yksi lippuparametri, joka on oletuksena OPAQUE, toinen vaihtoehto on TRANSPARENT (läpinäkyvä). Jos kutsut SetBkMode()-funktiota OPAQUE-lipulla, teksti esitetään sekä merkin että merkin taustaväriä käyttäen. TRANSPARENTlipun syöttämällä käytetään piirrettäessä ainoastaan tekstin väriä. Voit muuttaa OnDraw()-funktiosi listauksen 17.4 mukaiseksi, jotta saisit esimerkin läpinäkyvästä ja näkymättömästä piirtotilasta.

LISTAUS 17.4 LST17_4.CPP Läpinäkyvän ja näkymättömän tekstin piirtotilan asettaminen OSA IV LUKU 17 395 1 void CSimpTextView::OnDraw(CDC* pdc) 2 { 3 CSimpTextDoc* pdoc = GetDocument(); 4 ASSERT_VALID(pDoc); 5 6 // TODO: add draw code for native data here 7 8 pdc->ellipse(160,160,240,240); 9 pdc->settextalign(ta_center); 10 11 // ** Set Transparent Mode 12 pdc->setbkmode(transparent); 13 14 // ** Display some Text 15 pdc->textout(200, 180, "Transparent"); 1 16 17 // ** Set Opaque Mode 18 pdc->setbkmode(opaque); 2 19 20 // ** Display some Text 21 pdc->textout(200, 220, "Opaque"); 22 } 1 Läpinäkyvässä tilassa ympyrä näkyy tekstin alta. 2 Läpinäkymättömässä tilassa teksti piirretään taustavärin kanssa, jolloin ympyrä jää piiloon. Listauksessa 17.4 rivin 12 jälkeen esitettävä tekstin tausta on läpinäkyvä. Tausta asetetaan värilliseksi vasta rivillä 18. Käännettyäsi ohjelman muutosten tekemisen jälkeen ja ajaessasi sen näet, että teksti Opaque peittää osittain ellipsin. Tekstin Transparent alta se kuitenkin näkyy. Vaikka taustaväri olisi asetettu, sitä ei piirretä TRANSPARENT-tilassa. Tekstin rajaaminen suorakulmioon Usein halutaan rajata (clip) esitettävä teksti tietyn suorakulmaisen alueen sisään. Tämä sallitaan yleensä mieluummin kuin annetaan pitkän tekstin sotkea koko kuvio. ExtTextOut()-funktio on TextOut():in kehittyneempi muoto. Saat rajattua tekstisi syöttämällä funktiolle ETO_CLIPPED lipun. Ensimmäisinä parametreinä ExtTextOut()-funktiolle syötetään TextOut():in tapaan sijoituspaikan koordinaatit. Kolmantena parametrinä käytetään lippua, joka voi olla joko ETO_CLIPPED tekstiä rajattaessa tai ETO_OPAQUE, mikäli tavallinen teksti asetettuna halutaan Käytä ExtTextOut()-funktion TA_UPDATECP-lippua Voit käyttää SetTextAlign()- funktion lippua TA_UPDATECP funktion ExtTextOut() kanssa. Kun tämä lippu on asetettu, ensimmäinen TextOut() tai ExtTextOut()-funktio toimii normaalisti, mutta seuraavat eivät huomioi annettuja koordinaatteja, vaan esittävät tekstin sen hetkisessä piirto-osoittimen paikassa.

396 Grafiikan piirtäminen näyttää läpinäkyvällä taustalla esitettävää tekstiä. Liput voidaan myös yhdistää, jolloin saadaan rajattua läpinäkyvää tekstiä. Ellet halua kumpaakaan ominaisuutta käytettävän, voit syöttää kolmantena parametrinä myös nollan (kuten listauksen 17.5 rivillä 13). Neljäntenä parametrinä annetaan suorakulmio CRect-muodossa tätä käytetään tekstin rajaamiseen, mikäli ETO_CLIPPED-lippua on käytetty. Tulostettava teksti tulee viidennessä parametrissä (CString-oliona) ja kuudentena annetaan vektorina merkkien halutut välimatkat tai NULL oletusvälejä käytettäessä. Saat sovellukseesi tekstin rajauksen muutamalla OnDraw()-funktiosi listauksen 17.5 mukaiseksi. LISTAUS 17.5 LST17_5.CPP Tekstin rajaaminen ExtTextOut()- funktiolla 1 ExtTextOut()-funktio rajaa tekstin annettuun alueeseen ETO_CLIPPED-lipulla. 1 void CSimpTextView::OnDraw(CDC* pdc) 2 { 3 CSimpTextDoc* pdoc = GetDocument(); 4 ASSERT_VALID(pDoc); 5 6 // TODO: add draw code for native data here 7 8 CRect rcclipbox(cpoint(100,100),cpoint(250,120)); 9 pdc->rectangle(rcclipbox); 10 pdc->setbkmode(transparent); 11 12 // ** Draw the unclipped text 13 pdc->exttextout(100,100,0,rcclipbox, 14 _T("This text won't fit in there!"),null); 15 16 rcclipbox.offsetrect(0,40); 17 pdc->rectangle(rcclipbox); 18 19 // ** Draw the clipped text 20 pdc->exttextout(100,140,eto_clipped,rcclipbox, 21 "This text won't fit in there!",null); 1 22 } Listauksessa 17.5 määritellään suorakulmio rivillä 8. Tätä käytetään tekstin paikan asettamiseen ja sen rajaamiseen. Rivin 13 ExtTextOut()-funktiota kutsutaan ilman ETO_CLIPPED-lippua, joten teksti valuu suorakulmion ulkopuolelle. Rivillä 20 ExtTextOut():illa puolestaan rajataan teksti, joten suorakulmion ulkopuolista tekstiä ei näytetä.

Käännettyäsi ohjelman listauksen 17.5 muutosten tekemisen jälkeen ja ajaessasi sen näet kaksi suorakulmiota, joista toisesta teksti valuu ulos, mutta toisessa se rajataan. OSA IV LUKU 17 397 KATSO MYÖS Yksityiskohtia piirtämisestä ja rajaamisesta luvusta 15. Erilaisten fonttien luominen Tähän mennessä olet näyttänyt tekstiä piirtopinnan oletusfonttia käyttäen. Siveltimien ja kynien tapaan myös fontteja edustavat GDIobjektit ja niitä voidaan valita piirtopinnalle ja poistaa sieltä. Voit luoda ja räätälöidä fontteja tarpeen mukaan Windowsin GDI-funktioilla ja vastaavilla MFC-luokkien metodeilla. CFont-luokan käyttö MFC:n CFont-luokka piilottaa sisäänsä GDI-fonttiobjektin. Muiden MFC:n paketointiluokkien tavoin CFont-luokkaa ei voi noin vain muodostaa oletusarvoin ja käyttää. Tämän sijaan on aina määriteltävä ensin CFont-olio ja sen jälkeen käytettävä Create-funktiota sopivin parametrein. Create-funktiot eivät aina takaa pyydettyä fonttia. Tämän sijaan fonttienhakuohjelma käsittelee pyyntösi ja yrittää löytää mahdollisimman samanlaisen fontin ja räätälöi sen vielä pyytämäsi kaltaiseksi (ja tekee sen yleensä tyydyttävästi). Fonttien luominen CreatePointFont()-funktiolla CreatePointFont()-funktion käyttö on helpoin tapa fontin luomiseen. Sille syötetään kolme parametriä: fontin koko pisteen kymmenyksinä, fontin nimi (esimerkiksi Arial) ja lopuksi piirtopinta, jossa fonttia käytetään. Muuta nyt OnDraw()-funktiosi käyttämään CreatePointFont()-funktiota listauksen 17.6 mukaisesti suurella Arial-fontilla piirtämiseen.

398 Grafiikan piirtäminen LISTAUS 17.6 LST17_6.CPP - Fonttien luominen CreatePointFont()-funktiolla 1 CreatePointFont() on nopea ja helppo tapa luoda annetun tyylinen ja kokoinen fontti. 1 void CSimpTextView::OnDraw(CDC* pdc) 2 { 3 CSimpTextDoc* pdoc = GetDocument(); 4 ASSERT_VALID(pDoc); 5 6 // TODO: add draw code for native data here 7 8 // ** Create a 36 point Arial font 9 CFont fnbig; 10 fnbig.createpointfont(360,"arial",pdc); 1 11 12 CFont* poldfont = pdc->selectobject(&fnbig); 13 14 pdc->textout(50,50,"** 36 Pt Arial Font **"); 15 16 pdc->selectobject(poldfont); 17 } Huomaa, että rivillä 10 syötetään CreatePointFont()-funktiolle 360. Tässä fontin pistekoko annetaan kymmenesosapisteinä. Näin saat enemmän valinnan varaa fontin kokoon. Käännettyäsi ohjelman muutosten tekemisen jälkeen ja ajaessasi sen näet rivillä 14 esitetyn tekstin suurella (36 pt) Arial-fontilla. Fonttien luominen CreateFont()-funktiolla CreateFont() lienee MFC:n mutkikkaimpia funktioita: se vaatii 14 parametriä, joissa on vielä useita lippuyhdistelmiä. Oli miten oli, kaikkia fontin asetuksia ei saa millään kierrettyä, joten parametrien kanssa on vain selvittävä. CreateFont()-funktion prototyyppi on esitetty listauksessa 17.7. LISTAUS 17.7 LST17_7.CPP CreateFont()-funktion parametrit 1 BOOL CreateFont( int nheight, int nwidth, 2 int nescapement, int norientation, int nweight, 3 BYTE bitalic, BYTE bunderline, BYTE cstrikeout, 4 BYTE ncharset, BYTE noutprecision, 5 BYTE nclipprecision, BYTE nquality, 6 BYTE npitchandfamily, LPCTSTR lpszfacename );

OSA IV LUKU 17 399 Fontin korkeuden ja leveyden asettaminen CreateFont()-funktion kaksi ensimmäistä parametriä liittyvät halutun fontin korkeuteen ja leveyteen. Ensimmäinen parametri nheight voi olla positiivinen tai negatiivinen. Positiivisia arvoja verrataan saatavilla olevien fonttien solun kokoon ja parhaiten täsmäävä valitaan. Negatiivisia arvoja puolestaan verrataan käytettävissä olevien fonttien merkin kokoon. Korkeuden sovitussäännöt Fonttien korkeutta sovitettaessa valitaan suurin annettua korkeutta pienempi fontti. Solu (cell) tarkoittaa merkkiä sekä siihen liittyvää merkin ylä- ja alapuolelle varattua tilaa. Puhuttaessa pelkän merkin koosta näitä välejä ei huomioida. Parametrin arvolla 0 valitaan sopiva (toivottavasti) oletusarvo. nwidth-parametri määrittää halutun keskileveyden (suhteellisin välein esitettävissä fonteissa on leveitä ja kapeita merkkejä). Jos käytät tässä arvoa nolla, käytetään hyvää korkeuteen ja sivusuhteeseen perustuvaa oletusleveyttä. Fontin kallistuksen ja suunnan asettaminen Kallistus (escapement) ja suunta (orientation) viittaavat koko tekstin kallistukseen (joka tavallisesti on vaakasuunnassa) ja yksittäisten merkkien kallistukseen. nescapement-parametrillä voidaan piirtää kallistettua tekstiä määrittämällä tekstin suunnan eron x-akseliin nähden asteen kymmenesosina. Arvolla 900 saat pystysuuntaista tekstiä. norientation-parametri kertoo yksittäisen merkin perusviivan ja x-akselin välisen kulman, myös asteen kymmenyksinä. Lihavointi, kursivointi, alle- ja yliviivaus Seuraavat neljä parametriä liittyvät merkin paksuuteen sekä erilaisiin korostuksiin, kuten kursivointi, alleviivaus ja yliviivaus. nweight-parametrillä voit muuttaa merkkien paksuutta arvojen 0 (ohut) ja 1000 (paksu) välillä. Taulukossa 17.2 on esitetty käytön helpottamiseksi määriteltyjä valmiita arvoja.

400 Grafiikan piirtäminen TAULUKKO 17.2 Fontin paksuusliput Lippu nweight-arvo FW_DONTCARE 0 FW_THIN 100 FW_EXTRALIGHT 200 FW_LIGHT 300 FW_NORMAL 400 FW_MEDIUM 500 FW_SEMIBOLD 600 FW_TBOLD 700 FW_EXTRABOLD 800 FW_HEAVY 900 bitalic-parametri esittää fontin kursivoituna, mikäli arvo on TRUE. bunderline-parametri esittää fontin alleviivattuna, mikäli arvo on TRUE. bstrikeout-parametri esittää fontin yliviivattuna, mikäli arvo on TRUE. Fontin laadun ja tarkkuuden asettaminen Laatu- ja tarkkuusparametreillä voit vaikuttaa siihen, kuinka fontti valitaan ja piirretään kohdelaitteella. Voit myös valita tyylin, kuten kiinteän tai suhteellisen välistyksen sekä kertoa, milloin serif-fontteja toivotaan. ncharset-parametrillä voit määritellä käytettävän merkistön. Tavallisesti tämä on ANSI_CHARSET normaaleja ANSI-merkkejä varten. Joskus saatat tarvita kuvamerkkejä, jolloin tähän valitaan SYMBOL_CHARSET. noutprecision-parametrillä määritellään, kuinka fontin sovitinfunktio valitsee tietyn fontin toisen sijaan. Tavallisesti tämä on OUT_DEFAULT_PRECIS, mutta vaatiessasi välttämättä TrueType-fonttia saatat antaa parametriksi OUT_TT_PRECIS. Parametrillä nclipprecision voit määrittää

OSA IV LUKU 17 401 rajaamistarkkuuden. Tavallisesti käytetään arvoa CLIP_DEFAULT_PRECIS. Fontin ominaisuuksien ja esitysasun painoarvoon voidaan vaikuttaa nquality-parametrillä. Se voi saada arvoja DEFAULT_QUALITY, DRAFT_QUALITY tai PROOF_QUALITY. npitchandfamily-parametrillä saat asetettua kaksi ominaisuutta kerralla. Tämän takia saatat saada kääntäjältä virheilmoituksen kahden parametrin käytöstä yhden sijaan, kun kääntäjä ilmoittaa, ettei CreateFont() käytä 15 parametriä. Tarkista tällaisen virheilmoituksen saatuasi, että nämä arvot on yhdistetty (+ tai -merkillä) eikä erotettu pilkulla. Käytettävissä olevat fontin leveyden tyylit (pitch) on esitetty taulukossa 17.3. TAULUKKO 17.3 Pitch-asetukset Vaihtoehtoiset rajaustarkkuusliput nclipprecision-liput muuttavat tapaa, jolla fontti rajataan sen joutuessa rajausalueen ulkopuolelle. Muita mahdollisia arvoja ovat CLIP_EMBEDDED (vain upotetuille kirjoitussuojatuille fonteille) ja CLIP_LH_ANGLES (voidaan käyttää, jos fontin kallistus on muuttunut). Vanhassa koodissa saatetaan käyttää muitakin lippuja, mutta useimpia niistä ei enää käytetä ja ne voidaan jättää huomiotta. Lippu DEFAULT_PITCH VARIABLE_PITCH FIXED_PITCH Kuvaus Kuten fontilla tavallisesti käytetään Ainoastaan vaihtelevalevyinen fontti Kiinteävälinen fontti, esimerkiksi pääteemulaattoreita varten. Voit yhdistää taulukon 17.3 pitch-liput taulukossa 17.4 esitetyn fonttiperheen kanssa npitchandfamily-parametriin. Esimerkiksi DEFAULT_PITCH FF_SCRIPT asettaa käsinkirjoitusfontin oletusleveyksin. TAULUKKO 17.4 Fonttiperheasetukset Lippu Kuvaus FF_DECORATIVE Erikoisfontit, kuten vanhanaikaisessa tekstissä. FF_DONTCARE Fontista ei ole tietia tai väliä FF_MODERN Kiinteävälinen tai levyinen FF_ROMAN Suhteellinen välistys ja vaihteleva leveys FF_SCRIPT Käsialatyylit FF_SWISS Suhteellinen välistys ilman serif-viivoja TMPF_TRUETYPE TrueType-versio vaaditaan TrueType-fonttien käyttö Voit yhdistää fonttiperhelippuun lipun TMPF_TRUETYPE halutessasi käyttöön annetun fonttiperheen TrueType-fontin.

402 Grafiikan piirtäminen True Type fontit piirretään kaarien ja piirtovihjeiden avulla. Piirtotavasta johtuen ne skaalautuvat paljon kiinteitä fontteja paremmin suuriin kokoihin. Määrätyn fontin nimen asettaminen Voit määrittää asennetun fontin nimen perusteella lpszfacenameparametrinä, esimerkiksi Times New Roman. Fontin luominen CreateFont()-funktiolla Voit kokeilla fontinluontiesimerkkiä, jossa myös muutetaan fontin asetuksia. Tätä varten joudut tekemään listauksessa 17.8 esitetyt muutokset OnDraw()-funktioosi. Listauksen esittämä koodi näyttää tekstirivin, joka pyörii keskipisteensä ympäri muuttamalla suuntaansa 360 astetta. LISTAUS 17.8 LST17_8.CPP Fonttien luominen CreateFont()- funktiolla 1 CreateFont()-funktio sallii fonttisovittimen valita ja luoda tarkkaan määritetyn fontin, mutta sen käyttö voi lukuisien parametrien vuoksi olla vaikeaa. 1 void CSimpTextView::OnDraw(CDC* pdc) 2 { 3 CSimpTextDoc* pdoc = GetDocument(); 4 ASSERT_VALID(pDoc); 5 6 // TODO: add draw code for native data here 7 8 // ** Declare a CRect to hold the client rect 9 CRect rcclient; 10 GetClientRect(&rcClient); 11 12 // ** Find the mid point 13 CPoint ptcentre = rcclient.centerpoint(); 14 pdc->setbkmode(transparent); 15 16 // ** Loop through 360 degrees 17 for(int i=0 ; i <360 ; i+=18) 18 { 19 CFont fnbig; 20 // ** 30 high, default width 1 21 fnbig.createfont(30,0, 22 // ** Change Orientation 23 i*10,i*10, 24 // ** Increase the weight 25 i/4, 26 FALSE, 27 TRUE, //** Underlined 28 FALSE, 29 ANSI_CHARSET, 30 OUT_DEFAULT_PRECIS, 31 CLIP_DEFAULT_PRECIS,

OSA IV LUKU 17 403 32 PROOF_QUALITY, 33 DEFAULT_PITCH + FF_DONTCARE, 34 "Arial" 35 ); 36 37 CFont* poldfont = pdc->selectobject(&fnbig); 38 39 // ** Draw the text 40 pdc->textout(ptcentre.x,ptcentre.y, 41 "...Beautiful Fonts"); 2 42 43 pdc->selectobject(poldfont); 44 } 45 } 2 Pyöritettävä teksti voidaan piirtää TextOut()-funktiolla. Listauksessa 17.8 tekstiä pyöritetään riveillä 17-43 riviltä 13 luetun keskipisteen ympäri. Kookas CreateFont()-funktiokutsu alkaa riviltä 21 ja sille syötetään kasvava paksuusparametri (weight) rivillä 25. Rivillä 23 funktio saa suunnan ja kallistuksen, jotka varsinaisesti aiheuttavat tekstin esittämisen silmukassa muutetuissa eri kulmissa. Käännettyäsi ja ajettuasi ohjelman muutosten tekemisen jälkeen näet tekstin pyörivän ikkunan keskipisteen ympäri, kuten kuvassa 17.2 on esitetty. Fontin luominen vain kerran sovelluksen nopeuttamiseksi Todellisessa sovelluksessa fontti todennäköisesti luodaan vain kerran ja tallennetaan näkymäluokan jäsenmuuttujaan, jolloin fontin luomiseen ei kulu ylimääräistä aikaa. KUVA 17.2 Pyörivä teksti CreateFont()- funktiota käyttäen.

404 Grafiikan piirtäminen Fonttien valitseminen Nykyään Windows-käyttäjä on tottunut laajaan fonttivalikoimaan. Fonttien valitseminen alkaa olla jo useissa sovelluksissa, eikä pelkästään tekstinkäsittelyohjelmissa, vakiovaruste. Jos haluat saada fonttien valintamahdollisuuden omaan sovellukseesi, joudut hakemaan luettelon tarjolla olevista fonteista sekä niiden asetuksista. Saat nämä palvelut GDI:n fonttien läpikäyntifunktioista sekä erikoisvalintaikkunoista. C++:n läpikäyntifunktiot Läpikäyntifunktiot (enumerator functions) olivat yleisiä tavallista C:tä ja WIN32-kirjastoa käytettäessä. Callback-tekniikoilla ei kuitenkaan voida välittää C++:n this-osoittimella tarkoitettua oliotietoa. Tästä syystä läpikäyntifunktioiden on oltava globaaleja, mikä ei sovi hyvin C++:n oliokeskeiseen ohjelmointimalliin. Koska MFC:n C++-luokkien tulee kuitenkin kaikkien Windows-ohjelmien tavoin hyödyntää WIN32- alijärjestelmää (ohjelmointikielestä riippumatta), niiden tulee hyväksyä globaalien callbackfunktioiden käyttö tässä erikoistapauksessa. Fonttien läpikäynti Kuinka ohjelmasi sitten saa luettelon järjestelmään asennetuista fonteista sekä niiden asetuksista? Vastaus on: EnumFontFamilies()- funktiolla sekä siihen liitetyllä callback-funktiolla. Callback-funktioita käytetään asettamalla käyttöön (itse tehty) funktio jokaisen luettelon jäsenen kohdalla suoritettavaksi ja kutsutaan läpikäyntifunktiota (enumerator) syöttämällä sille tuon funktion nimi. Läpikäyntifunktio käsittelee kaikki luettelon alkiot kutsuen jokaisen kohdalla erikseen callback-funktiota. Voit asettaa tällaisen läpikäyntifunktion käsittelemään fonttiluetteloa ja hakemaan fonttiin liittyvät tiedot. Nämä tiedot se sitten välittää callback-funktiollesi. Voit esimerkiksi näyttää asennettujen fonttien luettelona, jossa kunkin fontin nimi esitetään tuolla fontilla, kuten kuvassa 17.3 on esitetty. Listauksen 17.9 koodi sekä sitä seuraava selitys kertovat, kuinka EnumFontFamilies()-funktiolla saadaan tämä tehtyä. Jos haluat piirtää fonttiluettelon (kuvassa 17.3 esitettyyn tapaan) joudut lisäämään seuraavan callback-funktion ennen OnDraw()- funktiota. Huomaa, että kyseessä on globaali funktio, eikä sen nimen edessä ole minkään luokan määrettä. Joudut koodaamaan funktion tiedostoon ennen OnDraw()-funktiota muutoin joutuisit käyttämään ylimääräistä funktion prototyyppimäärittelyä ennen OnDraw()- funktiota. Lisää myös EnumFontFamilies()-funktion kutsu OnDraw()-funktioon listauksen 17.9 mukaisesti.

OSA IV LUKU 17 405 KUVA 17.3 EnumFontFamilies()-funktiolla läpikäydyt fontit. LISTAUS 17.9 LST17_9.CPP Asennettujen fonttien läpikäynti ja näyttäminen 1 // ** The Font Callback function 2 int CALLBACK FontCallBack(ENUMLOGFONT FAR* lpelf, 3 NEWTEXTMETRIC FAR *lpnt, 4 int FontType, 5 LPARAM lparam) 1 6 { 7 // ** Pick the DC pointer from the lparam 8 CDC* pdc = (CDC*)lParam; 9 CFont fnenum; 10 11 // ** Create the font indirectly 12 fnenum.createfontindirect(&lpelf->elflogfont); 2 13 14 CFont* poldfont = pdc->selectobject(&fnenum); 15 16 // ** Get the current Cursor position 17 int nypos = pdc->getcurrentposition().y; 18 19 // ** Draw the font name 20 pdc->textout(5,nypos,cstring( lpelf->elflogfont.lffacename)); 21 1 Callback-funktiotasi kutsutaan kerran jokaista järjestelmään asennettua fonttia kohden. Fontin tiedot funktio saa parametreinä. 2 CreateFontIndirect()-funktio on aivan CreateFont()-funktion kaltainen, mutta se saa parametrit LOGFONT-tietorakenteena.

406 Grafiikan piirtäminen 3 Tällä MoveTo()-funktiolla asetetaan piirto-osoitin valmiiksi seuraavaa fonttia varten. 4 Callback-funktion osoite syötetään EnumFontFamilies()- funktiolle, jotta se voi kutsua tätä jokaiselle asennetulle fontille erikseen. 22 //** Move down by the height of the font 23 pdc->moveto(0,nypos + lpelf->elflogfont.lfheight); 3 24 25 pdc->selectobject(poldfont); 26 27 // ** return TRUE to keep on going 28 return TRUE; 29 } 30 31 32 33 //////////////////////////////////////////////////////// 34 // CSimpTextView drawing 35 36 void CSimpTextView::OnDraw(CDC* pdc) 37 { 38 CSimpTextDoc* pdoc = GetDocument(); 39 ASSERT_VALID(pDoc); 40 41 // TODO: add draw code for native data here 42 43 // ** Setup the enum callback calling your function 44 EnumFontFamilies(pDC->GetSafeHdc(),NULL, 45 (FONTENUMPROC)FontCallBack,(LPARAM)pDC); 4 46 } Listauksessa 17.9 ensimmäinen funktio riveillä 1 29 on callbackfunktio. Tätä funktiota kutsutaan jokaisen järjestelmään asennetun fontin kohdalla erikseen ja fontin yksityiskohdat annetaan funktiolle parametreinä. Mitä tässä siis tapahtuu? OnDraw()-funktiossa alustetaan callback-funktion kutsuminen. lparam-parametri on käyttäjän määrittämä arvo, jonka callbackfunktion alustava kutsu on asettanut osoittimeksi piirtopintaan rivillä 44. Tälle piirtopinnalle piirretään piirtopinnan (siis näytön) kanssa yhteensopivien fonttien nimet. Rivillä 12 oleva CreateFontIndirect()-funktio toimii kuten CreateFont(), mutta sille syötetään kaikki parametrit yhdessä tietorakenteessa, kuten myöhemmin myös listauksessa 17.11 esitetään. Enum -funktion toinen parametri rivillä 44 on fonttiperhe. NULL tarkoittaa kaikkia fonttiperheitä. Jos olisit syöttänyt parametriksi esimerkiksi Arial tai Courier, olisit saanut luettelon ainoastaan tuon perheen fonteista. Kolmantena parametrinä annetaan callback-funktion nimi, jonka voit muuttaa vielä (FONTENUMPROC) tyyppiseksi kääntäjän herjojen välttämiseksi.

Lopuksi voit syöttää valitsemaasi tietoa long-tyyppisessä parametrissä. Fonttien piirtämisen tapauksessa tähän sopii osoitin piirtopintaan (johon piirrät) ehkä parhaiten. Kuten huomaat, läpikäyntifunktio hakee fonttiluettelon, alkaa kutsua callback-funktiotasi FontCallBack() syöttäen sille useita parametrejä, joista ensimmäinen on ENUMLOGFONT-tietorakenne. Listauksessa 17.10 esitetään tämän määrittely. LISTAUS 17.10 LST17_10.CPP ENUMLOGFONT-tietorakenne 1 typedef struct tagenumlogfont { 2 LOGFONT elflogfont; 3 BCHAR elffullname[lf_fullfacesize]; 4 BCHAR elfstyle[lf_facesize]; 5 } ENUMLOGFONT; OSA IV LUKU 17 407 Parametrinä syötetyssä ENUMLOGFONT-tietorakenteessa on fontin nimi elffullname-alkiona ja sen tyyli elfstyle-alkiossa, mutta ehkä kaikista käyttökelpoisin on siihen kuuluva LOGFONT-tietorakenne. Tähän tietorakenteeseen on koottu kaikki CreateFont()-funktiolle syötettävät parametrit. Kuten listauksen 17.9 riviltä 12 huomasit, sitä voidaan käyttää CreateFontIndirect()-funktion kanssa. Listauksessa 17.11 on esitetty tämän tietorakenteen määrittely Windowsissa. LISTAUS 17.11 LST17_11.CPP LOGFONT-tietorakenne 1 typedef struct taglogfont { 2 LONG lfheight; 3 LONG lfwidth; 4 LONG lfescapement; 5 LONG lforientation; 6 LONG lfweight; 7 BYTE lfitalic; 8 BYTE lfunderline; 9 BYTE lfstrikeout; 10 BYTE lfcharset; 11 BYTE lfoutprecision; 12 BYTE lfclipprecision; 13 BYTE lfquality; 14 BYTE lfpitchandfamily; 15 TCHAR lffacename[lf_facesize]; 16 } LOGFONT; Pääset käsiksi LOGFONTin yksityiskohtiin yhdistämällä LOGFONTtietorakenteen ENUMLOGFONT-tietorakenteen osoittimeen lpelf, jonka

408 TEXTMETRICS-tietorakenteet Kuten ehkä saatoit arvata, NEWTEXTMETRICStietorakenteella oli edeltäjä, TEXTMETRICS. Itse asiassa WIN32-tietorakenteista on useita eri versioita ja eri funktiot saattavat vaatia erilaisia tietorakenteen versioita. Sekaannuksen lisäämiseksi mukana ovat vielä NEWTEXTMETRICSEX, TEXTMETRICW ja TEXTMETRICA, jotka käsittelevät fonttien allekirjoituksia, Unicodea ja ei- Unicodea. Grafiikan piirtäminen callback-funktiosi saa syöteparametrinä (listauksen 17.9 rivillä 2). Tätä käytetään ensimmäisen kerran rivillä 12 (hakemaan LOGFONT-tietorakenteen osoite &lpelf->elflogfont-koodilla). Seuraava callback-funktiollesi syötetty parametri listauksessa 17.9 on NEWTEXTMETRICS-tietorakenne. Tässä ovat tiedot merkin koosta ja annetulle piirtopinnalle sovittamisesta. Sen jälkeen saat fontin tyypin (FontType). Tämä lippu kertoo, onko fontin tyyppi TRUETYPE_FONTTYPE, RASTER_FONTTYPE vai DEVICE_FONTTYPE (laitefontti). Lopuksi saat callback-funktioon vielä piirtopintaosoittimen LPARAM-tyyppisenä, minkä välittömästi muunnat CDC* -tyyppiseksi. Luotuasi ja valittuasi fontin saat piirto-osoittimen paikan listauksen 17.9 rivillä 17 GetCurrentPosition()-funktiolla. Voit lukea fonttien nimet LOGFONT-tietorakenteesta (kuten rivillä 20) ja näyttää nimen TextOut()-funktiolla. Piirto-osoittimen paikkaa muutetaan fontin korkeuden verran ja se asetetaan MoveTo()-funktiolla rivillä 23. Vanhan fontin uudelleenvalinnan jälkeen joudut palauttamaan läpikäyntifunktiolle TRUE, jotta se jatkaisi toimintaa seuraavalla alkiolla. FALSE tulkittaisiin, ettei callback-funktiota haluttaisi enää kutsuttavan. Fontinvalintaikkunan käyttö Windowsissa on valmis valintaikkuna fontin ja sen asetusten valintaan. Sitä käytetään useissa sovelluksissa itsekin olet varmaan käyttänyt tällaista sovellusta useita kertoja. Saat lisättyä esimerkkisovellukseen Choose Font ikkunan lisäämällä aluksi valikkoon uuden komennon fontinvalintaikkunaa varten. Voit siis lisätä Edit-valikkoon uuden komennon Choose Font (kuva 17.4) ja antaa komennon ID-tunnukseksi ID_CHOOSEFONT. Toimenpiteen yksityiskohdat selviävät luvusta 13. Tämän jälkeen joudut lisäämään uuden valikon komentosi (ID_CHOOSEFONT) COMMAND-sanomalle käsittelijän OnChoosefont() luokkaan CSimpleTextView (kuva 17.5). Ohjeet tähän löydät luvusta 13.

OSA IV LUKU 17 409 KUVA 17.4 Choose Font komennon lisääminen valikkoon. KUVA 17.5 OnChoosefont()-valikon käsittelijän lisääminen ClassWizardilla Nyt valikossa on sopiva komento ja siihen liitetty käsittelijäfunktio, johon voit lisätä ja käyttää CFontDialog-luokkaa listauksen 17.12 mukaisesti. LISTAUS 17.12 LST17_12.CPP OnChoosefont()-valikon käsittelijäfunktion toteutus 1 void CSimpTextView::OnChoosefont() 2 { 3 // TODO: Add your command handler code here 4 5 // ** Declare the CFontDialog 6 CFontDialog dlgchoosefont; 1 7 if (dlgchoosefont.domodal() == IDOK) 8 { 9 m_fncustom.deleteobject(); 10 m_fncustom.createfontindirect( 11 dlgchoosefont.m_cf.lplogfont); 12 Invalidate(); 13 } 14 } 1 CFontDialog paketoi järjestelmän CHOOSEFONTvalintaikkunan ja antaa käyttäjän valita helpolla, mutta edistyneellä tavalla halutun fontin. Listauksessa 17.12 määritellään rivillä 6 CFontDialog-luokan olio dlgchoosefont. Voit sitten avata valintaikkunan DoModal()- funktiolla, kuten rivillä 7 on tehty. Käyttäjä voi tällöin valita uuden fontin ja OK-painikkeen napautuksen jälkeen joudut kutsumaan vanhan fontin DeleteObject()-funktiota, jolloin vapautat GDIobjektin. Tämän jälkeen voit luoda uuden fontin CFontDialog-luokan m_cf-jäsenen avulla, jolla on osoitin LOGFONT-tietorakenteeseen. Kutsu lopuksi Invalidate()-funktiota (rivillä 12), jotta ikkuna piirrettäisiin uudelleen ja OnDraw()-funktiota kutsuttaisiin.

410 Grafiikan piirtäminen Seuraavaksi joudut lisäämään tuon m_fncustom-jäsenen näkymäluokkaan (view). Napauta projektin työtilaikkunassa ClassView-sivua ja kaksoisnapauta sivulla CSimpleTextView-luokkaa, jolloin saat esiin näkymäluokan määrittelyn. Lisää seuraava fonttijäsen // Attributeskommentin alle, kuten listauksessa 17.13 on tehty. LISTAUS 17.13 LST17_13.CPP CFont-jäsenen lisääminen näkymäluokkaan 1 // Attributes 2 public: 3 // ** Your New Added Font Member 4 CFont m_fncustom; 5 6 CSimpTextDoc* GetDocument(); Lopuksi joudut muuttamaan OnDraw()-funktiosi piirtämään tekstiä valitulla fontilla. Listaus 17.14 näyttää, miten tämä tehdään. LISTAUS 17.14 LST17_14.CPP Käyttäjän valitsemalla fontilla piirtäminen 1 void CSimpTextView::OnDraw(CDC* pdc) 2 { 3 CSimpTextDoc* pdoc = GetDocument(); 4 ASSERT_VALID(pDoc); 5 6 // TODO: add draw code for native data here 7 8 CFont* poldfont = pdc->selectobject(&m_fncustom); 9 pdc->textout(20,20, 10 "Bah bah black sheep, have you any wool"); 11 pdc->selectobject(poldfont); 12 } Listauksessa 17.14 fontti valitaan rivillä 8 ja teksti näytetään TextOut()-funktiolla rivillä 9 ja 10. Käännä ja aja ohjelmasi. Sovelluksessa pitäisi nyt voida muuttaa esitettävän tekstin fonttia valitsemalla Edit-valikosta Choose Font komento. Muuta haluamasi asetukset tässä ikkunassa ja sanoma näytetään uudelleen, kuten kuvassa 17.6.

OSA IV LUKU 17 411 KUVA 17.6 Font-valintaikkuna toiminnassa. KATSO MYÖS Erilaisten valikoiden lisääminen ja toteutus luvun 13 alussa. Muotoillun ja monirivisen tekstin lisääminen Fonttien eri koko vaikuttaa suoraan niiden tarvitsemaan piirtoalueeseen, joten tekstin rajaaminen määrättyyn ruutuun olisi turhan vaivalloista tähän mennessä opituin keinoin. Onneksi Windowsin DrawText()-funktio tulee apuun tässä vaiheessa. Funktion kolmesta parametristä ensimmäisenä annetaan tulostettava teksti CStringtyyppisenä, toisena suorakulmainen alue, johon teksti halutaan tulostettavan ja viimeisenä muttei vähäisimpänä lipputieto, jossa tekstin sijoittelu ja muotoilu ruutuun määritellään. Taulukossa 17.5 esitettyjä tärkeimpiä lippuarvoja voidaan tarpeen mukaan yhdistellä halutun tuloksen saavuttamiseksi. DrawTextEx()-funktion käyttö DrawText()-funktiosta on olemassa laajennettu versio DrawTextEx(). Tämä on käytössä ainoastaan WIN32-funktiona, joten joudut syöttämään sille kohdepiirtopinnan piirtopintakahvan ensimmäisenä parametrinä. Laajennettu muoto käyttää muutoin normaaleja parametrejä (siis piirtopintakahvan jälkeen), mutta sallii viimeisenä parametrinä myös DRAWTEXTPARAMS-tietorakenteen. Tässä tietorakenteessa voidaan määritellä sarkainpysähdykset ja vasen sekä oikea marginaali.

412 Grafiikan piirtäminen TAULUKKO 17.5 DrawText()-funktion muotoiluliput Lippu DT_LEFT DT_RIGHT DT_CENTER DT_VCENTER DT_WORDBREAK DT_CALCRECT DT_EXPANDTABS DT_NOPREFIX DT_TOP DT_BOTTOM Kuvaus Tasaa tekstin ruudun vasempaan reunaan. Tasaa tekstin ruudun oikeaan reunaan. Keskittää tekstin ruudun suhteen. Keskittää tekstin pystysuunnassa. Jakaa sanatkin tarvittaessa eri riveille (kuten tekstinkäsittelyohjelmissa). Ei piirrä tekstiä, vaan laskee ainoastaan ruudun koon. Muuttaa sarkainmerkit välilyönneiksi (oletuksena kahdeksaksi). Etuohjausmerkkejä ei käytetä ilman tätä &- merkki muuttaisi seuraavan merkin pika valinnaksi. Tasaa tekstin rivin yläreunan mukaan (vain yksirivinen teksti). Tasaa tekstin rivin alareunan mukaan (vain yksirivinen teksti). Nyt voit muuttaa Choose Font ohjelmasi OnDraw()-funktiota siten, että se tulostaa tekstin DrawText()-funktiolla TextOut():in sijaan. Muutokset on esitetty listauksessa 17.15. LISTAUS 17.15 LST17_15.CPP Muotoillun tekstin piirtäminen DrawText()-funktiolla 1 void CSimpTextView::OnDraw(CDC* pdc) 2 { 3 CSimpTextDoc* pdoc = GetDocument(); 4 ASSERT_VALID(pDoc); 5 6 // TODO: add draw code for native data here 7 8 CFont* poldfont = pdc->selectobject(&m_fncustom); 9 10 CRect rcsmall(cpoint(20,20),cpoint(200,100)); 11 pdc->rectangle(rcsmall); 12 pdc->setbkmode(transparent); 13 // ** Call DrawText with the message in the rect 14 // ** Word Breaking and centralized

OSA IV LUKU 17 413 15 16 pdc->drawtext( 17 "Bah bah black sheep, have you any wool", 18 rcsmall, DT_WORDBREAK + DT_CENTER); 1 19 20 pdc->selectobject(poldfont); 21 } 1 Syöttämällä DrawText()- funktiolle DT_WORDBREAK- ja DT_CENTER-liput teksti saadaan rivitettyä ja keskitettyä annetulle alueelle. Listauksen 17.15 rivillä 16 piirretään DrawText()-funktiolla esimerkkiteksti rcsmall-suorakulmioon. Käännettyäsi ohjelman muutosten tekemisen jälkeen ja ajettuasi sen, näet kuvan 17.7 mukaisesti tekstin ruutuun keskitettynä ja rivitettynä. Fonttia muuttamalla näet koon muuttamisen vaikutuksen suorakulmiossa olevaan tekstiin. KUVA 17.7 DrawText()-funktiolla muotoiltua tekstiä. KATSO MYÖS Kuinka saisit tekstin luettua käyttäjältä tekstiruudusta luvusta 5.

414 Grafiikan piirtäminen Fonttien tuhoaminen Muiden paketointiluokkien tapaan oliossa olevat GDI-fonttiobjektit tuhotaan, kun oliot eivät ole enää käytössä. Voit myös tuhota fonttiobjektin (joka ei ole valittuna piirtopinnalla) manuaalisesti DeleteObject()-funktiolla. Tämän jälkeen voit käyttää paketointiluokkaa uudelleen kutsumalla sopivaa Create-funktiota. Fontit vievät GDI-objekteista eniten muistia, joten muista tuhota tarpeettomat fonttiobjektit. Jos tarvitset fonttia uudelleen, se kannattaa tallettaa näkymäluokan jäsenmuuttujaksi, jolloin voit valita fontin luomatta sitä joka käyttökerta uudelleen. Tämä nopeuttaa ohjelman toimintaa. KATSO MYÖS Lisätietoja GDI-objekteista luvun 15 alusta.