Hiirisanomiin vastaaminen



Samankaltaiset tiedostot
Piirtopinnalle piirtäminen

Visual C++ -ohjelman tekeminen ja suunnittelu

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

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

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

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

Tulostaminen ja esikatselu

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

MDI-sovellusten kehittäminen

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

Kynien ja siveltimien käyttö

Hiirisanomiin vastaaminen. 2007

Ohjelmoinnin perusteet Y Python

,QWHUQHWVHODLPHQNl\WWlPLQHQ±,QWHUQHW([SORUHU

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

Versio 1.1 P/N Copyright 2002, ATI Technologies Inc. Kaikki oikeudet pidätetään.

Siirtyminen Outlook versioon

TeamViewer 11 -ohjelma etäkoulutuksissa ja tuessa

ActiveX-kontrollien käyttö

Interaktiivinen käyttöliittymä. 2008

Osio 4: Graafinen käyttöliittymä

OHJE 1(6) Windowsin ääniasetukset Jos äänet eivät kuulu ConnectPro:ssa, Skypessä tai muussa ohjelmassa,

2.1 Yksinkertaisen geometrian luonti

Käyttöliittymän muokkaus

Harjoitustyö: virtuaalikone

GeoGebra-harjoituksia malu-opettajille

UpdateIT 2010: Editorin käyttöohje

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

KUVAN TUOMINEN, MUOKKAAMINEN, KOON MUUTTAMINEN JA TALLENTAMINEN PAINTISSA

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

PageMaker 6.5 -moniste

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

Peilaus pisteen ja suoran suhteen Pythonin Turtle moduulilla

HARJOITUKSIA ios-ohjelmointiin LIITTYEN

Tämän monisteen tarkoitus on tutustua pikamaski -toimintoon GIMP:issä.

Jos haluat uuden Share-työkalun, valitse Pods -> Share -> Add New Share tai jos sinulla on jo auki Share-työkalu, näyttää se tältä:

Jypelin käyttöohjeet» Ruutukentän luominen

2016/07/05 08:58 1/12 Shortcut Menut

Sovellusten ohjelmointi Microsoft Foundation Classes -luokkien avulla

ActiveX-kontrollien luominen

Scratch ohjeita. Perusteet

WINDOWS 10 -kurssi.

Windows 10 käyttöjärjestelmän helppokäyttötoiminnot ja asetukset

Dokumentit, näkymät ja kehykset

Tasohyppelypeli. Piirrä grafiikat. Toteuta pelihahmon putoaminen ja alustalle jääminen:

Avaa ohjelma ja tarvittaessa Tiedosto -> Uusi kilpailutiedosto

Tapahtumapohjainen ohjelmointi. Juha Järvensivu 2007

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

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

Windows 8.1 -käyttöjärjestelmän käytön aloitus

Näkymien vierittäminen ja koon muuttaminen

Helppokäyttöisyyttä Windows Vista käyttöjärjestelmän asetuksilla

Ohjelmoinnin perusteet Y Python

Hiiressäsi on kallistusrulla pysty- ja vaakasuoravieritystä, yhden askeleen zoomausta ja nopeaa Internet-navigointia varten.

NetMeetingiä voi käyttää esimerkiksi Internet puheluissa, kokouksissa, etätyössä, etäopiskelussa ja teknisessä tuessa.

Ohje internetkarttapalveluun

EASY Tiedostopalvelin - mobiilin käyttöopas

Skype for Business pikaohje

Olio-ohjelmointi Javalla

Usean näkymän luominen

TIETOKONEEN ASETUKSILLA PARANNAT KÄYTETTÄVYYTTÄ

Ohjelmoinnin peruskurssi Y1

Pikanäppäin Yhdistelmiä. Luku 6 Pikanäppäimet

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

LUKU 17 MUUTAMIA JAVA FX -SOVELLUKSIA. Tässä dokumentissa esitellään muutamia Java FX -sovelluksia.

Ohjeissa pyydetään toisinaan katsomaan koodia esimerkkiprojekteista (esim. Liikkuva_Tausta1). Saat esimerkkiprojektit opettajalta.

Adobe Premiere 6.0 ohjelmasta

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

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

H5P-työkalut Moodlessa

Uutiskirjesovelluksen käyttöohje

Listarakenne (ArrayList-luokka)

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

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

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

Harjoitus 2: Oppijan aktivointi ( )

TAITAJA 2007 ELEKTRONIIKKAFINAALI KILPAILIJAN TEHTÄVÄT. Kilpailijan nimi / Nro:

Tämä on PicoLog Windows ohjelman suomenkielinen pikaohje.

Palvelemme arkisin klo. 08:00-17:00

SSH Secure Shell & SSH File Transfer

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

ASIO-OHJE HENKILÖSTÖLLE.

Gree Smart -sovelluksen (WiFi) asennus- ja käyttöohje: Hansol-sarjan ilmalämpöpumput WiFi-ominaisuuksilla

KUVAN LIITTÄMINEN TOISEEN KUVAAN PHOTOSHOP ELEMENTS 6 - OHJELMALLA

Kuva 1. Jokaisen tavallisen kuvan tasotyökalussa näkyy vain yksi taso, tässä nimellä tausta.

Graafisen käyttöliittymän ohjelmointi

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

WCONDES OHJEET ITÄRASTEILLE (tehty Condes versiolle 8)

PowerPoint -esitysgrafiikka

Vahva tunnistautuminen Office palveluihin. MFA Suojauksen lisätarkistus

Ladataan kartta näkyviin. Avataan valmiiksi ladattu kartta valikosta: Lataa -> Lataa kartta tiedosto

Muuttujien määrittely

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

2020 Fusion. What s New in Version 6? What s New in Version 6? 1 of Fusion

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

Mukavia kokeiluja ClassPad 330 -laskimella

Tekstinkäsittelyn jatkokurssi

1 ClipArt -kuvan käyttö Paint-ohjelmassa

Käyttöopas RoofCon Viewer

ohjeet. AtFlow Oy, Pekka Rönkkönen, +358 (0)

Transkriptio:

OSA II LUKU 8 163 8 LUKU Reagointi käyttäjän painaessa tai vapauttaessa hiiren painikkeen Omien funktioiden käyttö, kun hiiri liikkuu Hiirikoordinaattien käsittely ja valitun alueen tutkiminen

164 Näppäinpainallusten ajoituksen seuranta Kaikissa Windowsin sanomissa on tieto sanoman postitusajankohdasta. Tämä saadaan selville MSG-tietorakenteen timejäsenestä korvaamalla virtuaalifunktio PreTranslateMessage(). PreTranslateMessage()-funktiota kutsutaan ennen sanomakartan käsittelyä kunkin sanoman saavuttua sovellukseen. Valintaikkunat ja kontrollit Hiiren painikesanomien käsittely Usein halutaan tietää, milloin ja missä hiiren painiketta painettiin tai milloin se vapautettiin ja ilman painikekontrollia. Yksinkertainen esimerkki on piirto-ohjelma, jossa ikkunaa käytetään piirtopintana, jonne piirretään napauttamalla hiiren painiketta tuon alueen päällä. Kuten jo aiemmin olet huomannut, kaikki käyttäjän syöte saapuu sovelluksellesi sanomina (message) tai tapahtumina (event). Hiiripainikkeen sanomat eivät poikkea tästä kaavasta. Painikesanomien mukana seuraa myös hiiriosoittimen paikkatieto, jolloin näitä sanomia voidaan helposti käyttää yhdessä Windowsin piirtofunktioiden kanssa. Painalluksen ja vapautuksen käsittely Windows käsittelee kolmea hiiren painiketta vasenta, keskimmäistä ja oikeaa. Toisissa hiirissä painikkeita on vain kaksi, joten käsiteltäväksi jää ainoastaan tapahtumat vasemmalta ja oikealta painikkeelta. Tästä syystä useimmat sovellukset vastaavat ainoastaan hiiren oikean ja vasemman painikkeen käyttöön, mutta erityistapauksissa saatat tarvita kaikkia kolmea. Sovellus saa Windowsilta kultakin painikkeelta kaksi tapahtumaa: kun painike painetaan alas ja kun se vapautetaan. Koska nämä sanomat on suunnattu suoraan ikkunan kantaluokalle, otat ne tavallaan kiinni (catch) omassa koodissasi ennen sitä. Napataksemme näitä tapahtumia luomme aluksi AppWizardilla tavallisen valintaikkunasovelluksen nimeltä MouseMsg. (Seuraa luvun 4 ohjeita tavallisen painikekontrollin yhteydessä.) Luotuasi valintaikkunasovelluksen, voit suurentaa resurssieditorissa pääikkunan IDD_MOUSEMSG_DIALOG noin 300 kuvapistettä leveäksi ja 200 korkeaksi. Näin saat tilaa tutkia saatuja hiirikoordinaatteja. Jotta hiirellä olisi riittävästi tilaa, poista valintaikkunasta TODO: Place Controls Here teksti ja jätä vain OK- ja Cancel-painikkeet. Seuraavien vaiheiden avulla saat lisättyä sanomankäsittelijän nappaamaan sanoman, jonka Windows lähettää sovellukselle käyttäjän painaessa hiiren vasenta painiketta. Hiiripainikkeen sanomankäsittelijän lisääminen 1. Napauta projektin työtilaruudussa ClassView-välilehteä. 2. Napauta ylintä plusmerkkiä, jotta saisit esiin projektisi kaikki luokat.

3. Napauta hiiren oikeaa painiketta CMouseMsgDlg-luokan yllä ja saat esiin pikavalikon. 4. Valitse Add Windows Message Handler komento ja saat esiin vastaavan ikkunan. 5. Valitse ikkunassa New Windows Messages/Events luettelosta WM_LBUTTONDOWN-sanoma. 6. Napauta Add and Edit painiketta ja pääset muokkaamaan uutta käsittelijää. Nyt käytössäsi on funktio OnLButtonDown() hiiren vasemman painikkeen lähettämiä tapahtumia varten. Tätä funktiota kutsutaan, kun käyttäjä painaa hiiren vasenta painiketta. Voit lisätä tähän funktioon oman piirtokoodisi. Esimerkiksi listauksen 8.1 koodi piirtää ikkunaan huutomerkin aina, kun hiiren painiketta painetaan. LISTAUS 8.1 LST8_1.CPP OnLButtonDown()-käsittelijän muokkaaminen piirtämään huutomerkki hiiren napautuspaikalle OSA II LUKU 8 165 1 void CMouseMsgDlg::OnLButtonDown(UINT nflags, CPoint point) 2 { 3 // TODO: Add your message handler code here and/or call default 4 5 // ** Display a message in the window title bar 6 CString strmessage; 7 strmessage.format("left Button Pressed at (%d,%d)", 8 point.x,point.y); 1 9 SetWindowText(strMessage); 10 11 // ** Choose the icon depending on the control key 12 char* pszicon; 13 if (nflags & MK_CONTROL) 2 14 pszicon = IDI_EXCLAMATION; 15 else 16 pszicon = IDI_HAND; 17 18 // ** Draw an exclamation Icon at that point 19 CDC* pdc = GetDC(); 20 pdc->drawicon(point, 21 AfxGetApp()->LoadStandardIcon(pszIcon)); 3 22 ReleaseDC(pDC); 23 24 CDialog::OnLButtonDown(nFlags, point); 25 } 1 Asema muotoillaan merkkijonomuuttujaan ja näytetään valintaikkunan otsikkopalkissa. 2 Jos Ctrl-näppäin on painettuna, valitaan eri kuvake. 3 Valittu kuvake piirretään hiiren paikkaan.

166 Windows 95/98:n ja NT 4.0:n vakiokuvakkeet Jos käytät näitä vakiokuvakkeita, huomaat, että kuvakkeiden nimet eivät vastaa kuvaa. Esimerkiksi IDI_HAND piirtää valkean rastin punaiselle taustalle eikä kättä (hand) näy missään. Nimien alkuperä johtaa Windows 3.11 ja NT 3.51:een - kuvakkeita on päivitetty, mutta nimet pidetty samoina. Valintaikkunat ja kontrollit Huomaa, että listauksessa 8.1 OnLButtonDown()-funktiolle välitetään kaksi parametriä: ensimmäinen, nflags, kertoo, mitä muita hiiren painikkeita pidetään alhaalla ja onko yhtä aikaa painettu myös vaihtotai Ctrl-näppäimiä. Nämä lippuarvot on esitetty taulukossa 8.1. Liput ovat yhden bitin mittaisia ja useampi lipuista voi olla käytössä yhtä aikaa. Jos haluat tutkia tietyn lipun tilaa, käytä C++:n &-operaattoria (looginen AND), kuten rivillä 13 on tehty. Listauksessa testataan MK_CONTROL-lippua, joka on TRUE, kun Ctrl-näppäintä painetaan hiiren vasenta painiketta napautettaessa. Listauksessa rivillä 14 asetetaan pszicon-osoitin osoittamaan järjestelmän IDI_EXLAMATION kuvakkeeseen (huutomerkki) tai IDI_HANDkuvakkeeseen, riippuen nflags-muuttujan Ctrl-näppäintestin onnistumisesta. Nämä kuvakkeet kuuluvat Windowsin vakiovalikoimaan ja niitä käytetään rivin 20 ja 21 DrawIcon()-piirtofunktioissa. Kun sovellusluokan funktiolle LoadStandardIcon() syötetään psziconosoitin, saadaan kyseinen kuvake luettua käyttöä varten (rivi 21). Muut järjestelmän kuvakkeet on lueteltu taulukossa 8.2. Toinen OnLButtonDown()-funktiolle syötetty parametri on CPointolio nimeltä point. CPoint-luokka tallettaa pisteen koordinaatit x- ja y-jäseninä. Rivillä 7 pisteen koordinaatit muutetaan merkkijonoksi, joka näytetään ikkunan otsikkopalkissa SetWindowText()-funktiolla rivillä 9. Tätä samaa pistettä käytetään vielä rivillä paikantamaan piirrettävä kuvake. TAULUKKO 8.1 OnLButtonDown-käsittelijälle välitetyn nflags-parametrin bittiliput Lipun arvo MK_LBUTTON MK_MBUTTON MK_RBUTTON MK_CONTROL MK_SHIFT Kuvaus Hiiren vasen painike on painettuna. Hiiren keskimmäinen painike on painettuna. Hiiren oikeanpuoleinen painike on painettuna. Ctrl-näppäin on painettuna. Vaihtonäppäin on painettuna.

TAULUKKO 8.2 LoadStandardIcon()-funktiolla saatavat järjestelmän kuvakkeet OSA II LUKU 8 167 Kuvake IDI_EXCLAMATION IDI_HAND IDI_APPLICATION IDI_ASTERISK IDI_QUESTION Kuvaus Huutomerkki kolmiossa X punaisessa ympyrässä Sovelluksen oletuskuvake i niin kuin info, sinisellä taustalla Kysymysmerkki Kun lisäät listauksen 8.1 koodin käsittelijäfunktioosi ja koostat ja ajat ohjelmasi, sinulla on maailman yksinkertaisin piirto-ohjelma. Voit napautella sovellusikkunassa hiirellä: vasemmalla painikkeella piirretään napautuskohtaan huutomerkki ja jos Ctrl-näppäin on yhtä aikaa painettuna, rasti (kuva 8.1). 1 2 KUVA 8.1 Kuvakkeiden piirtäminen hiiren vasemman painikkeen napautuksella. 1 Huutomerkki piirretään, kun pelkästään vasenta painiketta painetaan. 2 Rasti piirretään, kun myös Ctrl-näppäin on painettuna. Huomaa myös, että hiiren viimeisin napautuspaikka näytetään ikkunan otsikkopalkissa. Jos napautat lähellä ikkunan vasenta yläkulmaa, huomaat, että koordinaatit ovat ikkunakoordinaatteja eivätkä koko ruudun koordinaatteja. Halutessasi saat selville koordinaatit ruudulla funktiolla GetCursorPos(). Funktiolle syötetään koordinaattien tallettamista varten yksi CPoint-parametri. Voit kokeilla näyttökoordinaatteja lisäämällä käsittelijääsi listauksen 8.1 rivillä 3 olevien TODO-kommenttien jälkeen rivin: GetCursorPos(&point);

168 Valintaikkunat ja kontrollit Koostettuasi ja käynnistettyäsi ohjelman huomaat, että otsikkopalkissa esitettävät koordinaatit mitataankin suhteessa näytön eikä ikkunan vasempaan yläkulmaan. Tosin myös kuvakkeet piirretään käyttäen noita koordinaatteja, vaikka piirto vaatiikin ikkunakohtaiset koordinaatit. Näin ollen kuvakkeet piirretään hieman hiiren viereen. Tämän kokeilun jälkeen halunnet ehkä poistaa tuon juuri lisätyn rivin. Voit lisätä käsittelijän myös sanomalle hiiren vasemman painikkeen vapauttamisesta aivan edellä olleiden painikkeen painamissanoman ohjeiden mukaan. Korvaa tässä kuitenkin WM_LBUTTONDOWNsanoma sanomalla WM_LBUTTONUP, joka luo käsittelijäfunktion OnLButtonUp(). Voit sitten lisätä funktioon oman koodisi, esimerkiksi kertomaan ikkunan otsikkopalkissa, että painike on vapautettu: SetWindowText( Left Button Released ); Kun lisäät tämän rivin, koostat ja käynnistät ohjelmasi huomaat, että tätä käsittelijää kutsutaan aina, kun vapautat hiiren vasemman painikkeen. Näin voit esimerkiksi käynnistää ohjelmassasi erikoistoiminnan, kun hiiren painike painetaan alas ja lopettaa sen, kun painike vapautetaan. Tuttu esimerkki tästä on ikkunan siirtäminen ruudulla. Painat hiiren vasemman painikkeen alas ikkunan otsikkopalkin päällä ja pääset siirtotilaan; vapautat painikkeen ja ikkuna jää uuteen paikkaan ja voit jatkaa muuta toimintaa. Hiiren keskimmäisen painikkeen käsittelijöiden käyttö Keskimmäisen painikkeen käsitteminen on hankalaa,koska se ei ole mukana ClassWizardin luetteloissa. Tästä syystä joudutaan lisäämään rivit sanomakarttaan sekä funktion määrittely manuaalisesti. Kaiken tämän tarkoitus on hankaloittaa vain kolminäppämisellä hiirellä toimivien ohjelmien tekemistä. Samanlaiset käsittelijät voi tehdä myös hiiren keskimmäiselle ja oikeanpuoleiselle painikkeelle aivan samoin ohjein. Käytät tällöin taulukosta 8.3 löytyvää sanoman nimeä ja vastaavaa käsittelijäfunktiota. TAULUKKO 8.3 Windowsin hiiren painikesanomat Sanoman nimi AppWizard käsittelijän nimi Kuvaus WM_LBUTTONDOWN OnLButtonDown Vasen painike painettu WM_LBUTTONUP OnLButtonUp Vasen painike vapautettu WM_MBUTTONDOWN ei ole Keskimmäinen painike painettu WM_MBUTTONUP ei ole Keskimmäinen painike vapautettu WM_RBUTTONDOWN OnRButtonDown Oikea painike painettu WM_RBUTTONUP OnRButtonUp Oikea painike vapautettu

KATSO MYÖS Lisätietoja piirtämisestä piirtopinnalle luvun 15 alussa. Valintaikkunan suunnittelu ja muokkaus luvussa 3. OSA II LUKU 8 169 Kaksoisnapautus Kaksoisnapautuksella (double-clicking) on usein erikoismerkitys Windows-sovelluksissa. Monesti sitä käytetään pikavalintana luetteloissa. Käyttäjä saa lähetettyä kaksoisnapautuksen sovellukselle napauttamalla hiiren samaa painiketta kaksi kertaa nopeasti peräkkäin. Windows mittaa napautuksien välisen ajan ja jos se on riittävän lyhyt, lähettää sovellukselle WM_LBUTTONDBLCLK-sanoman (kun napautettiin vasenta painiketta). Keskimmäiseltä ja oikeanpuoleiselta painikkeelta saadaan vastaavasti WM_MBUTTONDBLCLK ja WM_RBUTTONDBLCLK - sanomat. Voit lisätä näille käsittelijät aiemman hiiren vasemman näppäimen käsittelyfunktion tavoin. Esimerkiksi sanomaruutu saadaan näytettyä hiiren vasemman painikkeen kaksoisnapautuksen seurauksena seuraavasti: void CMouseMsgDlg::OnLButtonDblClk(UINT nflags, CPoint point) { AfxMessageBox( Left Button Double Clicked ); CDialog::OnLButtonDblClk(nFlags, point); } Lisättyäsi koodin ja käännettyäsi ohjelmasi, näet ohjelmaa ajettaessa sanomaruudun aina, kun kaksoisnapautat hiiren vasenta painiketta. Muiden hiiren painikesanomien tavoin saat kaksoisnapautuksestakin parametreinä nflags-liput painikkeiden ja näppäinten tilan selvittämiseen sekä point-olion koordinaatteineen. Kaksoisnapautuksen nopeuden asettaminen Kaksoisnapautuksen painallusten välinen aikaero voidaan määrittää Ohjauspaneelin Hiirikuvakkeesta, jossa säätö tehdään liukusäätimellä esimerkkianimaation avulla. Hiiren liikkeen ja paikan seuranta Hiiren napautuspaikan selvittäminen on hyödyllistä, mutta joskus halutaan myös tietää, missä hiiri liikkuu sen raahaamisen aikana. Piirto-ohjelma voisi käyttää tätä esimerkiksi vapaalla kädellä piirrettävien viivojen piirtämisessä. Windows vastaa tarpeeseen lähettämällä sanoman aina, kun hiirtä liikutetaan ja sanoman mukana hiiriosoittimen koordinaatit.

170 Hiiren liikkeen käsittelyn rajoittaminen Tavallisesti ohjelmissa pyritään rajoittamaan hiiren liikesanoman käsittelyssä tehtävää työtä, koska sanomia saattaa tulla useita nopeasti peräkkäin. Liika prosessointi hidastaa järjestelmää ja vastetta käyttäjälle. 1 Hiiren asema tallennetaan muuttujaan OnPaint()-funktiossa tulevaa käyttöä varten. Valintaikkunat ja kontrollit Mouse Move tapahtuman käsittely Hiiren painikkeiden tavoin myös hiiren liikkumisesta lähetetään sanoma sovelluksellesi, tällä kertaa WM_MOUSEMOVE-sanomana. Saat lisättyä käsittelijän WM_LBUTTONDBLCLK-sanomalle aiemmin esitetyllä tavalla (kun käsiteltiin vasemman painikkeen painamista). ClassWizard tekee sen seurauksena OnMouseMove()-käsittelijän, joka on esitetty listauksessa 8.2. LISTAUS 8.2 LST8_2.CPP OnMouseMove()-käsittelijässä näytetään ja tallennetaan osoittimen paikka hiiren liikkuessa 1 void CMouseMsgDlg::OnMouseMove(UINT nflags, CPoint point) 2 { 3 // TODO: Add your message handler code here and/or call default 4 5 // ** Display the mouse position 6 CString strmessage; 7 strmessage.format("mouse Position = (8%d,%d)", 8 point.x,point.y); 9 SetWindowText(strMessage); 10 11 // ** Store the point and redraw the window 12 m_ptmouse = point; 1 13 Invalidate(); 14 15 CDialog::OnMouseMove(nFlags, point); 16 } Huomaa, että OnMouseMove()-funktiolle välitetyt parametrit ovat samat kuin painiketapahtumien käsittelijöillä. Voit tutkia painetut painikkeet ja näppäimet nflags-lipuista taulukon 8.1 mukaisesti samoin kuin tehtiin painikkeelle listauksessa 8.1. Toinen parametri sisältää hiiren paikan point-oliossa, tämä esitetään otsikkopalkissa listauksen 8.2 riveillä 6-9. Rivillä 13 kutsuttu Invalidate()-funktio pakottaa ikkunan piirrettäväksi uudelleen. Voit tallettaa hiiren paikan CMouseMsgDlg-luokkaan jäsenmuuttujaksi sen näytölle päivittämistä varten. Muuttujaa on jo käytetty listauksen rivillä 12 ja joudutkin lisäämään jäsenmuuttujan luokan määrittelyyn ennen ohjelman kääntämistä. Jäsenmuuttujan lisääminen valintaikkunaluokkaan käy seuraavasti.

Jäsenmuuttujan lisääminen valintaikkunaluokkaan 1. Napauta projektin työtilaruudussa ClassView-välilehteä. 2. Napauta ylintä plusmerkkiä, jotta saisit esiin projektisi kaikki luokat. 3. Napauta hiiren oikeaa painiketta CMouseMsgDlg-luokan yllä ja saat esiin pikavalikon. 4. Valitse Add Member Variable komento ja saat esiin vastaavan ikkunan. 5. Syötä muuttujan tyypiksi Variable Type ruutuun CPoint. 6. Anna muuttujan nimeksi Variable Declaration ruutuun m_ptmouse. Voit jättää tässä esimerkissä ennalleen käyttöoikeudet (Access Type) oletusasetukseen Public Access (jolloin muuttuja on kaikkien olioiden käytettävissä). Jos et halua antaa muiden luokkien käyttää muuttujaa, voit vaihtoehtoisesti muuttaa käyttöoikeuksiksi Protected tai Private. 7. Lisää uusi jäsenmuuttuja napauttamalla OK. Näin olet lisännyt m_ptmouse-muuttujan, jota voidaan nyt käyttää OnPaint()-käsittelijäfunktiossa piirtämään ikkuna osoittamaan hiiren viimeisintä paikkaa. Lisäämällä listauksen 8.3 koodin, saat sovelluksen, jossa silmät seuraavat hiiriosoitinta sitä liikuttaessasi. Lisää koodi kaksoisnapauttamalla projektin työtilaruudussa ClassView-sivulla OnPaint()-jäsenfunktiota. Ellei se ole näkyvissä, joudut napauttamaan ensin CMouseMsgDlg-tekstin viereistä plusmerkkiä saadaksesi luokan jäsenfunktiot esiin. Tässä funktiossa on valmiiksi koodisovelluksen kuvakkeen piirtämiseksi tilanteessa, jolloin IsIconic()-funktio palauttaa arvon TRUE (eli sovellusikkuna on pienennetty). Sinun ei tarvitse välittää siitä, vaan voit lisätä koodisi tyhjään else-lohkoon // TODO: -kommenttien jälkeen. LISTAUS 8.3 LST8_3.CPP Silmäparin piirtäminen seuraamaan hiiriosoitinta OSA II LUKU 8 171 1 else 2 { 3 // ** Create a device context for drawing 4 CPaintDC dc(this); 1 5 6 // ** Find the dialog dimensions 7 CRect rcdlg; 8 GetClientRect(&rcDlg); 1 Paint-piirtopinta alustetaan ja käytetään piirtämistä varten.

172 Valintaikkunat ja kontrollit 2 Silmän sijainniksi asetetaan tässä 80 pistettä valintaikkunan keskipisteestä. 3 Silmän valkea osa piirretään Ellipse()-funktiolla. 4 Silmän pupillin sijainti lasketaan hiiren paikan perusteella. 5 Tässä pupillit piirretään hiiren suuntaan siirrettyinä. 9 10 // ** Loop twice, once for each eye 11 for(int i=0;i<2;i++) 12 { 13 // ** Find the center of the eye 14 CPoint pteye = rcdlg.centerpoint(); 15 16 // ** Set the eye position for each eye 17 pteye.x += i==0? -80 : +80; 2 18 19 // ** Make a eye rectangle 20 CRect rceye(pteye,pteye); 21 rceye.inflaterect(40,60); 22 23 // ** Draw the eye white 24 dc.selectstockobject(white_brush); 25 dc.ellipse(rceye); 3 26 rceye.deflaterect(20,40); 27 28 // ** Use the mouse position to update the pupil 29 CPoint ptrel = m_ptmouse - rceye.centerpoint(); 30 double dx = (double)ptrel.x * 31 (rceye.width() / (double)rcdlg.width()); 32 double dy = (double)ptrel.y * 33 (rceye.height() / (double)rcdlg.height());4 34 35 // ** Move the pupil position and draw it 36 rceye.offsetrect(cpoint((int)dx,(int)dy)); 37 dc.selectstockobject(black_brush); 38 dc.ellipse(rceye); 5 39 } 40 41 CDialog::OnPaint(); 42 } Listauksessa 8.3 rivillä 4 luodaan CPaintDC-piirtopintaolio piirtämistä varten (piirtopintoja käsitellään varsinaisesti luvussa 15). Valintaikkunan koko selvitetään rivillä 8 funktiolla GetClientRect() ja se talletetaan rivillä 7 määriteltyyn CRect-luokan olioon rcdlg. CRectluokka tallettaa kaksi CPoint-oliota toinen vastaa näytöllä olevan suorakulmion vasenta yläkulmaa ja toinen oikeaa alakulmaa. Luokassa on myös käyttökelpoiset funktiot suorakulmion keskikohdan, leveyden ja korkeuden selvittämiseksi sekä sen koon muuttamiseksi. Rivillä 11 aloitetaan kaksi kertaa suoritettava silmukka eli kerran kullekin silmälle. Silmän määrittävän suorakulmion paikka määritetään

rivillä 14 hakemalla ensin ikkunan keskikohta ja rivillä 17 asettamalla silmät siitä vasemmalle ja oikealle. Rivillä 20 tuo nelikulmio suurennetaan oikean kokoiseksi ja valkoinen osa piirretään riveillä 25-26. Suorakulmio pupillia varten asetetaan oikean kokoiseksi rivillä 26. Rivi 29 on todella kiinnostava. Tässä lasketaan pupillin sijainti hiiriosoittimen paikan perusteella. Ero lasketaan ja asetetaan riveillä 30-36 ja riveillä 37 ja 38 piirretään. En ole selittänyt piirtofunktioita tässä kovin tarkasti, koska niitä kuitenkin käsitellään luvussa 16. Koostettuasi ja käynnistettyäsi ohjelmasi näiden muutosten jälkeen sinulla on ikkuna, jossa on kaksi hiiriosoitinta seuraavaa silmää (kuva 8.2). OSA II LUKU 8 173 KUVA 8.2 Kaksi silmää seuraa hiiriosoitinta sen liikkuessa ikkunassa. KATSO MYÖS Lisätietoja OnPaint-käsittelijästä luvussa 15. Oppia kynällä ja siveltimellä piirtämisestä luvussa 16. Hiirisyötteen kaappaaminen Jos olet kääntänyt listauksen 8.3 koodin, huomannet siinä pienen ongelman: kaikki menee hyvin vain niin kauan kuin pysyt ikkunan sisällä. Syy tähän on, että tavallisesti sovellukselle lähetetään hiirisanomia vain, kun osoitin on kyseisen sovelluksen ikkunan kohdalla. Kun siirrät hiiren sovellusikkunan ulkopuolelle, saa toinen ikkuna hiirisanomat. Voit kuitenkin omia nuo sanomat omalle ikkunallesi kaappaamalla hiiren (mouse capture).

174 Hiirisyötteen kaappaamissäännöt Ainoastaan edustalla oleva ikkuna voi kaapata hiiren syötteen. Jos joku taustalla olevista ikkunoista yrittää saada hiirisyötteen itselleen, se onnistuu ainoastaan ikkunan näkyvissä osissa. Hiirisyöte voi kohdistua kerrallaan ainoastaan yhdelle ajossa olevalle ohjelmalle. Valintaikkunat ja kontrollit Saat kaapattua hiirisanomat helposti kutsumalla SetCapture()- funktiota kaappaavasta sovellusikkunasta. Tällainen toiminta on kuitenkin epäkohteliasta muita sovelluksia kohtaan, joten hiiri tulee palauttaa mahdollisimman pian normaalitilaansa ReleaseCapture()- funktiolla. Hyvä paikka kaapata ja vapauttaa hiiri on hiiripainikkeen alas painamisen ja vapauttamisen yhteydessä. Muuta siis yhä listauksen 8.3 ohjelmaa hyödyntäen OnLButtonDown()-käsittelijääsi seuraavasti: void CMouseMsgDlg::OnLButtonDown(UINT nflags, CPoint point) { SetCapture(); CDialog::OnLButtonDown(nFlags, point); } Painaessasi nyt hiiren vasenta painiketta hiiri kaapataan sovellusikkunaasi. Voit vapauttaa kaapatun hiiren kutsumalla ReleaseCapture()-funktiota OnButtonUp()-käsittelijäfunktiosta näin: void CMouseMsgDlg::OnLButtonUp(UINT nflags, CPoint point) { ReleaseCapture(); CDialog::OnLButtonUp(nFlags, point); } Koosta ja aja ohjelmasi nämä muutokset tehtyäsi. Ajettaessa huomaat, että painamalla hiiren painikkeen alas sovellusikkunassa saat silmät seuraamaan hiiriosoitinta myös ikkunan ulkopuolelle. Tämä tarkoittaa, että saat yhä WM_MOUSEMOVE-sanomia, vaikkei hiiriosoitin olekaan sovellusikkunasi päällä. Huomaa myös, että koordinaatit muuttuvat negatiivisiksi ikkunasi yläpuolella ja vasemmalla puolen, koska hiiren paikka ilmaistaan suhteessa ikkunan vasempaan yläkulmaan. Jos vapautat hiiren painikkeen, kutsutaan ReleaseCapture()- funktiota ja hiiren toiminta palautuu normaaliksi eli kaappausdraama on päättynyt. Osumatestauksen asettaminen Usein vapaan hiiren liikkeen käyttöön liittyy kyky tutkia ilman hankalaa painikkeiden käyttöä, onko hiirtä napautettu tietyllä alueella. Jos esimerkiksi haluat muuttaa esimerkkiohjelmassamme silmien väriä

OSA II LUKU 8 175 niitä napauttamalla, asetat ikkunalle osumatestin (hit test). Osumatestaus yksinkertaisesti tarkistaa, onko piste tietyn suorakulmion sisällä. Aivan ensin joudut tallettamaan viimeisimmän napautuksen paikan. Tämä on syynä OnLButtonDown()-funktiolle välitetyn point-parametrin asettamiseen jäsenmuuttujaan: void CMouseMsgDlg::OnLButtonDown(UINT nflags, CPoint point) { SetCapture(); M_ptButton = point; // ** talleta saadut koordinaatit } Muista lisätä CMouseMsgDlg-luokkaan CPoint-tyyppinen m_ptbutton-jäsenmuuttuja. Tämä käy samoin kuin hieman aiemmin lisäämäsi m_ptmouse-muuttujan lisääminen. Muuttujan tyyppi on yhä CPoint, mutta muuta aiempia ohjeita seuratessasi muuttujan nimeksi nyt m_ptbutton. Viimeisin napautuspaikka on nyt siis talletettu ja voit tarkistaa, onko m_ptbutton jommankumman silmän alueella muuttamalla hieman OnPaint()-käsittelijää // ** Draw the eye white kommentin jälkeen, näin: // ** Draw the eye white if(rceye.ptinrect(m_ptbutton)) dc.selectstockobject(gray_brush); else dc.selectstockobject(white_brush); CRect-luokan jäsenfunktio PtInRect() palauttaa TRUE, kun syötetty CPoint-parametri (tässä m_ptbutton) on kyseisen (rceye) nelikulmion sisäpuolella. Jos piste on silmän alueella, käytetään harmaata väriä (GRAY_BRUSH) tavallisen valkoisen (WHITE_BRUSH) sijaan ja silmä esitetään harmaana. Koosta ja aja sovelluksesi tehtyäsi nämä muutokset ja huomaat, että silmään napauttamalla saat sen harmaaksi. Jos tämän jälkeen napautat toista silmää, se harmaantuu ja entinen valkaistuu ja silmien ulkopuolella napauttaminen valkaisee molemmat silmät, koska napautuspiste ei ole kummankaan nelikulmion sisällä. Osoittimen kuuma piste Ainoastaan yksi osoittimen kuvapiste edustaa hiiren sijaintia. Tätä kutsutaan kuumaksi pisteeksi (hotspot) ja yleensä se on nuoliosoittimen päässä. Kuuman pisteen sijainti voidaan määrittää osoitinta luodessa. Osumakohdan tarkistus palauttaa arvon TRUE, kun tämä kuuma piste on tutkittavalla alueella.

176 Valintaikkunat ja kontrollit KUVA 8.3 Osumatestauksella saadaan silmä harmaaksi, jos napautuspiste sattuu sen sisäpuolelle. KATSO MYÖS Lisää oppia järjestelmän siveltimistä (stock brush) luvussa 16. CRectTracker-luokan käyttö Olet varmaan käyttänyt joissain sovelluksissa hiirellä piirrettävää nelikulmiota valitsemaan monta kappaletta yhtä aikaa. Tätä toimintaa kutsutaan suorakulmion selvittämiseksi (rectangle tracking) ja se on helppo toteuttaa CRectTracker-luokan avulla. Tämä luokka käyttää omaa hiiren kaappaamista, sallii käyttäjän valita alueen ja antaa sovelluksesi tutkia, ovatko määrätyt pisteet käyttäjän valitseman suorakulmio sisällä. Voit lisätä sovellukseesi CRectTracker-luokan, jotta voisit valita toisen silmistä tai molemmat piirtämällä niiden ympärille suorakulmion ja lopuksi tutkia sovelluksessa, onko kumpikaan silmistä tuon suorakulmion sisällä. Lisää sovelluksesi CMouseMsgDlg-luokkaan CRectTrackerjäsenmuuttuja nimeltä m_recttracker normaaliin tapaan. Aivan aluksi joudut alustamaan valintasuorakulmion (rect tracker) paikan, koon ja sen tyylimäärittelyt. Voit lisätä seuraavan koodin CMouseMsgDlg-luokan muodostinfunktion CMouseMsgDlg::CMouseMsgDlg()-otsikkoon: CMouseMsgDlg::CMouseMsgDlg(CWnd* pparent /*=NULL*/) : CDialog(CMouseMsgDlg::IDD, pparent),

OSA II LUKU 8 177 m_recttracker(crect(0,0,0,0), // ** Valintasuorakulmion koko ja paikka aluksi CRectTracker::hatchedBorder + // esitetään katkoviivalla CRectTracker::resizeOutside) // ja suorakulmiossa esitetään kahvat koon muuttamista varten Pääset tähän funktioon kaksoisnapauttamalla CMouseMsgDlg-luokan alta löytyvää CMouseMsgDlg()-jäsenfunktiota projektin työtilaikkunan ClassView-ruudussa. Koodin kommenttienkin mukaan m_recttracker-jäsenmuuttujan alkuperäiseksi kooksi ja paikaksi alustetaan nolla (joten mitään ei vielä ole valittu). Toinen parametri CRectTracker-muodostimelle on tyylimäärittely, jossa voidaan käyttää kaikkia taulukossa 8.4 mainittujen lippujen yhdistelmiä. Tyyli CRectTracker::hatchedBorder piirtää paksun harmaan viivan valintasuorakulmiolle ja tämä yhdistetään vielä tyyliin CRectTracker::resizeOutside, jolloin suorakulmion kokoa muutettaessa käytetyt kahvat sijaitsevat sen ulkopuolella (estää ongelmat hyvin pienillä suorakulmioilla). TAULUKKO 8.4 CRectTracker-luokan tyylimäärittelyliput Tyyli CRectTracker::solidLine CRectTracker::dottedLine CRectTracker::hatchedBorder CRectTracker::hatchInside CRectTracker::resizeInside CRectTracker::resizeOutside Kuvaus Piirtää valintasuorakulmion yhtenäisellä viivalla Piirtää valintasuorakulmion katkoviivalla Piirtää valintasuorakulmion paksulla harmaalla viivalla Esittää koko valitun alueen harmaalla Koonmuutoskahvat sijaitsevat suorakulmion sisäpuolella Koonmuutoskahvat sijaitsevat suorakulmion ulkopuolella Suorakulmiolla valitseminen (rubber-banding) tehdään yleensä hiiren vasemmalla painikkeella, joten valitseminen kannattaakin käynnistää OnLButtonDown()-käsittelijästä. Koko valintatapahtuma tehdään CRectTracker-luokan TrackRubberBand()-jäsenfunktiolla. Voit lisätä tämän OnLButtonDown()-käsittelijääsi seuraavasti:

178 Lassoamisen räätälöinti CRectTracker-luokan käyttäytymistä voidaan muuttaa johtamalla oma luokka CRectTrackerluokasta. Luokassa on useita korvattavissa olevia virtuaalifunktioita, kuten piirtämiseen liittyvä DrawTrackerRect(). Näissä voit toteuttaa valitun alueen muuttuessa tarvittavan oman piirtokoodin. Valintaikkunat ja kontrollit void CMouseMsgDlg::OnLButtonDown(UINT nflags, CPoint point) { m_recttracker.trackrubberband(this, point, TRUE); CDialog::OnLButtonDown(nFlags, point); } Kuten huomaat, TrackRubberBand()-funktio käyttää kolmea parametriä. Ensimmäinen näistä osoittaa ikkunaan, jossa valinta tehdään. Sovelluksessamme tämä on sovellusikkunamme, joten parametrinä voidaan käyttää C++:n this-osoitinta, joka osoittaa itse CMouseMsgDlg-olioon (joka on johdettu CWnd-luokasta ja on siksi myös ikkunaolio). Toinen parametri on valintasuorakulmion aloituspiste. Tässä voit käyttää hiiren napautuspistettä. Kolmanneksi parametriksi valitaan TRUE, jolloin käyttäjä voi valita suorakulmion myös napautuspisteen yläpuolelta ja vasemmalta puolen. FALSE-parametrillä valinta voitaisiin tehdä napautuspisteestä alkaen vain alaspäin ja oikealle. Aiemmin OnLButtonDown()-käsittelijässä oli mukana SetCapture()- funktiokutsu, joka on nyt poistettu, koska suorakulmion valintatoiminto (rect tracker) kaappaa itse hiiren ja tällöin oma SetCapture()-funktio vain sotkisi sitä. Muista myös poistaa vastaava ReleaseCapture()-kutsu OnLButtonUp()-käsittelijästä: void CMouseMsgDlg::OnLButtonUp(UINT nflags, CPoint point) { CDialog::OnLButtonUp(nFlags, point); } Lopuksi joudut muokkaamaan vielä silmän piirtokoodista osumatestausta käyttämään tutkittavana kohteena suorakulmiota eikä yksittäistä pistettä. CRectTracker-luokalla on oma HitTest()- funktionsa, jolle syötetään tutkittavaksi CPoint-olio: // ** Draw the eye white if(m_recttracker.hittest(rceye.centerpoint())!=crecttracker::hitnothing) dc.selectstockobject(gray_brush); else dc.selectstockobject(white_brush);

Kun HitTest()-funktiolle syötetään rceye.centerpoint(), kysytään, onko jommankumman silmän keskipiste valitun suorakulmion alueella. HitTest()-funktio palauttaa arvon CRectTracker::hitNothing (eli 1), ellei syötetty piste ole valitun alueen sisällä. Jos piste on valitulla alueella, palautetaan useita arvoja, jotka määrittävät pisteen sijaintia alueessa. Arvo voi olla periaatteessa mikä tahansa taulukon 8.5 määrittelemistä arvoista, vaikka se yleensä onkin CRectTracker::hitMiddle, kun piste oli alueella ja CRectTracker::hitNothing, ellei ollut. TAULUKKO 8.5 CRectTracker-luokan HitTest()-funktion palauttamat arvot Paluuarvo Arvo Tarkoittaa CRectTracker::hitNothing -1 Piste ei ollut alueella CRectTracker::hitTopLeft 0 Piste on suorakulmion vasemmassa yläosassa CRectTracker::hitTopRight 1 Piste on suorakulmion oikeassa yläosassa CRectTracker::hitBottomRight 2 Piste on suorakulmion vasemmassa alaosassa CRectTracker::hitBottomLeft 3 Piste on suorakulmion vasemmassa alaosassa CRectTracker::hitTop 4 Piste on suorakulmion yläosassa CRectTracker::hitRight 5 Piste on suorakulmion oikeassa osassa CRectTracker::hitBottom 6 Piste on suorakulmion alaosassa CRectTracker::hitLeft 7 Piste on suorakulmion vasemmassa osassa CRectTracker::hitMiddle 8 Piste on jossain suorakulmion keskiosassa OSA II LUKU 8 179 Kun käännät ja ajat ohjelmasi näiden muutosten jälkeen, voit valita hiiren vasemmalla painikkeella suorakulmion muotoisen alueen ikkunasta ja muuttaa sen halutun kokoiseksi ennen kuin vapautat hiiren painikkeen. Jos jommankumman silmän keskipiste on valitulla alueella, kyseinen silmä valitaan ja esitetään harmaana (kuva 8.4).

180 Valintaikkunat ja kontrollit KUVA 8.4 Suorakulmion muotoisen alueen valitseminen ikkunasta CRectTracker-luokan avulla.