/**************************************************************************** LIBRARY: STRLIB.C PURPOSE: Malli DLL-kirjaston työosa, joka voidaan liittää sellaisenaan mysö tavalliseksi kirjastoksi. Editor: Vesa Lappalainen 10.11.1992 USAGE: 1) Lisätään omaan ohjelmaan #include "strdll.h" 2) Kutsut aliohjelmiin: KysyJono(...) 3) Alustetaan pääohjelmassa globaali muuttuja GhInstance ============================= Aliohjelmien tarkempi kuvaus: ============================= ------------------------------------------------------ int CALLBACK_DLL KysyJono(LPSTR kysymys, LPSTR oletus, LPSTR jono, int max_pit) ------------------------------------------------------ Kysytään merkkijono käyttäjältä. Kysymykseen tulee dialogi, jonka otsikkona on kysymys. Dialogissa on kaksi nappulaa OK ja CANCEL. Mikäli valitaan OK (=Return), palautetaan vastatusta jonosta niin monta merkkiä kuin tulokseen sopii. Muuten (CANCEL = ESC) ei tulosta muuteta. Paluttaa: -1 = painettiin ESC tai CANCEL 0 <= annetun merkkijonon pituus LPSTR kysymys - dialogin otsikokksi tulostuva kysymys LPSTR oletus - edit-kenttään oletuksena tulostuva arvo LPSTR jono - tulosjono int max_pit - tulosjonon suurin sallittu pituus (myös \0) Tyyppi CALLBACK_DLL on joko CALLBACK tai CALLBACK _export sen mukaan, tuleeko tästä .DLL vai ei. ***************************************************************************** Tämän kirjaston käyttämiseksi pitää projektissa olla Pääohjelma.C STRLIB.C ???.DEF KYSYJONO.RC Lisäksi tarvitaan STRDLL.H ja KYSYJONO.H Jos tästä kirjastosta halutaan .DLL, niin ks. STRDLL.C ----------------------------------------------------------------------------- Toteutuksesta: ============== Kirjastossa on varattu taulukko globaaleja muuttujia varten. Kaikki globaalit muuttujat on pistetty yhteen tietueeseen joka sitten pystytään tallettamaan yhteen taulukon alkioon. Näin voidaan kullekin kutsun esiintymällä antaa omat globaalit muuttujat ikkunan kahvan perusteella. Tosin globaaleja ei nyt käytetä "staattisesti", eli kun kirjastosta poistutaan hävitettään esiintymän globaalit. Funktio GetG(hwnd) antaa osoitteen ikkunan globaaleihin muuttujiin ReleaseG(hwnd) vastaavasti vapauttaa ikkunan globaalit muuttujat. Globaalista taulukosta voidaan muutella niiden paikkoja, joten GetG -kutsulla saatavaan paikkaan saa luottaa vain sen ajan, kun Windows ei pääse saamaan uutta viestiä, eli suoritus pysyy omassa ohjelmassa. Aina kun on ollut vaara muuttua, pitää osoitin hakea uudelleen. Poistoalgoritmi voitaisiin rakentaa myös sellaiseksi, että poistettava merkitään vapaaksi ja paikkoja siirretään vain kun kaikki ovat vapaita. Uusi annettaisiin sitten 1. vapaasta. Nytkin käytetty menetelmä kuitenkin toimii vaikka se tuntuukin vaaralliselta. Globaalit saadaan tietysti "staattisiksi" lisäämällä kirjastoon aliohjelma, jonka kutsulla globaaleja vapautetaan ja normaalien rutiinien jälkeen niitä ei vapautettaisi. ----------------------------------------------------------------------------- Tehtäviä: 1) Käännä tästä .DLL versio ja kokeile toimintaa useammalla eri pääohjelman esiintymällä (eli syöttö kesken kahdessa ohjelmassa yhtäaikaa). Toimiiko? 2) Käännä .DLL versio, jossa määritelty vakio ONE_G, eli saadaan käyttöön vain yhdet "työglobaalit". Kokeile kuten edellä useammalla pääohjelman esiintymällä. Toimiiko? ****************************************************************************/ #include /* Tarvitaan kaikissa Windows C-ohjelmissa */ #include #include "strdll.h" #include "kysyjono.h" typedef BOOL CALLBACK (*PDIALOGPROC)(HWND,unsigned,WPARAM,LPARAM); typedef struct { /* Globaalien työmuuttujien tyyppi */ LPSTR jono; LPSTR oletus; LPSTR kysymys; int max_pit; HWND hwnd; /* Ikkuna joko "omistaa" muuttujat */ } StrGlobals; #define MAX_GLOBALS 50 static StrGlobals Globals[MAX_GLOBALS]; int Gnum = 1; /* Ensimmäinen varattu virhetilanteita varten! */ #ifdef ONE_G /* Määrittele tämä vakio, jos haluat kokeilla toim.yhd. Glob.*/ static StrGlobals Gl; #endif /***************************************************************************/ StrGlobals *GetG(HWND hwnd,int child) /* Palauttaa sen globaalin osoitteen, jonka hwnd omistaa. ** Jos child-lippu päällä, otetaan hwnd:ksi isän hwnd ** Jos hwnd:tä ei vielä ole allokoitu, tehdään sille uusi. ** Virhetilanteessa palautetaan joukon 1. (indeksi 0) */ { int i; HWND hwndp=GetParent(hwnd); #ifdef ONE_G if ( child != -1 ) return &Gl; #endif if ( child ) hwnd = hwndp; for ( i = 1; i < Gnum; i++ ) if ( Globals[i].hwnd == hwnd ) return &Globals[i]; if ( Gnum >= MAX_GLOBALS ) return &Globals[0]; Globals[Gnum].hwnd = hwnd; return &Globals[Gnum++]; } /***************************************************************************/ void ReleaseG(HWND hwnd) /* Poistetaan se globaali, jonka hwnd omistaa. Jos hwnd:tä ** ei ole allokoitu, niin ei poisteta mitään! */ { int i,j; for ( i = 1; i < Gnum; i++ ) if ( Globals[i].hwnd == hwnd ) { /* Jos löytyi, niin poistetaan */ for ( j = Gnum-1; j > i; j--) Globals[j-1] = Globals[j]; Gnum--; return; } } /***************************************************************************/ int DoModalDialog(HWND hWnd,char *name,PDIALOGPROC func) { int ret; FARPROC lpProcFunc; lpProcFunc = MakeProcInstance((FARPROC)func, GhInstance); ret = DialogBox(GhInstance, name, hWnd, lpProcFunc); FreeProcInstance(lpProcFunc); return ret; } /***************************************************************************/ BOOL CALLBACK_E KysyJonoDialog(HWND hDlg,unsigned message, WPARAM wParam,LPARAM lParam) { #pragma argsused StrGlobals *G; switch (message) { case WM_INITDIALOG: G = GetG(hDlg,1); SetWindowText(hDlg,G->kysymys); SetDlgItemText(hDlg,EDITJONO,G->oletus); return (TRUE); case WM_COMMAND: switch ( wParam ) { case IDOK: G = GetG(hDlg,1); GetDlgItemText(hDlg,EDITJONO,G->jono,G->max_pit); EndDialog(hDlg,lstrlen(G->jono)); return (TRUE); case IDCANCEL: EndDialog(hDlg,-1); return (TRUE); } break; } return (FALSE); } /***************************************************************************/ int CALLBACK_DLL KysyJono(LPSTR kysymys, LPSTR oletus, LPSTR jono, int max_pit) { int ret; HWND hwnd = GetFocus(); StrGlobals *G = GetG(hwnd,0); G->oletus = oletus; G->kysymys = kysymys; G->jono = jono; G->max_pit = max_pit; ret=DoModalDialog(hwnd,"KYSYJONO",KysyJonoDialog); ReleaseG(hwnd); return ret; }