Grafikus C# – Windows Forms tanfolyam › 2.15 lecke Windows Forms · 2.15 lecke · haladó Egy szövegszerkesztőből a dokumentumot ki is kell tudni nyomtatni. A Windows Forms ehhez egy PrintDocument komponenst kínál, amelynek a lapokat mi rajzoljuk meg: a program szétosztja a szöveget oldalakra, a nyomtatási párbeszédablak és az előnézet pedig a Windows beépített ablakai. Ebben a leckében a MiniWord szövegét nyomtatjuk, és közben megértjük, hogyan működik egy többoldalas kiírás.PrintDialog, PrintDocument és nyomtatási előnézet

A lecke végére
- a
PrintDocument, aPrintDialogés aPrintPreviewDialogösszekapcsolásával nyomtatási folyamatot építesz; - a
BeginPrintés aPrintPageesemény szerepét érted; - többoldalas szöveget tördelsz oldalakra a
MeasureStringés aHasMorePagessegítségével; - a nyomtatást PDF-nyomtatóval is kipróbálod, papír nélkül;
- tudod, mit nem tud ez az egyszerű megoldás (a formázás nyomtatása);
- felismered a nyomtatás tipikus hibáit.
Mielőtt elkezded
Ehhez a leckéhez kell a MiniWord a 2.14 lecke után, a mezők (1.12 lecke), a Font (2.4 lecke) és a try–catch (2.2). A nyomtatás haladó téma, ezért a kódot lépésenként magyarázzuk.
Három komponens, egy dokumentum
A nyomtatás három komponensből áll, amelyeket a Toolbox Printing csoportjában találsz. Húzd mindhármat az ablakra (a komponenssávba kerülnek):
PrintDocument: a nyomtatandó dokumentum. Eseményeiben rajzoljuk meg a lapokat.PrintDialog: a Windows Nyomtatás ablaka (nyomtató, példányszám kiválasztása).PrintPreviewDialog: nyomtatási előnézet, a lapok képernyőn.dlgNyomtatas és a ppdElonezet Document tulajdonságát állítsd a pdDokumentum elemre (a Properties ablakban legördülő listából).A fájl elejére add hozzá a Mit tegyél ide: a komponenssáv a három nyomtatási komponenssel (pdDokumentum, dlgNyomtatas, ppdElonezet), mellette a Properties ablak, amelyben a dlgNyomtatas Document tulajdonsága a pdDokumentum értékre van állítva.Javasolt fájlnév: winforms-2-15-komponensek.webp · Alt szöveg: A nyomtatási komponensek és a Document tulajdonság beállításausing System.Drawing.Printing; sort, mert a nyomtatás típusai ebben a névtérben vannak.
A PrintPage esemény: itt rajzoljuk a lapot
A PrintDocument a nyomtatás megkezdése előtt a BeginPrint eseményt váltja ki, majd minden egyes lapra lefuttatja a PrintPage eseményt. A PrintPage eseménykezelőjében a lapra rajzolunk, ugyanúgy, mint a képernyőre. A PrintPageEventArgs e paraméter adja az eszközöket:
DrawString metódussal.PrintPage újra lefut). Ha hamis, a nyomtatás véget ér.Egyetlen lapra kiírva a szöveget így néz ki a legegyszerűbb változat:
private void pdDokumentum_PrintPage(object sender, PrintPageEventArgs e)
{
Font betu = new Font("Arial", 12);
e.Graphics.DrawString(rtbDokumentum.Text, betu, Brushes.Black, e.MarginBounds);
betu.Dispose();
e.HasMorePages = false;
}Jósolj!
A dokumentum három oldalnyi szöveget tartalmaz, de ez a kód egyetlen lapra rajzol, és a HasMorePages értéke hamis. Mi kerül a papírra?
Jóslat ellenőrzése
Csak az első lapnyi szöveg. A DrawString levágja azt, ami nem fér a téglalapba, és mivel a HasMorePages hamis, a többi lapra nincs nyomtatás. A hosszabb szöveg miatt kell a következő szakasz.
Többoldalas szöveg tördelése
Hosszabb szövegnél a programnak lapról lapra el kell döntenie, hány karakter fér egy lapra, azt kiírni, majd a maradékkal folytatni. Ehhez két mezőre van szükség: a nyomtatandó szövegre és arra, hogy hol tartunk benne (1.12 lecke: mező). A MeasureString metódus megmondja, hányadik karakterig fér a szöveg a területre:
private string nyomtatandoSzoveg = "";
private int pozicio = 0;
private void pdDokumentum_BeginPrint(object sender, PrintEventArgs e)
{
nyomtatandoSzoveg = rtbDokumentum.Text;
pozicio = 0;
}
private void pdDokumentum_PrintPage(object sender, PrintPageEventArgs e)
{
Font betu = new Font("Arial", 12);
string maradek = nyomtatandoSzoveg.Substring(pozicio);
int karakterek;
int sorok;
e.Graphics.MeasureString(maradek, betu, e.MarginBounds.Size, StringFormat.GenericTypographic, out karakterek, out sorok);
e.Graphics.DrawString(maradek.Substring(0, karakterek), betu, Brushes.Black, e.MarginBounds, StringFormat.GenericTypographic);
pozicio = pozicio + karakterek;
e.HasMorePages = pozicio < nyomtatandoSzoveg.Length;
betu.Dispose();
}out változókba tölti, hány karakter és sor fér el. (Az out működését az 1.3 lecke magyarázta.)PrintPage újra lefut.Jósolj!
Egy lapra 1800 karakter fér, a szöveg 4000 karakter hosszú. Hányszor fut le a PrintPage? Mi a pozicio értéke az utolsó lap után?
Jóslat ellenőrzése
Háromszor: az első két lapra 1800–1800 karakter kerül (3600), a harmadikra a maradék 400. Az utolsó lap után a pozicio értéke 4000, a HasMorePages hamis lesz, és a nyomtatás véget ér.
Haladó téma: nem kell mindent megjegyezned
A MeasureString és a DrawString használata a grafikus programozás (9. fejezet) része. Itt elég megérteni a menetet: megmérjük, mi fér a lapra, kiírjuk, megjegyezzük, hol tartunk, és újabb lapot kérünk, amíg van szöveg.
Mit nem tud ez a megoldás?
A formázás nem jelenik meg a nyomtatáson
A fenti kód a dokumentum sima szövegét egyetlen betűtípussal (Arial, 12 pont) nyomtatja. A félkövér, dőlt, színes szövegek, az igazítás és a különböző betűméretek nem kerülnek a papírra. Ez a megoldás gyakorláshoz és jegyzetekhez jó.
A formázott szöveg nyomtatásához a Windows saját RichEdit komponensét kell megkérni arra, hogy a lapra rajzolja a szöveget (EM_FORMATRANGE üzenet), ugyanúgy, ahogy a 2.7 leckében a sorkizárt igazításhoz üzenetet küldtünk neki. Ez bonyolultabb, és külön segédosztályt igényel: a MiniWord alapfeladatához nem szükséges. Ha érdekel, a Microsoft dokumentációjában keresd a „RichTextBox printing EM_FORMATRANGE” kifejezést.
Jósolj!
A MiniWordben a címet középre igazítottad, nagy méretű, félkövér betűkkel. Hogyan jelenik meg a címsor az egyszerű nyomtatáson?
Jóslat ellenőrzése
Balra igazított, normál 12 pontos Arial szövegként, mint a többi szöveg. A formázás és az igazítás nem kerül a nyomtatásba.
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. Csak az első oldal nyomtat
A hosszú dokumentumból csak egyetlen lap készül. A Ok és javítás
HasMorePages értéke nincs igazra állítva. Be kell állítani: e.HasMorePages = pozicio < nyomtatandoSzoveg.Length;, vagyis ha van még kiíratlan szöveg, igaz.
2. Minden lapon ugyanaz a szöveg
private void pdDokumentum_PrintPage(object sender, PrintPageEventArgs e)
{
int pozicio = 0; // ...
}Hiba és javítás
Rossz működés: a pozicio változót a metóduson belül hoztad létre, ezért minden lapon újra 0-ról indul. A változót mezőként, a metóduson kívül kell létrehozni (1.12 lecke), és a BeginPrint eseményben nullázni.
3. Ismeretlen típus
// CS0246: The type or namespace name 'PrintPageEventArgs' could not be foundHiba és javítás
Fordítási hiba (CS0246): hiányzik a using System.Drawing.Printing; sor a fájl elejéről. A nyomtatás típusai ebben a névtérben vannak.
4. Második nyomtatásnál rossz szöveg
Másodszor nyomtatva a dokumentum egy része hiányzik. A pozíció nincs nullázva a nyomtatás elején. A Ok és javítás
BeginPrint eseményben állítsd vissza pozicio = 0 értékre, és olvasd be újra a szöveget.
5. Nem jelenik meg a félkövér
A nyomtatott lapon nincs félkövér szöveg. Ez nem hiba: az egyszerű megoldás csak sima szöveget nyomtat, egyetlen betűtípussal. A formázott nyomtatáshoz külön, haladó megoldás kell (lásd az 5. szakaszt).Ok és javítás
Mini projekt: nyomtatás a MiniWordben
Építsd be a nyomtatást a MiniWordbe:
- Add hozzá a három komponenst (
pdDokumentum,dlgNyomtatas,ppdElonezet), és kösd őket össze aDocumenttulajdonsággal. A fájl elejére tedd ausing System.Drawing.Printing;sort. - Írd meg a két mezőt (
nyomtatandoSzoveg,pozicio), aBeginPrintés aPrintPageeseménykezelőt a 3. szakasz kódja szerint. - Adj a File menühöz Nyomtatás és Nyomtatási kép menüpontot, a 4. szakasz kódjával.
- Próbáld ki egy hosszú, több oldalas szöveggel az előnézetben, majd a Microsoft Print to PDF nyomtatóval, és nézd meg a PDF-et.
- Ellenőrizd: üres dokumentumnál nem omlik össze a program, és a másodszori nyomtatás is jó.
Mit tegyél ide: a MiniWord által készített, többoldalas PDF fájl első két lapja egymás mellett, az egyszerű szöveggel, a margókon belül tördelve.Javasolt fájlnév: winforms-2-15-pdf-kesz.webp · Alt szöveg: A MiniWordből nyomtatott többoldalas PDF első két lapja
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Oldalszám a lap alján
Minden lap aljára kerüljön az oldalszám, például: 1. oldal.Egy lehetséges megoldás
private int oldalSzam = 0;
// BeginPrint: oldalSzam = 0;
// PrintPage végén, az e.HasMorePages sor előtt:
oldalSzam = oldalSzam + 1;
Font kisBetu = new Font("Arial", 9);
e.Graphics.DrawString($"{oldalSzam}. oldal", kisBetu, Brushes.Gray, e.MarginBounds.Left, e.MarginBounds.Bottom + 10);
kisBetu.Dispose();
2. Fejléc a dokumentum nevével
Minden lap tetején jelenjen meg a dokumentum neve (például a címsor szövege). A Egy lehetséges megoldás
Font fejBetu = new Font("Arial", 9);
e.Graphics.DrawString(this.Text, fejBetu, Brushes.Gray, e.MarginBounds.Left, e.MarginBounds.Top - 25);
fejBetu.Dispose();this.Text az ablak címe (2.14 lecke). A margó felső széle fölé, a lap tetejére ír.
3. Nagyobb margó
Állítsd be, hogy a margók mindenhol körülbelül 2 cm-esek legyenek. (Segítség: a A 2 cm körülbelül 0,79 hüvelyk, vagyis 79 század. A négy érték sorban: bal, jobb, felső és alsó margó. A Margins osztály értékei századhüvelykben vannak, 1 hüvelyk = 2,54 cm.)Egy lehetséges megoldás
// a Form1_Load eseményben:
pdDokumentum.DefaultPageSettings.Margins = new Margins(79, 79, 79, 79);Margins is a System.Drawing.Printing névtérben van.
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. A feladatok a MiniWord nyomtatását gyakoroltatják (a pdDokumentum, dlgNyomtatas és ppdElonezet komponens a 2.15 lecke szerint). A fájl elejére tedd a using System.Drawing.Printing; sort. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Melyik komponens mire való?
Párosítsd: PrintDocument, PrintDialog, PrintPreviewDialog. Szerepek: (a) a Windows Nyomtatás ablaka, (b) a nyomtatandó dokumentum, amelynek lapjait mi rajzoljuk, (c) a nyomtatási előnézet.Megoldás megnyitása
PrintDocument → (b), PrintDialog → (a), PrintPreviewDialog → (c). A két ablak a Document tulajdonságon keresztül kapcsolódik a PrintDocument-hez.
2. Előnézet gomb
A Az előnézet ablaknak meg kell adni a dokumentumot, majd a btnElonezet gomb nyissa meg a nyomtatási előnézetet.Megoldás megnyitása
ShowDialog() megnyitja.private void btnElonezet_Click(object sender, EventArgs e)
{
ppdElonezet.Document = pdDokumentum;
ppdElonezet.ShowDialog();
}
Közepes szint
3. A szövegdoboz betűtípusa
A nyomtatás ne fix Arial betűvel, hanem a szövegdoboz betűtípusával ( A rtbDokumentum.Font) történjen. Mire kell vigyázni a betűtípus felszabadításánál?Megoldás megnyitása
Dispose() csak azokat a betűtípusokat szabad felszabadítani, amelyeket mi hoztunk létre (new Font). A vezérlő Font tulajdonságát nem szabad felszabadítani, mert a vezérlő még használja: ez a program hibájához vezetne. Itt ezért elmarad a betu.Dispose() sor.private void pdDokumentum_PrintPage(object sender, PrintPageEventArgs e)
{
Font betu = rtbDokumentum.Font; // nem mi hoztuk létre, nem szabad Dispose-olni
string maradek = nyomtatandoSzoveg.Substring(pozicio);
int karakterek;
int sorok;
e.Graphics.MeasureString(maradek, betu, e.MarginBounds.Size, StringFormat.GenericTypographic, out karakterek, out sorok);
e.Graphics.DrawString(maradek.Substring(0, karakterek), betu, Brushes.Black, e.MarginBounds, StringFormat.GenericTypographic);
pozicio = pozicio + karakterek;
e.HasMorePages = pozicio < nyomtatandoSzoveg.Length;
}
4. Üres dokumentum nyomtatása
Üres dokumentumnál a nyomtatás előtt figyelmeztessen a program (Nincs mit nyomtatni.), és ne jelenjen meg a nyomtatási ablak. Az ellenőrzés a nyomtatási ablak megnyitása előtt történik. A Megoldás megnyitása
return kilép a metódusból.private void miNyomtatas_Click(object sender, EventArgs e)
{
if (rtbDokumentum.TextLength == 0)
{
MessageBox.Show("Nincs mit nyomtatni.");
return;
}
dlgNyomtatas.Document = pdDokumentum;
if (dlgNyomtatas.ShowDialog() == DialogResult.OK)
{
pdDokumentum.Print();
}
}
Kihívás szint
5. Oldalbeállítás ablak
Egy Oldalbeállítás menüpont nyissa meg a Windows oldalbeállítás ablakát ( A PageSetupDialog), ahol a margók és a tájolás állítható, és a beállítás érvényesüljön a nyomtatáson.Megoldás megnyitása
PageSetupDialog komponenst a Toolbox Printing csoportjából húzod az ablakra (psdOldal). A Document tulajdonságával a nyomtatandó dokumentumhoz kötjük, így a beállított margók és a tájolás a PrintDocument beállításaiba kerülnek. A PrintPage eseményben használt e.MarginBounds már ezeket tükrözi.private void miOldalbeallitas_Click(object sender, EventArgs e)
{
psdOldal.Document = pdDokumentum;
psdOldal.ShowDialog();
}
6. PDF-teszt tervezése
Tervezz tesztet a Microsoft Print to PDF nyomtatóval: milyen dokumentumokkal és mit ellenőriznél?Megoldás megnyitása
Teszt Mit ellenőrzöl a PDF-ben? Rövid szöveg (3 sor) Egy lap, a szöveg a margón belül. Hosszú szöveg (több oldal) Több lap, a szöveg folytatódik, nem ismétlődik és nem hiányzik belőle. Üres dokumentum A program figyelmeztet, nem készül PDF. Sok üres sor és hosszú szó A tördelés nem szakad meg, nincs végtelen ciklus. Második nyomtatás ugyanabból A másodszor készült PDF azonos az elsővel (a pozíció újra nullázódik). Oldalbeállítás módosítása A margók és a tájolás változnak.
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. Minden nyomtatandó lapra lefut, és ebben rajzoljuk meg a lap tartalmát az Ha igaz, a nyomtató újabb lapot kér, és a Mert a lapok között is meg kell őriznie az értékét, a helyi változó pedig minden A nyomtatás elején egyszer fut le: beolvassa a szöveget, és nullázza a pozíciót. A Microsoft Print to PDF virtuális nyomtatóval, vagy a nyomtatási előnézettel. Mert a kód a sima szöveget (1. Mi a PrintPage esemény szerepe?
e.Graphics segítségével.2. Mit jelent az e.HasMorePages?
PrintPage újra lefut. Ha hamis, a nyomtatás véget ér.3. Miért mező a pozicio, és nem helyi változó?
PrintPage hívásnál újra létrejönne.4. Mire való a BeginPrint?
5. Hogyan teszteled a nyomtatást papír nélkül?
6. Miért nem jelenik meg a formázás a nyomtatásban?
Text) egyetlen betűtípussal rajzolja ki. A formázott nyomtatáshoz külön, haladó megoldás kell.
Mit tudsz már?
- Összekötöd a PrintDocument, a PrintDialog és a PrintPreviewDialog komponenst.
- Érted a BeginPrint és a PrintPage szerepét.
- Többoldalas szöveget tördelsz a HasMorePages segítségével.
- PDF-nyomtatóval papír nélkül teszteled a nyomtatást.
- Tudod, mi a megoldás korlátja.
Következő lecke: jegyzettömb és szövegszerkesztő záró projekt
A MiniWord minden fontos funkciója megvan. A fejezet záró projektjében összeállítjuk a teljes szövegszerkesztőt.





