/****************/ /* laskurm2.cpp */ /****************/ // Esimerkki Autolaskurista. Projektiin laskurm2.cpp ja laskurm2.rc // Kopioi hakemistoon ..\kuvat tiedosto laskurir.ico // Lisäksi tarvitaan ALI\owl\intlabel.h // // Tehtäviä: // 1) Lisää polkupyörien laskeminen ks. .RC ja kohdat, joíssa PP // 2) Laita tallettamisen Message boxiin jokin muu ikoni MB // (ks. ko. funktion Help) // 3) Muuta ohjelmaa siten, ettei laskureiden ole NN // mahdollista mennä negatiivisiksi // (vihje: modifioi TIntLaskuri -luokkaa) // 4) Muuta ohjelmaa siten, että aina kun jompikumpi laskuri AS // tulee täyteen uuden 10, niin tiedosto "talletetaan". // (vihje: lähetä viesti isäikkunalle: // Parent->SendMessage(WM_COMMAND,IDM_FILE_SAVE); // Entä miten saat toiminnon siten, että samaa laskuri voidaan // käyttää sellaisessakin ikkunassa, joka tallettaakin viestillä // CM_SAVEFILE) // 5) Lisää ohjelmaan automaattitalletus 10 sek välein. TS // 6) Lisää ohjelmaan ominaisuus, jolla automaattitalletuksen // väli voidaan muuttaa. // 7) Lisää ohjelmaan ominaisuus: Save-menu on harmaa, jos tiedostoa // ei tarvitse tallettaa. Joko ymmärrät miksi oli luokka cOnkoTallessa? // 8) Tee luokka cSuunta, jonka avulla voidaan käyttää // suunnan asettamista pelkästään suunta = 1 tai suunta = -1 // ja menuvalinnat vaihtuvat automaattisesti (ota idea cOnkoTallessa // luokasta). Joko ymmärrät miksi jopa tavallisesta kokonaisluvusta // kannattaa tehdä luokka? // 9) Muuta ohjelma oikeasti tiedostoon kirjoittavaksi ja tiedostosta // lukevaksi käyttäen ofstream os(nimi) ja ifstream is(nimi) // tietovirtoja. HUOM! TIntLabel-luokan olio osaa kirjoittaa ja // lukea itsensä tietovirrasta! #include #include #include "laskurm2.rh" #include "owl\intlabel.h" //------------------------------------------------------------------------------ class cOnkoTallessa { // Luokka joka pitää kirjaa tiedoston tallessa olemisesta int ontallessa; int saving; // TS int aikavali; int timeron; TWindow *wnd; public: int TalletusViesti; // AS cOnkoTallessa(TWindow *awnd,int tv,int av) : wnd(awnd),ontallessa(1), timeron(0), TalletusViesti(tv), aikavali(av){}// TS ~cOnkoTallessa() { StopTimer(); } virtual void StartTimer() { if ( !saving && !ontallessa ) { // TS wnd->SetTimer(1,aikavali); timeron = 1; }} virtual void StopTimer() { if ( timeron) wnd->KillTimer(1); timeron = 0;} virtual int aseta(int i) { ontallessa = i; if ( ontallessa ) StopTimer(); else StartTimer(); return i; } virtual operator int() const { return ontallessa; } virtual int operator=(int i) { return aseta(i); } virtual int AsetaOn() { return aseta(1); } virtual int AsetaEi() { return aseta(0); } virtual int Onko() const { return ontallessa; } virtual void SetAuto(uint ms=0) { if ( ms ) aikavali = ms; // TS StartTimer(); } virtual void SetSaving() { StopTimer(); // TS saving = 1; } virtual void ClearSaving() { saving = 0; // TS StartTimer(); } virtual int Saving() { return saving; }// TS }; //------------------------------------------------------------------------------ class cLock { // Luokka, joka sammuttaa timerin ja käynnistää sen uudelleen // hävitettäessä ja muttaa vastaavasti lukkomuuttujan arvoa cOnkoTallessa &tal; public: cLock (cOnkoTallessa &atal) : tal(atal) { tal.SetSaving(); } ~cLock() { tal.ClearSaving(); } }; //------------------------------------------------------------------------------ class TIntLaskuri : public TIntLabel { // Laskuri, joka ilmoittaa muutoksen //------------------------------------------------------------------------------ cOnkoTallessa &tallessa; public: // TIntLaskuri();cOnkoTallessa &tal,TWindow* parent, int resourceId, TIntLaskuri(cOnkoTallessa &tal,TWindow* parent, int resourceId, uint textLimit = 0, TModule* module = 0) : tallessa(tal),TIntLabel(parent,resourceId, textLimit, module) {} virtual int set(int i) { if ( i < 0 ) i=0; // NN if ( int(*this) == i ) return i; if ( &tallessa != NULL ) tallessa = 0; if ( i % 10 == 0 && i > 0 ) // AS Parent->PostMessage(WM_COMMAND,tallessa.TalletusViesti); // AS return TIntLabel::set(i); } int operator=(int i) { return set(i); } }; //------------------------------------------------------------------------------ class TLaskuriDialog : public TDialog { TIntLaskuri hal; TIntLaskuri kal; TIntLaskuri ppl; // PP int suunta; cOnkoTallessa tallessa; TOpenSaveDialog::TData TiedostonAvaus; public: TLaskuriDialog(TWindow *parent, TResId resId, TModule *module = 0) : TDialog(parent,resId,module), tallessa(this,IDM_FILE_SAVE,3000), // AS hal(tallessa,this, HAL), // Kun nämä konstruoidaan heti täällä, ei tarvii kal(tallessa,this, KAL), // olla dynaamisia ppl(tallessa,this, PPL), // PP TiedostonAvaus(OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST ,"Laskuri (*.las)|*.las|Teksti (*.txt)|*.txt|All Files (*.*)|*.*|", 0, "", "*") { suunta = 1; tallessa = 1; } // void SetupWindow() { // Kelloa ei voi käynnistää konstruktorissa! // // se pitäisi käynnistää täällä, mutta koska se // // käynnistyy automaattisesti datan muuttuessa, niin // // ei hätää! int TeeTyhja() { hal = 0; kal=0; ppl=0; return 0; }// PP void BNHAClicked() { hal += suunta; } void BNKAClicked() { kal += suunta; } void BNPPClicked() { ppl += suunta; }// PP void BNNollaaClicked() { TeeTyhja(); } void BNExitClicked() { /*Destroy();*/ CloseWindow(); } int KirjoitaTiedosto(const char *nimi) { MessageBox(nimi,"Kirjoitetaan"); tallessa = 1; return 0; } int LueTiedosto(const char *nimi) { MessageBox(nimi,"Luetaan",MB_ICONHAND); // MB tallessa = 1; return 0; } int ClearFileName(int ClearName); int SaveFileIfChanged(int ClearName=0); int NewFile(); int SaveFile(); int SaveFileAs(); int OpenAndReadFile(); void CmFileNew() { NewFile(); } void CmFileOpen() { OpenAndReadFile(); } void CmFileSave() { SaveFile(); } void CmFileSaveAs() { SaveFileAs(); } bool CanClose() { return SaveFileIfChanged() == 0; } const char *TitleName(); void CmDec() { TMenu menu(*Parent); suunta = -1; menu.CheckMenuItem(IDM_OPTIONS_DEC, MF_CHECKED); menu.CheckMenuItem(IDM_OPTIONS_INC, MF_UNCHECKED); } void CmInc() { TMenu menu(*Parent); suunta = 1; menu.CheckMenuItem(IDM_OPTIONS_DEC, MF_UNCHECKED); menu.CheckMenuItem(IDM_OPTIONS_INC, MF_CHECKED); } void EvTimer(uint timerId) { // TS SaveFile(); // TS } DECLARE_RESPONSE_TABLE(TLaskuriDialog); }; DEFINE_RESPONSE_TABLE1(TLaskuriDialog, TDialog) EV_BN_CLICKED(HA ,BNHAClicked), EV_BN_CLICKED(KA ,BNKAClicked), EV_BN_CLICKED(PP ,BNPPClicked), // PP EV_BN_CLICKED(NOLLAA ,BNNollaaClicked), EV_BN_CLICKED(EXIT ,BNExitClicked), EV_BN_CLICKED(IDCANCEL,BNExitClicked), // Tämä, niin ESCillä ei vahingossa EV_COMMAND(IDM_FILE_NEW ,CmFileNew ), EV_COMMAND(IDM_FILE_OPEN ,CmFileOpen ), EV_COMMAND(IDM_FILE_SAVE ,CmFileSave ), EV_COMMAND(IDM_FILE_SAVEAS ,CmFileSaveAs ), EV_COMMAND(IDM_FILE_EXIT ,BNExitClicked), EV_COMMAND(IDM_OPTIONS_DEC ,CmDec ), EV_COMMAND(IDM_OPTIONS_INC ,CmInc ), EV_WM_TIMER, // TS END_RESPONSE_TABLE; //------------------------------------------------------------------------------ const char *TLaskuriDialog::TitleName() { // Funktio erottaa tiedoston nimestä pelkän nimiosan esim. otsikkoa varten static char tn[100]; TOpenSaveDialog::GetFileTitle(TiedostonAvaus.FileName,tn,sizeof(tn)); return tn; } //------------------------------------------------------------------------------ int TLaskuriDialog::ClearFileName(int ClearName) { if ( ClearName == 0 ) return 0; TiedostonAvaus.FileName[0] = 0; // Rohkea temppu, mutta sorsien mukaan toimii Parent->SetDocTitle("",0); // ja muutakaan tapaa ei ole annettu! return 0; } //------------------------------------------------------------------------------ int TLaskuriDialog::SaveFileIfChanged(int ClearName /* =0 */) // Jos tiedostoa on muutettu, kysytään sen tallettaminen. // Jos tallettamiseen vastataan YES, talletetaan // jos NO, ei talleteta // jos CANCEL, palautetaan virhe // Jos kaikki onnistuu ja ClearFile=1, niin tyhjennetaan ikkunan otsikko // ja tiedoston nimi ja palautetaan 0. { if ( tallessa ) return ClearFileName(ClearName); char s[256]; wsprintf(s,"%s\nTiedostoa muutettu.\n\nTalletetaanko?", (LPSTR)TiedostonAvaus.FileName); switch ( MessageBox(s,0,MB_APPLMODAL | MB_YESNOCANCEL | MB_ICONSTOP) ){ case IDYES: if ( SaveFile() ) return 1; //HUOM! Jatketaan seuraavaan case IDNO: return ClearFileName(ClearName); // jos SaveFile == 0 default: return -1; } } //------------------------------------------------------------------------------ int TLaskuriDialog::NewFile() { if ( SaveFileIfChanged(1) ) return 1; TeeTyhja(); return 0; } int TLaskuriDialog::SaveFile() { if ( tallessa ) return 0; if ( strcmp(TiedostonAvaus.FileName," ") < 0 ) return SaveFileAs(); if ( tallessa.Saving() ) return 1; // TS cLock saveloc(tallessa); // TS return KirjoitaTiedosto(TiedostonAvaus.FileName); } int TLaskuriDialog::SaveFileAs() { if ( tallessa.Saving() ) return 1; // TS cLock saveloc(tallessa); // TS if ( TFileSaveDialog(this, TiedostonAvaus).Execute() != IDOK ) return 1; if ( KirjoitaTiedosto(TiedostonAvaus.FileName) ) return 1; Parent->SetDocTitle(TitleName(),0); return 0; } int TLaskuriDialog::OpenAndReadFile() { if ( SaveFileIfChanged() ) return 1; cLock saveloc(tallessa); // TS if ( TFileOpenDialog(this, TiedostonAvaus).Execute() != IDOK ) return 1; if ( LueTiedosto(TiedostonAvaus.FileName) ) return 1; Parent->SetDocTitle(TitleName(),0); return 0; } //------------------------------------------------------------------------------ class TLaskuriApp : public TApplication { public: TLaskuriApp(const char *title) : TApplication(title) {} void InitMainWindow() { #if 0 // Joko normaali raami TFrameWindow *fw = new TFrameWindow(0, Name, new TLaskuriDialog(0, "LASKURI") , true); // Tyyli WS_CHILD #else // Tai vähän koristeellisempi raami johon voi lisätä vaikka mitä TDecoratedFrame *fw = new TDecoratedFrame(0, Name, new TLaskuriDialog(0, "LASKURI") ); fw->SetFlag(wfShrinkToClient); #endif fw->AssignMenu("Paamenu"); fw->SetIcon(this, "IKONI"); SetMainWindow(fw); } }; /********************* Pääohjelma *********************************************/ int OwlMain(int ,char far * []) { return TLaskuriApp("Autolaskuri").Run(); }