/******************************************************************** MODULE: optdlg.c PURPOSE: Dialogi- eli keskusteluikkunan kontrollien käsittely Editor: Sirpa Pasanen 20.3.1994 Vesa Lappalainen korjauksia 30.10.1994 (merk. vl-94) + IDOK käsitellään "hyvänä" viestinä automaattisesti + kääntyy STRICT-asetuksen kanssa + koID2 saa olla 0 jos "ryhmässä" vain yksi vekotin Vesa Lappalainen korjauksia 11.8.1995 + tyyppi T_byte pienien ON/OFF tietojen tallentamiseen + HWND pois aliohjelmista Talleta ja Alusta ja niiden nimien muutos AlustaOptioDlg => AlustaOptiot TalletaOptioDlg => TalletaOptiot ********************************************************************* ------------------ Kirjaston sisältö: ------------------ Tässä kirjastossa on funktioita, joiden avulla voidaan A) saada keskusteluikkunaan annetut optioiden valintatiedot kut- suvan ohjelman varaamaan arvotietueeseen, B) alustaa arvotietue ini-tyyppisesta tiedostosta ja C) tallettaa tämä tietue ini-tyyppiseen tiedostoon tulevaa käyttöä varten. Käytettävissä olevat funktiot: 1) dialogin käsittelyn hoito int OptioDialogi( HWND, DialogiParam * ); 2) arvotietueen alustus ini-tiedostosta BOOL TalletaOptiot( DialogiParam * ); 3) arvotietueen tietojen talletus ini-tiedostoon BOOL AlustaOptiot( DialogiParam * ); 4) dialogin käsittely ini-tiedostoa käyttäen int OptioDialogiIni( HWND, DialogiParam * ); ----------------- Kirjaston käyttö: ----------------- Funktioiden käyttämiseksi on ohjemoijan tehtävä ohjelmaansa seuraa- vat toimenpiteet: 1) Luotava dialogi resurssieditorilla (tai tekstieditorilla re- surssieditorin muotoon, jos joku niin haluaa!) 2) Varattava dialogin kontrollien arvoille tietue ja alustettava se jollain tavoin, esim. AlustaOptioDialogi-funktion avulla ini-tiedostosta, johon tiedot on aiemmin viety funktiolla TalletaOptioDialogi. 3) Varattava ja alustettava kontrollien valintalistojen vaihto- ehtojen merkkijono-osoitintaulukot 4) Kuvattava dialogin kontrollit taulukkona KontrolliKuvaus-tie- tueen mukaisesti: int koID1 ryhmän 1. kontrollin tunnus int koID2 ryhmän viim. kontr. tunnus KontrolliTyyppi koTyyppi kontrollin tyyppi char *koArvonNimi arvon nimi ini-tiedostossa int koArvonPaikka arvon paikka optiotietueella int koArvonKoko arvon koko - " - TietoTyyppi koArvonTyyppi arvon tyyppi - " - int koMaxlkm listan alk. MAX-määrä tai valintaruudun tilojen lkm tai painikkeen palauttama arvo char **koListaAlkio listan valintalistan arvot 5) Kuvattava dialogi DialogiParam-tietueen mukaan: char *odNimi dialogin res.kuvauksen nimi DialogiTyyppi odTyyppi dialogin tyyppi KontrolliKuvaus *odKuvaus kontrollien kuvaustaulukko char *odTiedosto talletustiedoston polku char *odKappale ini-tiedoston kappaleen otsake void *odArvot dialogin arvotietue int odArvotKoko arvotietueen koko tavuina 6) Hoidettava dialogin tietojen käsittely OptioDialogi- tai OptioDialogiIni-funktiota kutsuen. 7) Lisättävä projektiin tiedostot optdlg.c ja mdialog.c sekä kut- suvaan ohjelmaan tiedostot optdlg.h ja mdialog.h. 8) Sen jälkeen kun vapaiden (modeless) dialogien käsittely on to- teutettu ja kun niitä halutaan käyttää, tarvitaan IsModelessMessage-funktion kutsu viestisilmukkaan ja FreeAllModeless-funktion kutsu ohjelman loppuun. ------------------- Esimerkki käytöstä: ------------------- 1) Resurssieditorilla on määritelty dialogi "Optiot2": |---|---------------------------------------------| | - | Optiot 2 | |---|---------------------------------------------| | | | |------------| |--Ruudut---| Yläraja | | | Kytkimet | | | |------------| | | | | | | |____________| | | | O Eka | | | | 80 |_| | | | | | [] Alku | | 100 | | | | | O Toka | | | | 150 | | | | | | | | | 250 | | | | | O Kolkki | | [] Loppu | | 500 | | | | | | | | | 680 | | | | |____________| |___________| |________|_| | | | | | | |----------------------------| | | |Terveiset monirivisellä | | | |muokattavalla tekstikentällä| |------| | | | | | Pois | | | | | |______| | | |____________________________| | | | |-------------------------------------------------| 2) Määritelty, varattu ja alustettu kontrollien arvotietue "optioArvot2": /* Optiot2-dialogin tietuekuva: * typedef struct { int kytkin; /* valintakytkinsarja: monesko valittu * char alku; /* valintaruutu: 0=ei alkutekstiä, * /* 1=lyhyt alkuteksti, * /* 2=pitkä alkuteksti * char loppu; /* valintaruutu: 0=ei lopputekstiä, * /* 1=lyhyt lopputeksti, * /* 2=pitkä lopputeksti * int yraja; /* yhd.lista: valittu arvo * char terve[115]; /* muokattava tekstikenttä: annettu teksti* } OA2; OA2 optioArvot2 = { 1, '1', '0', 100, "" }; 3) Varattu ja alustettu yhdistelmälistakontrollin "Yläraja" (IDC_YRAJA) valintalistan arvot (eli vaihtoehdot, joista valitaan): char *rajat[10] = { "80","100","150","250","500","680",NULL }; 4) Kuvattu kontrollit taulukkona: KontrolliKuvaus kontr2[] = { /* ryhmän ryhmän kontr. arvon arvon max val. * /* ensimm. viimeinen tyyppi nimi,paikka,koko tyyppi lkm lista* /*----------------------------------------------------------------* {IDC_EKA, IDC_KOLKKI,C_arbu, N_P_K(OA2,kytkin),T_int, 0, NULL }, {IDC_ALKU, IDC_ALKU, C_acbo, N_P_K(OA2,alku), T_char, 3, NULL }, {IDC_LOPPU, IDC_LOPPU, C_acbo, N_P_K(OA2,loppu), T_char, 3, NULL }, {IDC_YRAJA, IDC_YRAJA, C_cobo, N_P_K(OA2,yraja), T_int, 10,rajat}, {IDC_TERVE, IDC_TERVE, C_edte, N_P_K(OA2,terve), T_str, 0, NULL }, {IDC_POIS, IDC_POIS, C_pubu, NULL, 0, 0, T_int, 6, NULL }, {0, 0, 0, NULL, 0, 0, 0, 0, NULL } }; 5) Kuvattu dialogi: DialogiParam optioDlgParam2 = { "Optiot2", /* dialogin nimi * D_modal, /* dial. tyyppi: hallitseva * kontr2, /* kontrollien kuvaustaulukko* ".\\testi3.ini", /* talletustiedosto * "Optiot2", /* ini-tiedoston kappale * &optioArvot2, /* arvotietue * sizeof( OA2 ) /* arvotietueen koko * }; * 6) Alustettu arvotietue työhakemiston testi3.ini-tiedostosta kutsulla if ( !AlustaOptiot( &optioDlgParam2 ) ) MessageBox( hWnd, "Arvotietueen haku ei onnistu",... hoidettu käsittely kutsulla ipal = OptioDialogi( hWnd, &optioDlgParam2 ); ja talletettu arvot kutsulla if ( !TalletaOptiot( &optioDlgParam2 ) ) MessageBox( hWnd, "Arvotietueen vienti ei onnistu",... Toteutuksen jälkeen testi3.ini-tiedostossa on rivit: [Optiot2] kytkin=1 alku=0 loppu=2 yraja=250 terve=Terveiset muokattavalla tekstikentällä ON HELPPO LÄHETTÄÄ KAIKILLE ------------------------- Kontrollien kuvaamisesta: ------------------------- Jokaiselle käsiteltävälle kontrollille määritellään KontrolliKuvaus- tietueen mukaiset tiedot, jotka on järjestettävä taulukoksi. Vain määriteltyjen kontrollien viestejä otetaan vastaan ja arvoja tallete- taan tai alustetaan. Kuvausten järjestys taulukossa määrää kontrol- lien käsittelyjärjestyksen funktioissa, joten eniten viestejä saavat kontrollit kannattaa sijoittaa taulukon alkuun ja vähiten käytetyt taulukon loppuun. 1) koID1 ilmaisee kontrollille resurssieditorissa annetun numeerisen tunnisteen. Kun on kyse valintakytkimistä, tämä on koko ryhmän 1. kytkimen tunnus. Tällöin koko ryhmän valintakytkimet on nimettävä resurssieditorissa peräkkäisillä numeroarvoilla! 2) koID2 ilmaisee valintakytkinten ryhmän viimeisen kontrollin. Valintakytkinryhmä saa arvokseen valitun kytkimen järjestysluvun ryhmässä ts. jos ryhmän 1. kytkin valitaan, ryhmän arvo on 0, ja jos 2. valitaan, niin arvoksi saadaan 1, jne. ( Kaikille muille kontrollityypeille koID2:n arvoksi on asetettava koID1:n arvo ts. arvo 0 EI toimi oikein! ) Nyt toimii (vl-94). 3) koTyyppi kuvaa kontrollin tyypin ja voi arvoltaan olla joku seu- raavista: C_arbu valintakytkin, automaattinen C_rabu valintakytkin, ei automaattinen C_acbo valintaruutu, automaattinen C_chbo valintaruutu, ei automaattinen C_edte muokattava tekstikenttä C_libo valintalista C_cobo yhdistelmälista C_pubu painike C_stte tekstikenttä A) Valintakytkimien ja -ruutujen tapauksessa automaattiset ja ei-automaattiset on määriteltävä erikseen, koska niiden käsitte- lyssä ohjelmallisesti on vähän eroja, vaikka käyttäjän kannalta ne ovat samanlaisia. B) Valintaruudut voivat olla 2- tai 3-tilaisia. Jos tilojen luku- määrää ei ole annettu kontrollin kuvauksessa, niin oletetaan ti- lojen määräksi 2. Tilojen arvot talletetaan sellaisinaan (0,1,2). C) Muokattava tekstikenttä voi olla yksi tai monirivinen. Kenttään voi syöttää Windowsin rajoittaman määrän merkkejä, mutta vain vastaanottavan arvotietueen kentän pituuden verran syötetyn tiedon alusta alkaen talletetaan. Syöttökentän pituutta ei ole rajoitettu ohjelmallisesti, koska se näyttää johtavan siihen, että aiemmin annettua tietoa ei voi myöhemmin pidentää, vaikka vastaanottavan kentän pituus sen sallisikin! Myös salasanan syöttö tähän kenttä- tyyppiin toimii. D) Valintalistan vaihtoehtojen pituus rajoitetaan alustusvaiheessa vastaanottavan kentän mittaiseksi, jolloin ne näkyvät sellaisina, kuin tallentuvat arvotietueelle. E) Yhdistelmälistan vaihtoehtojen pituus rajoitetaan, samoin muo- kattavan tekstikentän pituus, vaikka silloin esiintyy em. merkki- jonon jatkamisongelma. F) Painikkeelle määritelty arvo palautetaan paluukoodissa, mutta se sijoitetaan myös arvotietueelle, jos sille on määritelty sinne paikka ja koko. G) Tekstikenttä on kontrolli, jonka arvoa ei käyttäjä voi muuttaa ts. sille ei vastaanoteta viestejä, mutta se alustetaan dialogin luonnin yhteydessä, joten sen avulla voidaan antaa käyttäjälle muuttuvia tietoja. 4) koArvonNimi on osoite merkkijonoon, jossa on kontrollin arvon nimi ini-tiedostossa. Nimi voi olla mikä tahansa haluttu merkkijono tai NULL, jos tietoa ei haluta tallettaa. Nimeksi voidaan N_P_K- makrolla asettaa ohjelmassa määritellyn arvokentän nimi. 5) koArvonPaikka ilmaisee, monenko tavun päässä arvotietueen alusta kontrollin antama arvo sijaitsee. N_P_K- ja P_K-makrojen avulla tämä tieto määräytyy käännösaikana arvotietueen kuvauksen mukaan. 6) koArvonKoko kertoo, montako tavua arvolle on varattu tilaa arvo- tietueella. Sen voi N_P_K- ja P_K-makrojen avulla laskettaa esikääntäjällä arvon kenttämäärityksen perusteella. 7) koArvonTyyppi voi olla jokin seuraavista: T_none arvoa ei palauteta arvotietueella T_int kokonaisluku T_char merkki (0 => '0') T_str merkkijono T_byte yhden tavun kokonaisluku 0-255, tyypiksi tietueessa annetaan char (0 => 0) 8) koMaxlkm kertoo valinta- ja yhdistelmälistojen tapauksessa listalla olevien vaihtoehtojen määrän, valintaruuduille niiden tilojen määrän ja painikkeille palautettavan ja mahdollisesti talletettavan paluuarvon, jonka on oltava positiivinen eli > 0. Muiden kontrollityyppien suhteen tiedolla ei ole merkitystä, joten se olkoon 0. 9) koListaAlkio on osoite osoitetaulukkoon, josta löydetään valin- ta- tai yhdistelmälistan vaihtoehtoja kuvaavat merkkijonot. Muille kontrollityypeille määritellään arvoksi NULL. ---------------------- Dialogin kuvaamisesta: ---------------------- 1) odNimi on osoite dialogin nimeen, joka on juuri resurssieditorissa dialogille annettu nimi 2) odTyyppi on dialogin tyyppi, joka toistaiseksi voi saada vain arvon D_modal, joka merkitsee hallitsevaa dialogia, jossa annetut tiedot palautetaan kutsuvalle ohjelmalle dialogin lopetuksen jälkeen. 3) odKuvaus ilmaisee kontrollien kuvaustaulukon osoitteen 4) odTiedosto on talletustiedoston polun kertovan merkkijonon osoite 5) odKappale sisältää osoitteen merkkijonoon, joka ilmaisee, minkä otsakkeen jälkeen arvotietueen tiedot ini-tiedostoon talletetaan 6) odArvot sisältää arvotietueen osoitteen 7) odArvotKoko on arvotietueen koko tavuina Kaikki tiedot ovat käsittelyn kannalta olennaisen tärkeitä ja eh- dottoman pakollisia. Ne ohjaavat modulien koko toimintaa yhdessä kontrollien kuvausten kanssa. ------------------------------------------ int OptSetNoMessage(int i); ------------------------------------------ Asetetaan virheilmoitusten näyttö pois päältä (i=1, oletus) tai päälle (i=0) ------------------------------------------ int OptioDialogi( HWND, DialogiParam * ) ------------------------------------------ Parametrit: 1) isäikkunan kahva 2) dialogi-ikkunan kuvaustietueen osoitin Paluukoodi: P_ei_tot vapaita dialogeja ei vielä käsitellä P_hairio jokin epäonnistuminen sattunut P_stdPainike Esc tai Enter painettu kok.luku lopetukseksi painetun painikkeen arvo Hoitaa hallitsevan (modal) dialogin käsittelyn kontrollien kuvaus- ten mukaan: -luo dialogin parametrinä annetun ikkunan lapseksi -alustaa määritellyt kontrollit arvotietueelta, kun dialogi saa WM_INITDIALOG-viestin -käsittelee määriteltyjen kontrollien viestit seuraavasti: valintakytkimille BN_CLICKED valintaruuduille BN_CLICKED muokattaville tekstikentille EN_KILLFOCUS valintalistoille LBN_KILLFOCUS yhdistelmälistoille CBN_KILLFOCUS painikkeille BN_CLICKED ja jättää muut viestit oletuskäsittelijälle -lopettaa dialogin, kun jotain painiketta on painettu ja palauttaa painetulle nappulalle kuvaustaulukossa määritellyn arvon -tallettaa määriteltyjen kontrollien muuttuneet arvot arvotietu- eelle, jos dialogia ei lopeteta keskeytysnäppäimen painallukseen ts. jos dialogille ei tule IDCANCEL-viestiä lopetukseksi eikä sitä suljeta ohjausvalikkoruudun kautta. --------------------------------------------- BOOL TalletaOptiot( DialogiParam * ) --------------------------------------------- Parametrit: 1) dialogi-ikkunan kuvaustietueen osoitin Paluukoodi: TRUE talletus tehty onnistuneesti kontrollien kuvausten mu- kaan FALSE talletus ei onnistunut joko puutteellisesti määritelty- jen dialogin kuvaustietojen tai tiedoston kirjoituksessa sattuneen häiriön vuoksi Tallettaa kontrollien kuvaustaulukon mukaan kontrollien arvot Dialogi- Param-tietojen ilmaisemaan ini-tiedostoon. -------------------------------------------- BOOL AlustaOptiot( DialogiParam * ) -------------------------------------------- Parametrit: 1) dialogi-ikkunan kuvaustietueen osoitin Paluukoodi: TRUE alustus onnistunut kontrollien kuvausten mukaan FALSE alustus ei onnistunut puutteellisten dialogin kuvaus- tietojen vuoksi Hakee DialogiParam-tietojen ilmaisemasta ini-tiedostosta kontrollien kuvaustaulukon mukaan tiedot arvotietueelle. Jos jollekin kontrollille ei löydy arvoa, niin sen paikka arvotietueella alustetaan nollaksi, jos ko. tiedon tyyppi on kokonaisluku tai merkki, ja tyhjäksi merkki- jonoksi, jos tiedon tyyppi on merkkijono. --------------------------------------------- int OptioDialogiIni( HWND, DialogiParam * ) --------------------------------------------- Parametrit: 1) isäikkunan kahva 2) dialogi-ikkunan kuvaustietueen osoitin Paluukoodi: P_ei_tot vapaita dialogeja ei vielä käsitellä P_hairio jokin epäonnistuminen sattunut P_stdPainike Esc tai Enter painettu kok.luku lopetukseksi painetun painikkeen arvo Hoitaa dialogin käsittelyn alustaen kontrollit ensin määritellystä ini-tiedostosta ja tallettaen annetut arvot lopuksi samaan tiedostoon. Suorittaa tehtävät edellä mainittuja funktioita käyttäen. ----------------------------------------------------------------------------- int OptioDialogiJaIni(HWND hWnd, const far DialogiParam *odParam ,int save); ----------------------------------------------------------------------------- Kuten edellä, mutta voidaan valita luetaanko ennen save == OPT_READ, talletetaanko jälkeenpäin save == OPT_SAVE vaiko molemmat save == OPT_READ | OPT_SAVE. ----------------------------------------------------------------------------- tWndMsgHandlerProc SetOptPreHandler(tWndMsgHandlerProc NewPreHandler) ----------------------------------------------------------------------------- Tällä voidaan asettaa uusi käsittelijä dialogin varsinaisen käsittelijän eteen. Aliohjelman pitää palauttaa -1, jos ei ole käsitellyt viestiä. ------------------------- Muiden kielien käyttö: ------------------------- - kutsutaan ennen 1. käyttöä: SetOptPreHandler(TranslateHandler); ------------------------- Puutteita ja rajoituksia: ------------------------- -Vain hallitsevat dialogit on käsitelty ja nekin vain siten, että arvot palautetaan kutsuvalle modulille vasta dialogin sulkemisen jälkeen. (Tällöin tosin käyttäjän on mahdollista perua tekemänsä muutokset.) Vapaiden dialogien käsittely edellyttää muutoksia sekä optdlg- että mdialog-kirjastoihin staattisten muuttujien kä- sittelyn suhteen. -Talletettavan arvon tietomuodoista on käsitelty vain kokonaisluku, merkki ja merkkijono. -Syötetyn tiedon oikeellisuutta ei testata, kun se muutetaan kokonaisluvuksi. Siitä seuraa, että jos syötetty tieto ei ollut numeerinen, saadaan arvoksi 0 ja arvoltaan liian suuresta kokonais- lukutiedosta negatiivinen ( kokonaisluvun pituus on rajoitettu 5 merkkiin). -Dialogin menuja ei käsitellä, vaikka menussa voitaisiin ajatella olevan arvojen talletuksen ja alustuksen. -Yhdistelmälistaan ei lisätä uusia syötettyjä vaihtoehtoja, vaikka ne sinne mahtuisivat. Jos kutsuva moduli varaisi niille muistipai- kat valmiiksi, olisi lisäys yksinkertainen, koska ei syntyisi on- gelmaa dynaamisesti varatun muistin vapauttamisesta. -Kaikkia resurssieditorin sallimia kontrollien ominaisuuksia ei ole huomioitu, esim. itse muotoiltavia painikkeita tai listoja. -Jos dialogi alkaa valintakytkinryhmällä, jonka 1. kontrolli mää- ritellään dialogin 1. "tabstop"-kontrolliksi, muuttuu ko. ryhmän arvoksi 0 eli ryhmän 1., jos ryhmässä ei käydä suorittamassa valintaa! -Kontrollin ja sen arvokentän tyypit tulisi voida automaattisesti päätellä resurssitiedostosta ja arvotietueen määrittelystä. /********************************************************************/ /********************************************************************/ #include #include #include #include #include #include #include #include "optdlg.h" #include "mdialog.h" #define Uchar unsigned char /********************************************************************/ /* Dialogi-ikkunan viestien käsittelyfunktioiden määrittely */ typedef BOOL (*DMSGHANDLER)(HWND,UINT,WPARAM,LPARAM); typedef struct { /* funktiotaulukon tietueessa: */ UINT message; /* - viestin tunnus */ DMSGHANDLER handler; /* - hoitava funktio */ } DMSGEntry; /********************************************************************/ /* Funktioiden staattiset muuttujat */ static const far DialogiParam *pDlgPar = NULL; static const far KontrolliKuvaus *pKonKuv = NULL; static char *pTemArv = NULL; static KontrolliKuvaus kIDOK = {IDOK,IDOK,C_pubu,NULL,0,0,T_int,IDOK,NULL }; /********************************************************************/ /* */ /* DIALOGIN KÄSITTELY */ /* */ /********************************************************************/ /********************************************************************/ /* Sisäisiä apufunktioita */ /********************************************************************/ /********************************************************************/ static int OptNoMessage = 1; int OptSetNoMessage(int i) { int old = OptNoMessage; OptNoMessage = (i != 0); return old; } /********************************************************************/ static int OptMessageBox(HWND hWnd, const char *text, const char *title, UINT mode) { if ( OptNoMessage ) return 0; return MessageBox(hWnd,text,title,mode); } /********************************************************************/ static int arvokentanPituus( void ) { /* Vastaanottavan kentän kapasiteetti merkkeinä */ int ret; char s[30]; switch( pKonKuv->koArvonTyyppi ) { case T_byte: case T_char: ret = sizeof( char ); break; case T_int: ret = strlen( itoa( INT_MAX, s, 10 ) ); break; case T_str: ret = pKonKuv->koArvonKoko - 1; break; } return ret; } /********************************************************************/ static char *varaaMerkkijono( HWND hWnd, int pit ) { /* Tilapäisalue merkkijonon käsittelyyn */ char *ret; ret = malloc( pit ); if ( !ret ) { OptMessageBox( hWnd, "Aluevaraus ei onnistu", "Optiodialogi", MB_APPLMODAL | MB_ICONHAND | MB_OK ); } return ( ret ); } /********************************************************************/ static int kytkinTietueelta( void ) { /* Valintakontrollin kokonaislukuarvo tietueelta */ char s[30]; int ret; if ( pKonKuv->koArvonKoko > 0 ) {/* vain, jos tieto on olemassa */ switch ( pKonKuv->koArvonTyyppi ) { case T_char: s[0] = *( pTemArv + pKonKuv->koArvonPaikka ); s[1] = NULL; ret = atoi( s ); break; case T_byte: ret = *( (Uchar *)( pTemArv + pKonKuv->koArvonPaikka ) ); break; case T_int: ret = *( (int *)( pTemArv + pKonKuv->koArvonPaikka ) ); break; case T_str: sscanf( pTemArv + pKonKuv->koArvonPaikka, "%d", &ret ); break; } } else ret = 0; return ret; } /********************************************************************/ static char *tekstiTietueelta( HWND hDlg, char *pmja ) { /* Tekstikontrollin merkkijono tietueelta */ #pragma argsused char *ret; int i; if ( pKonKuv->koArvonKoko > 0 ) {/* vain, jos tieto on olemassa */ switch ( pKonKuv->koArvonTyyppi ) { case T_char: pmja[0] = *( pTemArv + pKonKuv->koArvonPaikka ); pmja[1] = NULL; ret = pmja; break; case T_byte: i = (int)*( (Uchar *)(pTemArv + pKonKuv->koArvonPaikka) ); itoa( i, pmja, 10 ); ret = pmja; break; case T_int: i = (int)*( (int *)(pTemArv + pKonKuv->koArvonPaikka) ); itoa( i, pmja, 10 ); ret = pmja; break; case T_str: ret = pTemArv + pKonKuv->koArvonPaikka; break; } } else ret = NULL; return ret; } /********************************************************************/ static void kytkinTietueelle( int karvo) { /* Valintakontrollin kokonaislukuarvo tietueelle */ char s[30]; if ( pKonKuv->koArvonKoko > 0 ) {/* vain, jos tiedolle on tilaa */ switch ( pKonKuv->koArvonTyyppi ) { case T_char: wsprintf( s, "%d", karvo ); *( pTemArv + pKonKuv->koArvonPaikka ) = s[0]; break; case T_byte: *( (Uchar *)( pTemArv + pKonKuv->koArvonPaikka ) ) = (Uchar)karvo; break; case T_int: *( (int *)( pTemArv + pKonKuv->koArvonPaikka ) ) = karvo; break; case T_str: wsprintf( s, "%d", karvo ); if ( (int)strlen( s ) > pKonKuv->koArvonKoko ) { s[ pKonKuv->koArvonKoko - 1 ] = NULL; strcpy( (pTemArv + pKonKuv->koArvonPaikka), s ); } break; } } } /********************************************************************/ static void tekstiTietueelle( char *pmja ) { /* Tekstikontrollin merkkijono tietueelle */ int i; if ( pKonKuv->koArvonKoko > 0 ) {/* vain, jos tiedolle on tilaa */ switch ( pKonKuv->koArvonTyyppi ) { case T_char: *( pTemArv + pKonKuv->koArvonPaikka ) = pmja[0]; break; case T_byte: i = atoi( pmja ); *( (Uchar *)( pTemArv + pKonKuv->koArvonPaikka ) ) = (Uchar)i; break; case T_int: i = atoi( pmja ); *( (int *)( pTemArv + pKonKuv->koArvonPaikka ) ) = i; break; case T_str: if ( (int)strlen( pmja ) > pKonKuv->koArvonKoko ) { *( pmja + pKonKuv->koArvonKoko - 1 ) = NULL; } strcpy( (pTemArv + pKonKuv->koArvonPaikka), pmja ); break; } } } /********************************************************************/ static BOOL merkkaaListaAlkio( HWND hDlg, KontrolliTyyppi kt ) { /* Valintalistan vaihtoehdon merkitseminen */ UINT viesti1, viesti2; int virhe, i=1; char *pmja, s[30]; switch ( kt ) { /* valinta- / yhdistelmälista? */ case C_libo: viesti1 = LB_FINDSTRING; viesti2 = LB_SETCURSEL; virhe = LB_ERR; break; case C_cobo: viesti1 = CB_FINDSTRING; viesti2 = CB_SETCURSEL; virhe = CB_ERR; break; } pmja = tekstiTietueelta( hDlg, s ); if ( pmja && *pmja ) { /* jos valinta on olemassa ja */ i = (int) SendDlgItemMessage( hDlg, pKonKuv->koID1, viesti1, -1, (LPARAM) ((LPSTR) pmja) ); if ( i != virhe ) { /* listalla, se korostetaan */ SendDlgItemMessage( hDlg, pKonKuv->koID1, viesti2, i, 0L ); } else i=0; /* valinta ei listalla */ } return i; } /********************************************************************/ static void alustaListaAlkiot( HWND hDlg, KontrolliTyyppi kt ) { /* Valintalistan alustus vaihtoehdoilla */ UINT viesti; int i, k; char **pla; switch ( kt ) { /* valinta- / yhdistelmälista? */ case C_libo: viesti = LB_INSERTSTRING; break; case C_cobo: viesti = CB_INSERTSTRING; break; } pla = pKonKuv->koListaAlkio; i = arvokentanPituus(); for ( k=0; *pla; pla++,k++ ) { /* lista-alkioiden pituuden */ if ( (int)strlen( *pla ) > i ) { /* rajoittaminen vastaanottavan */ *( *pla + i ) = NULL; /* kentän mukaan */ } /* listan alustus */ SendDlgItemMessage( hDlg, pKonKuv->koID1, viesti, k, (LPARAM) ((LPSTR) *pla) ); } return; } /********************************************************************/ static BOOL palautaArvotietue( HWND hDlg, int id ) { /* Saatujen optiovalintojen arvojen sijoitus kuts. modulille */ char *ret; switch ( pDlgPar->odTyyppi ) { case D_modal: /* viivästetty arvojen palautus */ // case D_modeless: if ( id != IDCANCEL ) {/* hyväksytyt arvot takaisin */ ret = memcpy( pDlgPar->odArvot, pTemArv, pDlgPar->odArvotKoko ); if ( !ret ) { OptMessageBox( hDlg, "Arvojen palautus ei onnistu", "Optiodialogi", MB_APPLMODAL | MB_ICONHAND | MB_OK ); } } if( pTemArv ) /* vapautetaan tilapäisalue */ free( pTemArv ); break; // case D_modal_auto: /* välitön arvojen palautus */ // case D_modeless_auto: // ret = pTemArv; // break; } return ( (BOOL) ret ); } /********************************************************************/ static char *varaaArvotietue( HWND hWnd ) { /* Tilapäisalue optioiden arvoille käsittelyn ajaksi */ char *ret; switch ( pDlgPar->odTyyppi ) { case D_modal: /* viivästetty arvojen palautus */ // case D_modeless: /* varataan tilapäisalue */ pTemArv = malloc( pDlgPar->odArvotKoko ); if ( pTemArv ) {/* edelliset arvot uudelle alueelle */ ret = (char *) memcpy( pTemArv, (char *)(pDlgPar->odArvot), pDlgPar->odArvotKoko ); if (!ret ) { OptMessageBox( hWnd, "Arvojen kopiointi ei onnistu", "Optiodialogi", MB_APPLMODAL | MB_ICONHAND | MB_OK ); return NULL; } } else OptMessageBox( hWnd, "Aluevaraus ei onnistu", "Optiodialogi", MB_APPLMODAL | MB_ICONHAND | MB_OK ); break; // case D_modal_auto: /* välitön arvojen palautus */ // case D_modeless_auto: // pTemArv = pDlgPar->odArvot; // break; } return ( pTemArv ); } /********************************************************************/ /********************************************************************/ /* Kontrollien viestinkäsittelyfunktiot */ /********************************************************************/ /********************************************************************/ static BOOL HANDLER_BN_Clicked( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) /* Valintakytkinten ja -ruutujen käsittely */ { #pragma argsused int i, j; UINT id = GET_WM_COMMAND_ID(wParam,lParam); switch ( pKonKuv->koTyyppi ) { case C_arbu: /* auto-valintakytkin */ /* arvo (monesko) talteen */ kytkinTietueelle( id - pKonKuv->koID1 ); return TRUE; case C_rabu: /* valintakytkin */ /* edellinen asetus pois päältä */ j = (int) *( (int *)( pTemArv + pKonKuv->koArvonPaikka ) ); SendDlgItemMessage( hDlg, pKonKuv->koID1+j, BM_SETCHECK, 0, 0L ); /* uusi valinta päälle */ j = id - pKonKuv->koID1; SendDlgItemMessage( hDlg, pKonKuv->koID1+j, BM_SETCHECK, 1, 0L ); /* arvon (monesko) talletus */ kytkinTietueelle( j ); return TRUE; case C_acbo: /* autovalintaruutu, myös 3-tilainen */ i = (int) SendDlgItemMessage( hDlg, id, BM_GETCHECK, 0, 0L ); kytkinTietueelle( i ); return TRUE; case C_chbo: /* valintaruutu, myös 3-tilainen */ i = (int) SendDlgItemMessage(hDlg,id,BM_GETCHECK,0,0L); /* uusi tila mod(tilojen lkm) */ if ( pKonKuv->koMaxlkm ) j = ( i + 1 ) % pKonKuv->koMaxlkm; else j = ( i + 1 ) % 2; /* tilan näyttö */ SendDlgItemMessage( hDlg, id, BM_SETCHECK, j, 0L ); kytkinTietueelle( j ); return TRUE; } return FALSE; } /********************************************************************/ static BOOL HANDLER_EN_KillFocus( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) /* Muokattavan tekstikentän arvon talletus */ { #pragma argsused int i = arvokentanPituus(); char *pmja = varaaMerkkijono( hDlg, i+1 ); if ( pmja ) { GetWindowText( GET_WM_COMMAND_HWND(wParam,lParam), pmja, i+1 ); tekstiTietueelle( pmja ); free( pmja ); } return TRUE; } /********************************************************************/ static BOOL HANDLER_LBN_KillFocus( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) /* Valintalistan valinnan talletus */ { #pragma argsused int isel; int i = arvokentanPituus(); char *pmja = varaaMerkkijono( hDlg, i+1 ); UINT id = GET_WM_COMMAND_ID(wParam,lParam); if ( pmja ) { isel = (int) SendDlgItemMessage( hDlg, id, LB_GETCURSEL, 0, 0L); if ( isel != LB_ERR ) { SendDlgItemMessage( hDlg, id, LB_GETTEXT, isel, (LPARAM) ((LPSTR) pmja )); } else *pmja = NULL; tekstiTietueelle( pmja ); free( pmja ); } return TRUE; } /********************************************************************/ static BOOL HANDLER_CBN_KillFocus( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) /* Yhdistelmälistan valinnan talletus */ { #pragma argsused int isel, ilkm; int i = arvokentanPituus(); char *pmja = varaaMerkkijono( hDlg, i+1 ); UINT id = GET_WM_COMMAND_ID(wParam,lParam); HWND hwnd = GET_WM_COMMAND_HWND(wParam,lParam); if ( !pmja ) return TRUE; /* jos ei tilaa, ei käsittelyä */ isel = (int) SendDlgItemMessage( hDlg, id, CB_GETCURSEL, 0, 0L); if ( isel == CB_ERR ) { /* jos syötetty uusi arvo, */ GetWindowText( hwnd, pmja, i+1 ); if (*pmja ) { /* se lisätään listaan, */ ilkm = (int) SendDlgItemMessage( hDlg, id, CB_GETCOUNT, 0, 0L ); /* jos siinä on tilaa */ if ( ilkm < pKonKuv->koMaxlkm ) { SendDlgItemMessage( hDlg, id, CB_INSERTSTRING, ilkm, (LPARAM) ((LPSTR) pmja )); SendDlgItemMessage( hDlg, id, CB_SETCURSEL, ilkm, 0L ); /* ei talletu muistiin, vain ruudulle !!! */ } } } else /* valittu arvo talteen */ SendDlgItemMessage( hDlg, id, CB_GETLBTEXT, isel, (LPARAM) ((LPSTR) pmja )); tekstiTietueelle( pmja ); free( pmja ); return TRUE; } /********************************************************************/ static BOOL HANDLER_PBN_Clicked( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) /* Painikkeiden käsittely */ { #pragma argsused /* arvojen palautus ja lopetus */ UINT id = GET_WM_COMMAND_ID(wParam,lParam); palautaArvotietue( hDlg, id ); pTemArv = pDlgPar->odArvot; kytkinTietueelle( pKonKuv->koMaxlkm ); DestroyDialog( hDlg, pKonKuv->koMaxlkm ); return TRUE; } /********************************************************************/ /********************************************************************/ /* Dialogin WM_COMMAND-viestien käsittelyfunktiotaulukot */ DMSGEntry DComBut[] = { /* Valintakytkinten ja -ruutujen viestit */ { BN_CLICKED, HANDLER_BN_Clicked }, { NULL, NULL } }; DMSGEntry DComEdt[] = { /* Muok. tekstikenttien viestit */ { EN_KILLFOCUS, HANDLER_EN_KillFocus }, { NULL, NULL } }; DMSGEntry DComLib[] = { /* Valintalistojen viestit */ { LBN_KILLFOCUS, HANDLER_LBN_KillFocus }, { NULL, NULL } }; DMSGEntry DComCob[] = { /* Yhdistelmälistojen viestit */ { CBN_KILLFOCUS, HANDLER_CBN_KillFocus }, { NULL, NULL } }; DMSGEntry DComPub[] = { /* Painikkeiden viestit */ { BN_CLICKED, HANDLER_PBN_Clicked }, { NULL, NULL } }; /* Käsittelyfunktiotaulukot kontrollien tyypin mukaan */ DMSGEntry *pDComTbl[] = { DComBut, /* auto-valintakytkimet */ DComBut, /* valintakytkimet */ DComBut, /* auto-valintaruudut */ DComBut, /* valintaruudut */ DComEdt, /* muokattavat tekstit */ DComLib, /* valintalistat */ DComCob, /* yhdistelmälistat */ DComPub, /* painikkeet */ NULL }; /********************************************************************/ /********************************************************************/ /* Dialogi-ikkunan viestinkäsittelyfunktiot */ /********************************************************************/ /********************************************************************/ static BOOL HANDLER_DWM_Command(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { #pragma argsused int i, j; const far KontrolliKuvaus *pkk = pDlgPar->odKuvaus; DMSGEntry *pcm; int id = GET_WM_COMMAND_ID(wParam,lParam); UINT cmd = GET_WM_COMMAND_CMD(wParam,lParam); /* Käsiteltävän viestin on tultava tunnetulta kontrollilta */ for ( j=0; pkk->koID1; pkk++, j++ ) { if ( ( id >= pkk->koID1 && id <= pkk->koID2 ) || ( id == pkk->koID1 && pkk->koID2 == 0 ) ) { // vl-94 switch ( pkk->koTyyppi ) { case C_arbu: /* kontrollin tyypin oltava */ case C_rabu: /* tunnettu */ case C_acbo: case C_chbo: case C_edte: case C_libo: case C_cobo: case C_pubu: /* kontrollin kuvausrivin osoite*/ pKonKuv = pkk; /* viestinkäs.funktiota varten */ /* valitaan käsittelyfunktio */ pcm = pDComTbl[ pkk->koTyyppi ]; for (i=0; pcm->handler; i++, pcm++) { if ( cmd == pcm->message ) { return( pcm->handler( hDlg, message, wParam, lParam ) ); } } } } } /* tai sen on oltava jokin seuraavista: */ switch ( id ) { case IDOK: /* return vl-94 */ pKonKuv = &kIDOK; return HANDLER_PBN_Clicked(hDlg, message, wParam, lParam ); case IDCANCEL: /* escape */ palautaArvotietue( hDlg, id ); DestroyDialog( hDlg, id); // P_stdPainike ); vl-94 return TRUE; } return FALSE; } /********************************************************************/ static BOOL HANDLER_DWM_InitDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) /* Kontrollien alustus edellisen valinnan arvoilla */ { #pragma argsused int i; char *pmja, s[30]; const far KontrolliKuvaus *pkk = pDlgPar->odKuvaus; for ( ; pkk->koID1; pkk++ ) { pKonKuv = pkk; switch ( pkk->koTyyppi ) { case C_arbu: /* valintakytkimen merkkaus */ case C_rabu: i = kytkinTietueelta(); SendDlgItemMessage( hDlg, pkk->koID1+i, BM_SETCHECK, (WPARAM) 1, 0L ); break; case C_acbo: /* valintaruudun tilan näyttö */ case C_chbo: i = kytkinTietueelta(); SendDlgItemMessage( hDlg, pkk->koID1, BM_SETCHECK, (WPARAM) i, 0L ); break; case C_edte: /* muok. tekstikenttään arvo */ pmja = tekstiTietueelta( hDlg, s ); if ( pmja && *pmja ) { SetWindowText( GetDlgItem( hDlg, pkk->koID1 ), pmja ); } else { /* työkalulla määritelty arvo */ i = arvokentanPituus(); GetWindowText( GetDlgItem( hDlg, pkk->koID1), pmja, i ); } /* rajoitetaan annettavan tiedon pituus */ /* SendDlgItemMessage( hDlg, pkk->koID1, EM_LIMITTEXT, (WPARAM) i, 0L ); Estää pidentämästä entistä tietoa, vaikka kentän pituuden puolesta olisi varaa !!! */ break; case C_libo: /* valintalistan alustus */ alustaListaAlkiot( hDlg, C_libo ); /* sitten aiempi valinta, */ merkkaaListaAlkio( hDlg, C_libo ); break; case C_cobo: /* yhdistelmälistan alustus */ alustaListaAlkiot( hDlg, C_cobo ); /* sitten aiempi valinta, */ if ( !merkkaaListaAlkio( hDlg, C_cobo ) ) { pmja = tekstiTietueelta( hDlg, s ); if ( pmja && *pmja ) { SetWindowText( /* arvo listan ulkopuolelta */ GetDlgItem( hDlg, pkk->koID1 ), pmja ); } } /* rajoitetaan tiedon pituus */ i = arvokentanPituus(); SendDlgItemMessage( hDlg, pkk->koID1, CB_LIMITTEXT, (WPARAM) i, 0L ); break; case C_stte: /* tekstikentälle sisältö */ pmja = tekstiTietueelta( hDlg, s ); if ( pmja && *pmja ) SetWindowText( GetDlgItem( hDlg, pkk->koID1 ), pmja ); break; } } return TRUE; } /********************************************************************/ /* Dialogin viestinkäsittelyfunktiotaulukko */ DMSGEntry DMsgTbl[] = { {WM_COMMAND, HANDLER_DWM_Command }, {WM_INITDIALOG, HANDLER_DWM_InitDialog }, {NULL, NULL } }; static tWndMsgHandlerProc OptPreHandler = NULL; tWndMsgHandlerProc SetOptPreHandler(tWndMsgHandlerProc NewPreHandler) { tWndMsgHandlerProc OldPre = OptPreHandler; OptPreHandler = NewPreHandler; return OldPre; } /********************************************************************/ BOOL CALLBACK _export OptioDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) /* Dialogin viestinkäsittelyfunktioiden ohjaus */ { #pragma argsused int i; if ( OptPreHandler ) if ( OptPreHandler(hDlg,message,wParam,lParam) != -1 ) return TRUE; for ( i=0; DMsgTbl[i].handler; i++ ) { if ( message == DMsgTbl[i].message ) return( DMsgTbl[i].handler( hDlg, message, wParam, lParam )); } return FALSE; } /********************************************************************/ /********************************************************************/ int OptioDialogi( HWND hWnd, const far DialogiParam *odParam ) { /* Optiodialogin käsittely */ #pragma argsused int iPalKdi; pDlgPar = odParam; /* parametrit funktioille */ switch ( odParam->odTyyppi ) { case D_modal: /* hallitseva dialogi */ varaaArvotietue( hWnd ); if ( pTemArv ) { iPalKdi = (int)DoModalDialog( hWnd, odParam->odNimi, OptioDlgProc ); } else iPalKdi = P_hairio; break; case D_modeless: /* vapaa dialogi ja */ case D_modeless_auto: /* tietojen välitön palautus*/ case D_modal_auto: iPalKdi = P_ei_tot; /* ei hoidossa vielä! */ break; } return iPalKdi; } /********************************************************************/ /* */ /* DIALOGIN TIETOJEN TALLETUS */ /* */ /********************************************************************/ /********************************************************************/ static BOOL talletaTiedot( HWND hWnd, const char *posio, const char *pnimi, const char *parvo, const char *pdt ) { /* Talletustiedoston kirjoitus */ BOOL ret; /* tunnisteeksi kontrollin arvon nimi */ ret = WritePrivateProfileString( posio, pnimi, parvo, pdt ); if ( !ret ) { OptMessageBox( hWnd, "Kirjoitus ei onnistu", "Optiodialogin talletus", MB_APPLMODAL | MB_ICONHAND | MB_OK ); } return ret; } /********************************************************************/ /********************************************************************/ BOOL TalletaOptiot(const far DialogiParam *odParam ) { /* Optiovalintojen arvojen talletus */ HWND hWnd = GetFocus(); BOOL ret = TRUE; char sar[8]; const far KontrolliKuvaus *pkk = odParam->odKuvaus; const char *pdt = odParam->odTiedosto; const char *pos = odParam->odKappale; const char *par = odParam->odArvot; /* tiedoston ja kappaleen nimi tarvitaan*/ if ( !pdt || !pos ) return FALSE; for ( ; pkk->koID1; pkk++ ) { /* kaikki arvotietueen tiedot, */ if ( pkk->koArvonNimi ) { /* joilla on talletusnimi, */ switch ( pkk->koArvonTyyppi ){ case T_char: /* talletetaan yksitellen */ sar[0] = *((char *) (par + pkk->koArvonPaikka)); sar[1] = NULL; /* ini-tiedostoon */ ret = talletaTiedot( hWnd, pos, pkk->koArvonNimi, sar, pdt ); break; case T_byte: wsprintf( sar,"%d", *( Uchar *) (par + pkk->koArvonPaikka) ); ret = talletaTiedot( hWnd, pos, pkk->koArvonNimi, sar, pdt ); break; case T_int: wsprintf( sar,"%d", *( int *) (par + pkk->koArvonPaikka) ); ret = talletaTiedot( hWnd, pos, pkk->koArvonNimi, sar, pdt ); break; case T_str: ret = talletaTiedot( hWnd, pos, pkk->koArvonNimi, (char *) (par + pkk->koArvonPaikka), pdt ); break; } } } return ret; } /********************************************************************/ /* */ /* DIALOGIN TIETOJEN ALUSTUS */ /* */ /********************************************************************/ /********************************************************************/ /********************************************************************/ BOOL AlustaOptiot(const far DialogiParam *odParam ) { /* Optiovalintojen arvojen alustus */ int i; char parvo[10]; const far KontrolliKuvaus *pkk = odParam->odKuvaus; const char *pdt = odParam->odTiedosto; const char *pos = odParam->odKappale; char *par = odParam->odArvot; /* tiedoston ja kappaleen nimi tarvitaan*/ if ( !pdt || !pos ) return FALSE; /* arvotietue alustamatta! */ /* kaikki arvotietueen tiedot haetaan, */ for ( ; pkk->koID1; pkk++ ) { /* jos niillä on tall.nimi */ if ( pkk->koArvonNimi ) { switch ( pkk->koArvonTyyppi ) { case T_char: { char c[2] =" "; c[0] = * ( par + pkk->koArvonPaikka ); GetPrivateProfileString( pos, pkk->koArvonNimi, c , parvo, sizeof(parvo), pdt ); * ( par + pkk->koArvonPaikka ) = parvo[0]; break; } case T_byte: i = (int) GetPrivateProfileInt( pos, pkk->koArvonNimi, * ( (Uchar *) (par + pkk->koArvonPaikka)), pdt ); * ( (Uchar *) (par + pkk->koArvonPaikka) ) = (Uchar)i; break; case T_int: i = (int) GetPrivateProfileInt( pos, pkk->koArvonNimi, * ( (int *) (par + pkk->koArvonPaikka)), pdt ); * ( (int *) (par + pkk->koArvonPaikka) ) = i; break; case T_str: GetPrivateProfileString( pos, pkk->koArvonNimi, par + pkk->koArvonPaikka, par + pkk->koArvonPaikka, pkk->koArvonKoko, pdt ); break; } } } return TRUE; } /********************************************************************/ /* */ /* DIALOGIN KÄSITTELY INI-TIEDOSTOA KÄYTTÄEN */ /* */ /********************************************************************/ /********************************************************************/ /********************************************************************/ int OptioDialogiJaIni(HWND hWnd, const far DialogiParam *odParam ,int save) { int iPalKdi; if ( ( save & OPT_READ ) && !AlustaOptiot(odParam ) ) return P_hairio; iPalKdi = OptioDialogi( hWnd, odParam ); if ( ( save & OPT_SAVE ) && iPalKdi != IDCANCEL ) // P_stdPainike) { vl-94 if ( !TalletaOptiot(odParam ) ) return P_hairio; return iPalKdi; }