************************************* Egy egyszerű szövegszerkesztő MDI applikáció ************************************* A Windows alkalmazások kétfélék lehetnek: SDI (Single Document Intarface): Különálló ablakok, amelyek egymástól függetlenek. Ilyen pl. a Számológép program MDI (Multiple DI): Egy főablakban annak alárendelt gyerekablakok vannak, a gyerekablakok csak a főablakon belül léteznek. Az MDI alkalmazásokban általában több munkaterületen dolgozhatunk egyidőben, e munkaterületek a gyerekablakok (Word, Excel stb.) A főablakot ilyenkor MDI Form-nak, szülőablaknak vagy Conatiner ablaknak nevezzük, egy programban csak egy MDI Form lehet. A gyerekablakokat az MDI form kezeli, ahhoz képest méretezhetők ill. azon át könnyen, egyszerűen kezelhetők. Mind MDI, mind SDI alkalmazásokban lehetnek ún. modális ablakok, amelyekből annak megnyitása esetén az adott program többi ablak, menüje stb. nem érhető el, de más alkalmazások igen. Az MDI alkalmazásokban lehetnek (sima) párbeszédablakok is, amelyek a főablaktól függetlenek, de nem nem is modálisak. Ennek nincs értelme. Mintapélda: Egy egyszerű szövegszerkesztő program elkészítése ============================================================= Az MDI form és gyermekeinek létrehozása, összerendelése: -------------------------------------------------------- (MDI form létrehozása) Project\Add MDI Form Az MDI form tulajdonságai: Caption = "Little Text Editor" Name = frmMDI (Gyerekablak hozzárendelése MDI ablakhoz) Ha kell új form beszúrása Form frmSzöveg Caption = "Szöveg" Name = frmSzöveg MDIChild = True 'Az frmSzöveg az MDIform gyereke lesz (Elindítva: már működik is, próbáljuk végig a gyerekablak rendszerikonjait) A gyerekablak mint dokumentumablak megtervezése és méretezése: -------------------------------------------------------------- Tegyünk az frmSzövegbe egy szerkesztőmezőt (editbox) TextBox Text1 Text = (Üres) 'EZZEL KELL KEZDENI MultiLine = True 'Több soros lesz (Ekkor a Text = (Text) felíratú lesz) Scrollbars = 3 'Both azaz lesz vizszintes és függgőleges görgetősáv is 'Az frmSzöveg bal felső sarkába kerül a Text1 bal felső sarka: Left = 0 Top = 0 A jobb alsó sarkot kódból kell az aktuális méretre állítani: (AZ frmSzöveg átméretezésekor automatikusan akkora lesz a text box.) Private Sub Form_Resize() Text1.Height = ScaleHeight Text1.Width = ScaleWidth End Sub (Ki lehet próbálni) Menü készítése: Új gyerekablakok létrehozása futásidőben -------------------------------------------------------- Menü készítése az MDI formhoz: &Fájl mnuFile ...&Új mnuFileNew hot key megadása: shortcut=CTRL-N Gyerekablaknak is lehet menüje: ekkor ha a gyerekablak fut, lecserélődik a Szülőablak menüje a gyerekésre. (Wordben: Ha nincs megnyitott dokumentum a Szülőé látszik, ha van a gyereké (is) ) Szabályos menü: Fájl-Szerkesztés-...-Ablakok-Súgó Be kell tartani ! Az új menüpontot lekezelő eljárás: Private Sub mnuFileNew_Click() NewFile End Sub A NewFile eljárást egy önálló modulba tesszük: (Új modul létrehozása.) A modul propertyjében beállítjuk a modul nevét: modFile Public Sub NewFile() Dim NewDoc As New frmSzöveg 'Létrehoz még egy példányt NewDoc.Show End Sub (Próba) Gyerekablakok elrendezése futásidőben, menüből: ----------------------------------------------- Kell egy új menüpont a megfelelő elrendezésekkel az MDI formhoz: &Ablakok mnuWindow ...&Lépcsőzetes mnuWindowCascade ...&Mozaik mnuWindowTile ...&Ikonok mnuWindowIcons (Meghívjuk MDI ablak objektum Arrange metódusát a megfelelő VB konstanssal) (arrange (ö'reindzs)=elrendez) VB konstansok: előre elkészített konstansok, vb prefixel kezdődnek Private Sub mnuWindowCascade_Click() 'Lépcsőzetes elrendezés frmMDI.Arrange vbCascade End Sub Private Sub mnuWindowTile_Click() 'Mozaikszerű elrendezés frmMDI.Arrange vbTileHorizontal End Sub Private Sub mnuWindowIcons_Click() 'Ikonszerű elrendezés frmMDI.Arrange vbArrangeIcons End Sub Az ablakok közötti váltás az Ablak menüben: Legyen az Ablak menü WindowList jelölőnégyzete 1-checked A vonalat a VB kiteszi A gyerekablakok cimkéjének számozása (megkülönböztetés a felhasználónak): ------------------------------------------------------------------------- Szöveg-1 Szöveg-2 stb... a Caption-be Az ablakok számozásához bevezetünk egy globális változót (modFile-declarations:) Public intCounter as Integer A változó az MDI betöltésekor kap kezdőértéket: Privat Sub frmMDI_Load() intCounter=1 frmSzöveg.Show 'Az első példányt betölti automatikusan 'Mivel elsőnek az ős, az frmSzövegek töltődik be, Ő lesz az 1.: frmSzöveg.Caption="Szöveg-" & CStr(intCounter) End Sub Valamennyi konvertáló függvény alakja: CStr (C-konverzió és mibe) pl. CInt, CDate, CByte, CDbl A többi számozásához kiegészjük a NewFile eljárást: intCounter=intCounter+1 NewDoc.Caption="Szöveg -" & CStr(intCounter) A gyerekablakok megkülönböztetése futásidőben (a programozó számára): --------------------------------------------------------------------- Futás közben szükség lehet a gyerekablakok megkülönböztetésére, ha valamelyiken a felhasználó valamilyen műveletet végez. Az éppen aktív ablakra az frmMDI.ActiveForm tulajdonsággal hivatkozhatunk, az ablakok direkt megkülönböztetésére (pl. számozására) ritkán van szükség (az eseményvezérelt kezelés fölöslegessé teszi) Ha mégis ez megtehető, ekkor vektorként ábrázoljuk a gyerekablakokat: (egy BAS fájl deklarációs része:) Public Document() As New frmSzöveg 'Létrehozzuk az i-ediket a NewFile eljárásban: ReDim Preserve Document(i) 'A Dim NewDoc as New frmSzöveg helyett Document(i).Tag = i 'A továbbiakban a NewDoc ill. ActiveForm helyett a Document(i) szerepel 'Például amikor betöltjük a textboxába a fájlt: Document(i).Text1.Text = Input(LOF(1), 1) A fájlok betöltése ------------------ Segédeszköz: Commondialog: Win95 rendszerablak a legalapvetőbb funkciókhoz: Open, Save, Color, Font, Printer, Help Ha nincs, telepíteni kell: Project\Components\Controlls Az új vezérlőelemek hozzávételével a projectben új fájlok kerülhetnek, telepítéskor. Használata: Megnyitunk egy új formot: Name = frmFile Beleteszünk egy CommonDialog Controll-t. Megjelenítés a rendszer dolga, így nem kell beállítani semmit. Bővítjük a File menüt: &Megnyitás mnuFileOpen CTRL-O M&entés mnuFileSave CTRL-S A fájlmegnyitás rutin: Private Sub mnuFileOpen_Click() NewFile 'Új ablakot nyit OpenFileName 'A commondialog bekér egy fájlnevet OpenFile 'Betöltjük a fájlt End Sub A modFile deklarációs részébe egy új elem kerül: Public strFileName As String 'Ez lesz a fájlnév Public Sub OpenFileName() 'Beállítjuk a szűrőt: 'Ezt nem lehet _ -al tördelni ! frmFile.CommonDialog1.Filter = _ "Minden fájl |*.*| Text fájlok |*.txt|Batch fájlok| *.bat" 'Alapértelmezett szűrő a *.txt: frmFile.CommonDialog1.FilterIndex = 2 'Megjelenítjük a dialogusdobozt fájl megnyitásra: frmFile.CommonDialog1.ShowOpen 'A kiválasztott fájl neve a globális változóba kerül: strFileName = frmFile.CommonDialog1.FileName End Sub A Commondialog megjelenítésének módjai: ShowOpen; ShowSave; ShowPrinter; ShowColor; ShowFont; ShowHelp Public Sub OpenFile() 'A fájl megnyitása olvasásra Open strFileName For Input As #1 'A fájl maximális hossza: 64 KB If FileLen(strFileName) > 65535 Then MsgBox ("A fájl túl hosszú !") Close #1 Exit Sub End If 'A fájl beolvasása majd lezárása, egérkurzor kezeléssel: Screen.MousePointer = 11 'Homokóra frmMDI.ActiveForm.Text1.Text = Input(LOF(1), 1) 'Beolvasás Close #1 'Lezárás Screen.MousePointer = 0 'Nyíl alakú kurzor 'A cimkébe a fájlnév kerül frmMDI.ActiveForm.Caption = strFileName End Sub A fájl elmentése hasonló: ------------------------- Private Sub mnuFileSave_Click() SaveFileName SaveFile End Sub Public Sub SaveFileName() 'Beállítjuk a szűrőt: frmFile.CommonDialog1.Filter = "Minden fájl |*.*|Text fájlok |*.txt|Batch fájlok| *.bat" 'Alapértelmezett szűrő: frmFile.CommonDialog1.FilterIndex = 2 'Az utolsó filenév beállítása frmFile.CommonDialog1.filename = strFileName '"Mentés másként" ablak beállítása frmFile.CommonDialog1.ShowSave 'Fájlnév megadása a panel segítségével strFileName = frmFile.CommonDialog1.filename End Sub Public Sub SaveFile() Dim strSzöveg As String 'A fájl megnyitása írásra Open strFileName For Output As #1 'A szöveg kiírása majd a fájl lezárása Screen.MousePointer = 11 'Homokóra strSzöveg = frmMDI.ActiveForm.Text1.Text 'A szöveg elmentése Print #1, strSzöveg Close #1 Screen.MousePointer = 0 'Nyíl alakú gérkurzor 'A cimkébe a fájlnév kerül frmMDI.ActiveForm.Caption = strFileName End Sub Nyomtatás: ---------- Új menüpont a File menüben: &Nyomtatás mnuFilePrint CTRL-P A hozzá tartozó eljárás meghívja a modFile-ból a PrintFile eljárást: Public Sub PrintFile() Printer.Print frmMDI.ActiveForm.text1.Text Printer.EndDoc End Sub Beállítások megoldása (jelen esetben nincs értelme): Készítünk egy új űrlapot a Printernek: frmPrinter, és erre teszünk egy commondialog-ot (az frmFile nem használható, mert az Open/Save célú és minden funkciónak önálló CommonDialog kell !) Meghívjuk az frmPrinter.commondialog1.ShowPrinter metódust és a property-ket kiolvassuk. Pl. példányszám=frmPrinter.Commondialog1.Copies Megjegyzés: Ha hibásan állítunk be valamit, az összes alkalmazás aszerint fog nyomtatni, amíg vissza nem állítjuk. Szövegkijelölés, a vágóasztal kezelése : ---------------------------------------- A kijelölt szöveget a TextBox három tulajdonságával kezelhetjük: SelStart property = a kijelölt szöveg kezdőpontjára mutató LONG SelLength property= a kijelölt karakterek száma (LONG) SelText = A kijelölt szöveget tartalmazza A Clipboardot kezelő eljárások: SetText metódus : a megadott szöveget a vágólapra helyezi GetText metódus : a clipboard tartalmát a megfelelő helyre beilleszti Clear metódus : Törli a clipboardot Bővítjük a menüt a Szerkesztés menüvel, azon belül: Kivágás, Másolás, Beillesztés Private Sub mnuEditCopy_Click() Clipboard.Clear Clipboard.SetText frmMDI.ActiveForm.Text1.SelText End Sub Private Sub mnuEditCut_Click() Clipboard.Clear Clipboard.SetText frmMDI.ActiveForm.Text1.SelText frmMDI.ActiveForm.Text1.SelText = "" End Sub Private Sub mnuEditPaste_Click() frmMDI.ActiveForm.Text1.SelText = Clipboard.GetText() End Sub Az frmMDI.ActiveForm.Text1 helyett használhatnánk a Screen.ActiveControl megoldást is. Névjegy készítése: ------------------- Választunk a programnak egy ikont frmMDI.Icon property-be (pl. Vb\Icon\Writting\Note02.ICO ) Két lehetőség: A, Készítünk saját kezűleg egy frmAbout nevű formot, ízlésünk szerint B, A VB50 tartalmaz erre egy sablont: Project\AddForm\About Dialog A menüt bővítjük egy Súgó, azon belül egy névjegy menüponttal Private Sub mnuHelpAbout_Click() frmAbout.Show End Sub Saját frmAbout esetén gondoskodni kell az ablak bezárásáról, pl OK gomb segítségével: Private Sub Command1_Click() Unload Me End Sub Lehetett volna frmAbout.Hide is, de ekkor nem törlődik a memóriából, gyorsan előhívható a Show-val. (Fölöslegesen terheli a gépet.) Hibakezelés (run time) ---------------------- A futás közbeni hibák kezelésére két módszer lehetséges: A, Hiba esetén egy hibakezelő cimkére ugrik a program (On Error Goto Cimke) B, Hiba esetén azt figyelmen kívül hagyva a következő sorra lép. (On Error resume Next) Érdemes a következő sorba a hibától függően egy elágazást csinálni If Err Then... A, eset Hiba lép fel ha a felhasználó a fájlnév megadásakor a Mégse gombra kattint, ugyanis a fájl beolvasás azért megindul. Az OpenFileName eljárást függvénnyé alakítjuk, amelynek visszatérő értéke a Cancel esetén True, egyébként False: Public Function OpenFileName() As Boolean ... 'Hiba esetén ne szálljon el, hanem a Hibakezelő: cimkéhez ugorjon On Error GoTo Hibakezelő 'A Commondialog Cancel esetén hibát jelezve záródik be frmFile.commondialog1.CancelError = True 'Megjelenítjük a dialogusdobozt: frmFile.commondialog1.ShowOpen 'A kiválasztott fájlt megnyitjuk: strFileName = frmFile.commondialog1.filename OpenFileName = False 'Normális esetben ne szaladjon rá a hibakezelőre Exit Function Hibakezelő: OpenFileName = True End Function A logikai változótól függően meghívjuk vagy nem az OpenFile-t: Private Sub mnuFileOpen_Click() Dim voltCancel As Boolean NewFile voltCancel = OpenFileName() If Not voltCancel Then OpenFile End Sub B, eset Az OpenFile-t is kiegészítjük, mivel megnyitás közben hiba léphet fel (pl nincs bent a floppy vagy valaki .doc fájlt akar megnyitni) Public Sub OpenFile() 'Hiba esetén továbblép On Error Resume Next 'Megnyitja a fájlt Open strFileName For Input As #1 'Hiba esetén hibát jelez és kilép If Err Then MsgBox strFileName & " nem nyitható meg" Exit Sub End If 'A fájl maximális hossza: 64 KB If FileLen(strFileName) > 65535 Then MsgBox ("A fájl túl hosszú") Close #1 Exit Sub End If 'A fájl beolvasása majd lezárása Screen.MousePointer = 11 'Homokóra frmMDI.ActiveForm.Text1.Text = Input(LOF(1), 1) 'Hiba esetén hibát jelez és kilép If Err Then MsgBox strFileName & " nem nyitható meg" Close #1 Screen.MousePointer = 0 Exit Sub End If Close #1 Screen.MousePointer = 0 'Nyíl alakú 'A cimkébe a fájlnév kerül frmMDI.ActiveForm.Caption = strFileName End Sub Ugyanezeket a módosításokat végrehajtjuk a SaveFileName és a SaveFile eljárásoknál is. (Próba: mentés floppyra, ki kell venni; olvasni wmf fájlt stb.) Eszköztár készítése -------------------- Szükséges hozzá a Microsoft Common Controls 5.0 telepítése Az eszköztárat a Toolbar controll segítségével helyezzük fel (fix méretű) Az eszköztár gombjaihoz szükséges ábrákhoz szükségünk van egy ImageList controllra is, amelyet a Toolbar-ra kell húzni. Az ImageList Custom tulajdonságát választjuk, majd az Images fülön egyenként felvesszük a szükséges ikonokat, a VB\Graphics\Bitmaps\Tlbr_w95 alkönyvtárban vannak. A következő lépés a Toolbarra gombokat helyezni, és azokhoz az ikonokat hozzárendelni. Ehhez a Toolbar tulajdonságlapján a Custom tulajdonságot választjuk. A General fülön az ImageList mellé kiválasztjuk a létrehozott ImageList1-et, majd a Buttons fülön az Insert Button gombbal felveszünk egy gombot (indexe:1), megadjuk alul a hozzá tartozó kép sorszámát (1), és a key mellé az azonosítóját ("Cut")... Végül a gombokat hozzárendeljük a menüpontokhoz: Private Sub Toolbar1_ButtonClick(ByVal Button As ComctlLib.Button) Select Case Button.Key 'A Button objektum Key tulajdonsága Case "Cut" 'Első esetben "Cut" Call mnuEditCut_Click 'A megfelelő menüpont meghívása Case "Copy" Call mnuEditCopy_Click Case "Paste" Call mnuEditPaste_Click End Select End Sub Továbbfejlesztési lehetőségek: ============================== A programfejlesztés lényeges fázisa a hibák kijavítása illetve a továbbfejlesztés. Mivel programunk "csak" oktatás céljára készült, nagyon sok BUG-ot fedezhetünk fel, amelyet érdemes kijavítani: 1. Amikor megnyitjuk az első fájlt, akkor jelenleg az új dokumentumot hoz létre. Oldjuk meg, hogy az új fájl a megmyitáskor létrejött Szöveg-1-be kerüljön! 2. Ha már az össze fájl be van zárva, akkor a Fájl menü Bezár pontja a Kivágás, Másolás Beillesztés lehetőségek lekezeletlen hibát generálnak. Készítsük el a hibakezelő eljárást! 3. Bezáráskor nem kérdez rá az el nem mentett dokumentum mentésére. Valósítsuk meg a rákérdezést! 4. Üres dokumentumot is lehet menteni. Ezt tiltsuk le! 5. Nyomtatás előtt a felhasználónak mentenie kell a fájlt. Ha ekkor a "Mégse" lehetőséget választja, a program lekezeletlen hibával elszáll. Javítsuk ki! 6. Bővítsük a Szerkesztés menüt "Mindent kijelöl" CTRL-A lehetőséggel!