/**************/ /* autotw.c */ /**************************************************************************** PROGRAM: autotw.c Windows: Win 3.1 & WIN32 PURPOSE: Aliohjelmakirjasto liikkuvien autojen (tms.) piirtämiseksi näytölle. - Autoja voi pysäköidä ja laittaa jälleen liikkumaan napauttamalla autoa hiiren oikealla näppäimellä. Hiiren kursori muuttuu ristinuoleksi aina kun kursori on auton kohdalla. - Autoja voi liikuttaa tarttumalla niihin hiiren vasemmalla näpääimellä - Oikealla hiiren näppäimellä + CTRL tuhotaan koko auto. - Kuvien ei tietysti tarvitse oikeasti olla autoja, vaan ne voivat olla mitä tahansa (suoraviivaisesti) liikkuviksi tarkoitettuja objekteja. PROJECT: ALI\autotw.c ALI\mjonot.c ALI\bitmap.c - jollei määritelty vakiota LOADBITMAP, jolloin kuvat otetaan vain resursseista AUTHOR: Vesa Lappalainen 20.10.1992 USAGE: Käyttäjän pitää 0) Liittää projektiin ALI\autotw.c ja pääohjelmaan #include "autot.h" lisäksi projektiin ALI\mjonot.c 1) liittää .RC tiedostoonsa haluttujen autojen bittikartat. Auton bittikarttaan on piirretty oikealle kulkevan auton kuva siten, että läpinäkyviksi halutut kohdat on valkoisella. 2) tehdä .INI tiedosto, jossa on autojen koordinaatit, nimet ja nopeudet. (ks. alusta_autot()) 3) autojen alustamiseksi ohjelmassa kutsua sopivassa kohti funktiota alusta_autot(NULL,hWnd,ininame); Funktiota voidaan kutsua myös uudelleen autojen lisäämiseksi esimerkiksi eri ininame-tiedostosta. 4) ohjelman lopuksi (tai muulloin tarvittaessa) poistaa autot kutsulla tuhoa_autot(); (tätä ei ole enää pakko käyttää, koska Windows huolehtii tästä automaattisesti lähettämällä jokaisella autolle WM_DESTROY-viestin, jolla kukin auto poistetaan) ============ Aliohjelmat: (autotw.c, autot.h) ============ alusta_autot() - alustetaan autot tuhoa_autot() - tuhotaan autot ============================= Aliohjelmien tarkempi kuvaus: ============================= --------------------------------------------------------------------- int alusta_autot(HINSTANCE hInst, HINSTANCE hPrev,HWND hWnd, const char *inifile) --------------------------------------------------------------------- Funktiolla alustetaan autot. Autot on liitetty ohjelman resursseihin bittikarttoina ja niiden ominaisuudet on määrätty .INI -tiedostossa. Funktiota voidaán kutsua useita kertoja, jolloin saadaan mukaan eri .INI-tiedostoissa olevia autoja. HINSTANCE hInst esiintymän kahva, josta autojen kuvat löytyvät. Jos NULL, otetaan se esiintymä, joka luonut ikkunan hWnd. Molemmat hInst ja hWnd eivät voi olla NULL! HWND hWnd: ikkunan kahva, johon autot tulevat liikkumaan Toimii jotenkin, jos = NULL, jolloin autot liikkuvat kaikkien ohjelmien päällä ja koko ruudun alalla. char *inifile: .INI-tiedoston nimi, josta autoja etsitään, ei .INI tarkenninta mukana. Jos nimessä on tarkennin, vaihdetaan se .INI .INI-tiedoston muoto on: ------------------------ [Autot] Auto0=HAUTO,1,0,10,200 Auto1=KAUTO,0,100,20,300,10,1 Auto2=HAUTO,0,70,30,100 Yhden auton parametrit ovat: (0 aina oletus) ---------------------------- 1 = Resurssitiedostossa olevan bittikartan nimi 2 = Auto peittää koko taustansa ( 0 = näkyy läpi ) 1 = nopeampi liikkumaan, muttei toimi jollei kuva ole koko taustansa kokoinen! | 2 = ei näy läpi edes valkoisesta | 4 = ei käänny päissä 3 = y-koordinaatti näytöllä ( 0 = ajaa pohjalla ) 4 = auton hyppäys aikavälissä pisteinä ( 0 = 10 pistettä ) 5 = timerin jakso millisekuntteina ( 0 = 100 ms ) 6 = auton alkuperäinen x-paikka ( 0 = ikkunan puoliväli) 7 = onko auto päällä vai alla ( 0 = alla ) Autoja tulee niin monta kuin viimeinen juokseva Auto? ilmoittaa (+1), numerointi täytyy aloittaa 0:sta. .RC-tiedostossa: ---------------- HAUTO BITMAP "hauto.bmp" KAUTO BITMAP "kauto.bmp" ---------------------- void tuhoa_autot(void) ---------------------- Tuhoaa kaikki ohjelmaan liitetyt autot. Tätä on muistettava kutsua, jotta kaikki autoille tehdyt varaukset saadaan poistetuksi. Aliohjelman kutsuminen useampaan kertaan ei haitaa, samoin kuin ei sekään, vaikka kaikki autot jo olisi poistettu hiiren oikealla näppäimellä. ***************************************************************************** ** ** Toteutus: ** ========= ** ** Autot on toteutettu ikkunoina, koska muuten jouduttaisiin aina auton ** siirtämiseksi lukemaan tausta talteen. Kuitenkin Windows saattaa muuttaa ** taustaa ja näin autoja pitäisi hävittää näytöstä ennen taustaa ** muuttavia toimenpiteitä ja tämä on melko mahdotonta. Taustaa nimittäin ** muuttaa menut, muut ikkunat, muut mahdollisesti liikkuvat autot jne. ** ** Auton oleminen päällimmäisenä tarkoittaa sitä, että se on hiirelle ** ensin löytyvä. Kuitenkin kuvana päällä oleva (TOP) kulkee muiden ** ikkunoiden alitse??? ** ** Kun kursori tulee auton kohdalle, muutetaan se ristinuoleksi. ** ** **18.10.1992/vl: ** Toistaiseksi autojen piirtäminen hieman "nykii". ** Voitaisiinko ikoneilla ehkä hoitaa siistimmin??? ** **8.11.1992 ** Toiminta ei aivan kunnollista, mikäli hwnd==NULL. Auton ** "tausta" ei korjaannu kunnolla! CS_SAVEBITS luomisessa ei auta! ** **20.8.1994/vl: ** WM_DESTROY-toimimaan, jottei tuhoa_autot olisi välttämätön ** **25.8.1995/vl: ** Totetutettu käyttäen autoille omaa ikkunaluokkaa ja ikkunan ** sisäisiä tavuja tallettamaan mikä auto on missäkin ikkunassa. ** **24.9.1995/vl: ** Kuvat voidaan ladata myös tiedostosta ** Auton 2 parametriin lisää arvoja ** ****************************************************************************/ #include #include #include #include #include "mjonot.h" #include "bitmap.h" #include "autot.h" #define WAutoWClass "WAutoWClass" /***************************************************************************/ typedef struct { /* Yhden auton bittikartojen kahvat */ HBITMAP hAnd; /* AND -maski (mustavalkoinen) */ HBITMAP hOr; /* OR -maski (mahd. värillinen) */ } MaskiTyyppi; /***************************************************************************/ /* .INI -merkityt kohdat voi alustaa .INI-tiedostolla */ typedef struct { /* Auton ylläpitämiseksi tarvittavat tiedot: */ char nimi[20]; /* Bittikuvan nimi. .INI */ int korkeus; /* Auton yläreunan y-koordinaatti, 0 on pohj. .INI */ int vauhti; /* x-siirtymä kerrallaan .INI */ int aikavali; /* Siirtymien aikaväli ms .INI */ int paikka; /* Auton x-koordinaatti .INI */ int suunta; /* +/- vauhti kulkusuunnan mukaan */ int xkoko; /* Bittikartan x-koko (Selvitetään bittikartasta) */ int ykoko; /* Bittikartan y-koko */ int xmin; /* Auton liikkeen pienen x-koordinaatti */ int xmax; /* Vastaava suurin x-koordinaatti (ikkunan koko määr) */ int kopio; /* Onko bittikartat kopioita jostakin muusta */ MaskiTyyppi AutoO; /* Oikealle kulkevan auton bittimaskit */ MaskiTyyppi AutoV; /* Vasemmalle kulkevan auton bittimaskit */ MaskiTyyppi Nyt; /* Kulkusuunnan mukaan joko AutoO tai AutoV */ int alustettu; /* Onko tietorakenne alustettu (0 = ei) */ int nakyvissa; /* Onko auto näkyvissä (nykyinen versio ei käytä) */ int pysakoity; /* Onko auto pysäköity vai ei (oletus ei). */ HWND hwnd; /* Autoa kuvaavan ikkunan kahva. */ HWND ohitus; /* Kulkeeko auto päällä vai pohjalla .INI */ HWND ParenthWnd; /* Isäikkunan kahva. */ HINSTANCE hInstance;/* Esiintymä, jossa auton ikkuna luotu */ int kokokuva; /* Auto täyttää koko ikkunansa,helppo siirtää .INI */ } AutoTyyppi; /***************************************************************************/ /* Tiedoston globaalit muuttujat ja niiden käsittely */ /***************************************************************************/ #define MAX_AUTOJA 20 static AutoTyyppi *autot[MAX_AUTOJA]; static int AUTOJA = 0; static int nyky_auto = 0; #define FOR_EACH(a) for (a=eka_auto(); a; a=seuraava_auto() ) /***************************************************************************/ static AutoTyyppi *eka_auto(void) { if ( AUTOJA <= 0 ) return NULL; nyky_auto = 0; return autot[0]; } /***************************************************************************/ static AutoTyyppi *seuraava_auto(void) { if ( nyky_auto >= AUTOJA-1 ) return NULL; nyky_auto++; return autot[nyky_auto]; } /***************************************************************************/ static int poista_listasta(HWND hWnd) { AutoTyyppi *a; if ( hWnd == NULL ) return 1; FOR_EACH(a) if ( a->hwnd == hWnd ) { free(a); a = autot[AUTOJA-1]; AUTOJA--; return 0; } return 1; } /***************************************************************************/ static AutoTyyppi *lisaa_listaan(AutoTyyppi *a) { if ( AUTOJA >= MAX_AUTOJA ) return NULL; autot[AUTOJA] = malloc(sizeof(AutoTyyppi)); if ( autot[AUTOJA] == NULL ) return NULL; *(autot[AUTOJA]) = *a; return autot[AUTOJA++]; } /***************************************************************************/ /***************************************************************************/ static int is_class(HINSTANCE hInst, char *name) /* Palauttaa 1 jos name-niminen luokka on olemassa */ { WNDCLASS wc; wc.style = NULL; wc.lpfnWndProc = (WNDPROC)is_class; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = name; if ( !RegisterClass(&wc) ) return 1; UnregisterClass(name,hInst); return 0; } /***************************************************************************/ static int tuhoa_bitmap(AutoTyyppi *a) { AutoTyyppi *pa; /* Etsitään onko tästä autosta kopiota */ if ( !a ) return 1; FOR_EACH(pa) if ( pa->alustettu && pa->kopio && pa->AutoV.hOr == a->AutoV.hOr ) { pa->kopio = 0; return 0; } # define TUHOA_BIT(b) \ { DeleteObject(a->b.hAnd); \ DeleteObject(a->b.hOr); } TUHOA_BIT(AutoV); TUHOA_BIT(AutoO); # undef TUHOA_BIT return 0; } /***************************************************************************/ static int putsaa_auto(AutoTyyppi *a) { if ( !a ) return 1; if ( !a->alustettu ) return 1; KillTimer(a->hwnd,1); SetWindowLong(a->hwnd,0,NULL); a->alustettu = 0; if ( a->kopio == 0 ) tuhoa_bitmap(a); poista_listasta(a->hwnd); return 0; } /***************************************************************************/ static void LaitaMaskikartat(HDC hDC,HBITMAP hAnd,HBITMAP hOr,int x,int y) /* Piirretään AND ja OR bittikartat alkaen paikasta x,y */ { HDC hDCBit = CreateCompatibleDC(hDC); BITMAP bm; HGDIOBJ hOld = SelectObject(hDCBit,hAnd); GetObject(hAnd,sizeof(bm),&bm); BitBlt(hDC,x,y,bm.bmWidth,bm.bmHeight,hDCBit,0,0,SRCAND); SelectObject(hDCBit,hOr); BitBlt(hDC,x,y,bm.bmWidth,bm.bmHeight,hDCBit,0,0,SRCPAINT); SelectObject(hDCBit,hOld); DeleteDC(hDCBit); } /***************************************************************************/ static int luo_bittikartat(HWND hWnd,AutoTyyppi *a) /* ** Alkuperäinen oikealle kulkeva auton bittikuva ladataan ja siitä tehdään ** vastaava vasemmalle kulkeva kuva peilikuvana. ** Jotta näytölle saataisiin vain auton kuva, eikä valkoista laatikkoa auton ** ympärille, tehdään piirtovaiheessa siten, että kuvaan tehdään ** autonmuotoinen musta reikä, johon auto sitten piirretään OR- ** operaatiolla. Alkuperäisestä, autosta pitää OR-operaatiota varten ** laittaa reunat mustaksi. ** Autonmuotoinen musta reikä saadaan maskilla, johon on laitettu mustaa ** kaikkiin auton värillisiin kohtiin ja valkoista kaikkialle reunoille. ** Tämä maski saadaan helpoiten muuttamalla värillinen auto mv:ksi. ** Värillisen auton reunat saadaan sitten mustaksi tekemällä INVERT ** kaikille reunapisteille edellä saadun maskin avulla. ** ** Siis auton liikuttelua varten tarvitaan 4 maskia. ** Nyt-maski on kopio joko oikean tai vasemman suunnan autoista ** liikesuunnan mukaan. ** ** */ { HDC hDC,hDCBit1,hDCBit2; HGDIOBJ hOld1,hOld2; /* Ja niiden vanhat "työkalut" */ BITMAP bm; /* Oikealle ja vasemmalle liikkuvat värilliset autot */ a->kopio = 0; #ifdef LOADBITMAP a->AutoO.hOr = LoadBitmap(a->hInstance,a->nimi); #else a->AutoO.hOr = bmFileOrResLoadBitmap(a->hInstance,a->nimi); #endif if ( !a->AutoO.hOr ) return 1; hDC = GetDC(hWnd); hDCBit1 = CreateCompatibleDC(hDC); /* Apu muisti-DC:t piirtelyyn */ hDCBit2 = CreateCompatibleDC(hDC); GetObject(a->AutoO.hOr,sizeof(bm),&bm); a->xkoko = bm.bmWidth; a->ykoko = bm.bmHeight; a->AutoV.hOr = CreateCompatibleBitmap(hDC,a->xkoko,a->ykoko); /* Mustavalkoiset maskiautot (bitmap on mustavalk. jos CCB muisti DC:stä */ /* jossa ei ole ennestään bitmappia!) */ a->AutoO.hAnd = CreateCompatibleBitmap(hDCBit1,a->xkoko,a->ykoko); a->AutoV.hAnd = CreateCompatibleBitmap(hDCBit2,a->xkoko,a->ykoko); hOld1 = SelectObject(hDCBit1,a->AutoO.hOr); hOld2 = SelectObject(hDCBit2,a->AutoO.hAnd); /* Maskiauto, jossa vain mustaa autossa ja valkoista reunoilla */ BitBlt(hDCBit2,0,0,a->xkoko,a->ykoko,hDCBit1,0,0,SRCCOPY); /* Alkuperäisestä autosta reunat mustaksi maskiauton avulla */ if ( ( a->kokokuva & 2 ) == 0 ) BitBlt(hDCBit1,0,0,a->xkoko,a->ykoko,hDCBit2,0,0,SRCINVERT); /* Vasemmalle liikkuva auto tehdään oikealle liikkuvasta autosta */ SelectObject(hDCBit2,a->AutoV.hOr); /* Tehdään auton peilikuva bittikarttaan AutoV.hOr */ StretchBlt(hDCBit2,0,0,a->xkoko,a->ykoko, hDCBit1,a->xkoko-1,0,-a->xkoko,a->ykoko,SRCCOPY); /* Mustavalkoinen vasemmalle menevä maskiauto */ SelectObject(hDCBit1,a->AutoV.hAnd); SelectObject(hDCBit2,a->AutoO.hAnd); /* Tehdään mustavalkoisen auton peilikuva bittikarttaan AutoV.hAnd */ StretchBlt(hDCBit1,0,0,a->xkoko,a->ykoko, hDCBit2,a->xkoko-1,0,-a->xkoko,a->ykoko,SRCCOPY); /* Poistetaan turhat DC:t */ SelectObject(hDCBit2,hOld2); SelectObject(hDCBit1,hOld1); DeleteDC(hDCBit2); DeleteDC(hDCBit1); ReleaseDC(hWnd,hDC); return 0; } /***************************************************************************/ static int alusta_bittikartat(HWND hWnd,AutoTyyppi *a) /* ** Tilan säästämiseksi ei saman nimiselle autolle luoda enää uutta ** bittikarttaa, vaan otetaan kopio vanhasta. Mikäli otetaan kopio ** pitää ohjelmoijan pitää huolta, että jos varsinainen auto tuhotaan ** ei kopioitakaan enää käytetä, tai jos jostakin autosta on kopio ** ei sitä saa tuhota, ennenkuin kopiot on poistetu käytöstä. */ { AutoTyyppi *pa; FOR_EACH(pa) /* Onko vastaava bittikartta jo ladattu */ if ( (pa->alustettu) && ( strcmp(pa->nimi,a->nimi) == 0 ) ) { a->kopio = 1; a->AutoO = pa->AutoO; a->AutoV = pa->AutoV; a->xkoko = pa->xkoko; a->ykoko = pa->ykoko; return 0; } return luo_bittikartat(hWnd,a); } /***************************************************************************/ static int alusta_ja_lisaa_auto(HWND hWnd,AutoTyyppi *a) /* ** Lisäksi alustetaan muut tarpeelliset tiedot. Jos jonkin arvo on ** alunperin 0, laitetaan siihen oletusarvo. ** ** Mikäli auton nimellä olevaa bittikarttaa ei löydy lainkaan, ** jätetään vastaava auto alustamatta. ** Jos kaikki muu onnistuu, niin lisätään auton kopioi auto-listaan. ** Auton ikkunan ylimääräisiin tavuihin laitetaan auton osoite, jotta ** auto olisi jatkossa helppo löytää. */ { RECT rc; AutoTyyppi *pa; if ( !a ) return 1; if ( a->alustettu ) return 0; a->ParenthWnd = hWnd; if ( !hWnd ) hWnd = GetDesktopWindow(); GetClientRect(hWnd,&rc); if ( alusta_bittikartat(hWnd,a) ) return 1; a->Nyt = a->AutoO; if ( !a->vauhti ) a->vauhti = 10; if ( !a->aikavali ) a->aikavali = 100; if ( !a->xmax ) a->xmax = rc.right - a->xkoko; if ( !a->korkeus ) a->korkeus = rc.bottom - a->ykoko; a->suunta = a->vauhti; a->paikka = a->xmax/2; a->hwnd = CreateWindow(WAutoWClass,a->nimi, WS_CHILD | WS_VISIBLE, a->paikka,a->korkeus,a->xkoko,a->ykoko, hWnd,NULL,a->hInstance,(void *)a); if ( a->hwnd == NULL ) { putsaa_auto(a); return 1; } a->nakyvissa = 0; a->alustettu = 1; if ( ( pa = lisaa_listaan(a) ) == NULL ) return 1; SetWindowLong(a->hwnd,0,(LONG)pa); SetTimer(a->hwnd,1,a->aikavali,NULL); return 0; } /***************************************************************************/ static int uusi_paikka(AutoTyyppi *a,int piirra_kokonaan) { if ( !a ) return 1; if ( a->ParenthWnd ) { if ( (a->kokokuva & 1) == 0 || piirra_kokonaan ) InvalidateRect(a->hwnd,NULL,FALSE); SetWindowPos(a->hwnd,a->ohitus,a->paikka,a->korkeus,a->xkoko,a->ykoko, SWP_NOSIZE ); } else { /* Jollei isäikkunaa, eli liikkuu koko ruudun alueella */ // InvalidateRect(a->hwnd,NULL,TRUE); /* Ei tunnu tarvitsevan */ SetWindowPos(a->hwnd,a->ohitus,a->paikka,a->korkeus,a->xkoko,a->ykoko, SWP_HIDEWINDOW ); SetWindowPos(a->hwnd,a->ohitus,a->paikka,a->korkeus,a->xkoko,a->ykoko, SWP_NOSIZE ); SetWindowPos(a->hwnd,a->ohitus,a->paikka,a->korkeus,a->xkoko,a->ykoko, SWP_SHOWWINDOW ); } return 0; } /***************************************************************************/ static int siirra_auto(AutoTyyppi *a) { int suunta_vaihtui = 0; if ( !a ) return 1; if ( a->alustettu == 0 || a->pysakoity ) return 1; a->paikka += a->suunta; if ( a->paikka > a->xmax ) { /* Valitaan auto vasemmalle */ a->paikka = a->xmax; a->suunta = -a->vauhti; a->Nyt = a->AutoV; suunta_vaihtui = 1; } if ( a->paikka < a->xmin ) { /* Valitaan auto oikealle */ a->paikka = a->xmin; a->suunta = a->vauhti; a->Nyt = a->AutoO; suunta_vaihtui = 1; } if ( a->kokokuva & 4 ) { suunta_vaihtui = 0; a->Nyt = a->AutoO; } return uusi_paikka(a,suunta_vaihtui); } /***************************************************************************/ static int tuhoa_auto(AutoTyyppi *a) { if ( !a ) return 1; DestroyWindow(a->hwnd); return 0; } /***************************************************************************/ void tuhoa_autot(void) { AutoTyyppi *a; FOR_EACH(a) tuhoa_auto(a); } /***************************************************************************/ static AutoTyyppi *EtsiAuto(HWND hwnd) /* Etsitään auto, joka on yhdistetty ikkunaan hwnd */ { return (AutoTyyppi far *)GetWindowLong(hwnd,0); } /***************************************************************************/ LONG CALLBACK_E AutoWndProc(HWND hWnd, unsigned message, WPARAM wParam, LPARAM lParam) { AutoTyyppi *a; static int pysakoity,x,y,down = 0; switch (message) { case WM_PAINT: { PAINTSTRUCT ps; if ( (a=EtsiAuto(hWnd)) == NULL ) break; if ( BeginPaint(hWnd,&ps) ) { if ( a->kokokuva & 2 ) bmDrawBitmap(ps.hdc,a->Nyt.hOr,0,0); else LaitaMaskikartat(ps.hdc,a->Nyt.hAnd,a->Nyt.hOr,0,0); } EndPaint(hWnd,&ps); return NULL; } case WM_CREATE: { LPCREATESTRUCT cs = (LPCREATESTRUCT)lParam; SetWindowLong(hWnd,0,(LONG)cs->lpCreateParams); return NULL; } case WM_LBUTTONDOWN: if ( (a=EtsiAuto(hWnd)) == NULL ) break; SetCapture(hWnd); pysakoity = a->pysakoity; a->pysakoity = 1; down = 1; x = LOWORD(lParam); y = HIWORD(lParam); return NULL; case WM_MOUSEMOVE: { int dx,dy; if ( !down ) break; if ( (a=EtsiAuto(hWnd)) == NULL ) break; dx = LOWORD(lParam) - x; dy = HIWORD(lParam) - y; if ( dx == 0 && dy == 0 ) return 0; a->paikka += dx; a->korkeus += dy; uusi_paikka(a,0); return 0; } case WM_LBUTTONUP: if ( (a=EtsiAuto(hWnd)) == NULL ) break; a->pysakoity = pysakoity; down = 0; ReleaseCapture(); return NULL; case WM_RBUTTONDOWN: if ( (a=EtsiAuto(hWnd)) == NULL ) break; a->pysakoity = !a->pysakoity; if ( wParam & MK_CONTROL ) tuhoa_auto(a); return NULL; case WM_TIMER: if ( (a = EtsiAuto(hWnd)) == NULL ) break; if ( a->pysakoity ) break; if ( IsIconic(a->ParenthWnd) ) return NULL; siirra_auto(a); return NULL; case WM_DESTROY: if ( (a = EtsiAuto(hWnd)) == NULL ) break; putsaa_auto(a); return 0; default: /* Antaa Windowsin käsitellä muut */ break; } return (DefWindowProc(hWnd, message, wParam, lParam)); } /***************************************************************************/ static int alusta_autoluokka(HINSTANCE hInst) { static int luokka_alustettu=0; WNDCLASS wc; /* Ikkunaluokka */ if ( luokka_alustettu || is_class(hInst,WAutoWClass) ) return 0; wc.style = NULL; wc.lpfnWndProc = AutoWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(AutoTyyppi far *); wc.hInstance = hInst; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_SIZE); wc.hbrBackground = GetStockObject(HOLLOW_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = WAutoWClass; if ( !RegisterClass(&wc) ) return 1; luokka_alustettu = 1; return 0; } /***************************************************************************/ static int jono_autoksi(HINSTANCE hInst,char *s,AutoTyyppi *a) { char *p; int ohitus = 0; a->alustettu = 0; a->nimi[0] = 0; a->kokokuva = a->xmin = a->xmax = a->korkeus = a->vauhti = a->aikavali = 0; a->paikka = 0; a->ohitus = HWND_TOP; a->hInstance = hInst; if ( (p=strtok(s,",")) == NULL ) return 1; strncpy(a->nimi,p,sizeof(a->nimi)); a->nimi[sizeof(a->nimi)-1] = 0; if ( (p=strtok(NULL,"\0")) == NULL ) return 0; sscanf(p,"%d,%d,%d,%d,%d,%d",&a->kokokuva,&a->korkeus, &a->vauhti,&a->aikavali,&a->paikka,&ohitus); if ( ohitus ) a->ohitus = HWND_BOTTOM; return 0; } /***************************************************************************/ int alusta_autot(HINSTANCE hInst, HWND hWnd, const char *inifile) /* Luetaan autojen ominaisuudet .INI-tiedostosta. Palautetaan löydettyjen ** autojen lukumäärä. */ { int lkm; char *p,ininame[80],pname[20],s[80]; AutoTyyppi a; if ( !hInst ) { if ( !hWnd ) return 0; /* Molemmat eivät saa olla NULL! */ hInst = GetWindowInstance(hWnd); } if ( alusta_autoluokka(hInst) ) return 0; kopioi_jono(N_S(ininame),inifile); p = strrchr(ininame,'.'); if ( p ) *p = 0; liita_jono(N_S(ininame),".ini"); /* Tehdään .INI-tiedoston nimi */ for (lkm=0;;lkm++) { sprintf(pname,"Auto%d",lkm); /* Tehdään Auto? */ if ( GetPrivateProfileString("AUTOT",pname,"",s,sizeof(s),ininame) == 0 ) break; /* Jollei autoa saatu, lopetetaan */ if ( jono_autoksi(hInst,s,&a) ) continue; alusta_ja_lisaa_auto(hWnd,&a); } return lkm; } /***************************************************************************/