Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C#.net] Plaatje 2x printen geeft GDI+ error

Pagina: 1
Acties:

  • AzzKickah
  • Registratie: Juni 2001
  • Laatst online: 21-11 18:52

AzzKickah

06-CENSORED

Topicstarter
Ik ben een beginner in het programmeren, al gaat het me steeds wat beter af. (Leuk om resultaat
te merken :) )

Ik ben een programma aan het maken waarmee adres-labels kunnen worden geprint. Ik heb de label als PNG, daar knal ik wat strings overheen en dan print ie het plaatje na op een button te hebben geklikt (zonder PrintDialog of wat ook, gewoon klik --> print).

Dat werkt an sich prima, echter wanneer ik voor de 2e keer op de print-knop klik, geeft ie een GDI+ error.
Ik heb al geprobeerd het plaatje te 'disposen' maar dit werkt niet, of ik doe het verkeerd.

Hier een stukje code:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private void button1_Click(object sender, EventArgs ee)
{
    Bitmap bitMapImage = new System.Drawing.Bitmap("label.png");
    Graphics labelplaatje = Graphics.FromImage(bitMapImage);
    labelplaatje.SmoothingMode = SmoothingMode.HighQuality;
    labelplaatje.CompositingQuality = CompositingQuality.HighQuality;
    string nrOfLabelsStr = numericUpDown1.Value.ToString();
    int nrOfLabels = int.Parse(nrOfLabelsStr);
    int dummy = 0;
    string AdresText = richTextBox1.Text;

    if (AdresText.Contains("Lorenskog") || AdresText.Contains("Dubai"))
    {
        MessageBox.Show("Transport papers!", "Transport papers");
    }
    
    labelplaatje.DrawString(AdresText, new Font("Arial", 10, FontStyle.Regular), SystemBrushes.WindowText, new Point(150, 216));
    labelplaatje.DrawString(textBox1.Text, new Font("Arial", 36, FontStyle.Bold), SystemBrushes.WindowText, new Point(100, 80));
    if (radioButton2.Checked == true)
    {
        labelplaatje.DrawString("Normal", new Font("Arial", 32, FontStyle.Bold), SystemBrushes.WindowText, new Point(175, 360));
    }
    else
    {
        labelplaatje.DrawString("Next day", new Font("Arial", 32, FontStyle.Bold), SystemBrushes.WindowText, new Point(175, 360));
    }
    bitMapImage.Save("labeloutput.png");
    bitMapImage.Dispose();
    labelplaatje.Dispose();
    do
    {
        PrintLabel("labeloutput.png");
        dummy++;
    }
    while (dummy < nrOfLabels);
}

//Print Label Event
public void PrintLabel(string labelfile)
{
    using (var pd = new System.Drawing.Printing.PrintDocument())
    {


        pd.PrintPage += (k, e) =>
        {
            var img = System.Drawing.Image.FromFile(labelfile);
            e.Graphics.DrawImage(img, new Point(75, 50));


        };
        pd.Print();
        pd.Dispose();
    }
}


Kan iemand me vertellen hoe ik dat oplos? Mocht de user dat willen, moet ie gewoon 3 of 4x op de print-button kunnen klikken.

[ Voor 73% gewijzigd door AzzKickah op 20-06-2013 19:36 ]


  • Ethernal Five
  • Registratie: December 2009
  • Niet online
Misschien kan hij het plaatje niet overschrijven? Het is al een paar jaar geleden dat ik C# heb gedaan dus weet het niet meer zo uit me kop.

  • AzzKickah
  • Registratie: Juni 2001
  • Laatst online: 21-11 18:52

AzzKickah

06-CENSORED

Topicstarter
Ethernal Five schreef op woensdag 19 juni 2013 @ 12:04:
Misschien kan hij het plaatje niet overschrijven? Het is al een paar jaar geleden dat ik C# heb gedaan dus weet het niet meer zo uit me kop.
Jawel het plaatje overschrijven gaat prima. Als je het programma opnieuw opstart en de labeloutput.png bestaat al, overschrijft ie hem gewoon bij het maken van de nieuwe label.

Het heeft iets te maken met dat het plaatje nog in het geheugen zit, maar ik weet niet hoe ik dat oplos. Kom er met Google, StackOverFlow en MSDN niet uit.

[ Voor 15% gewijzigd door AzzKickah op 19-06-2013 12:06 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Als je code wil posten, gebruik dan code tags a.u.b. Vandaag of morgen haal je 't plaatje van je host en is je topic onbruikbaar voor mensen die hier later middels de search nog eens op stuiten. Hetzelfde geldt voor keywords; "A generic error occurred in GDI+" of "ExternalException" e.d. zijn nu middels de search onvindbaar omdat ze simpelweg niet genoemd worden in je topic, enkel in de screenshot.

Voor wat betreft je probleem: Uit m'n hoofd, en AFAIK, implementeren beide Bitmap en Graphics IDisposable; wat betekend dat je beide moet disposen (gebruik daarvoor using). En kijk dan ook eens in de documentatie naar de .Save() method; daarin staat precies wanneer de ExternalException gethrowed kan worden ;) Wil je het helemaal uitsluiten dat 't aan 't wel/niet kunnen overschrijven van 't plaatje ligt dan gebruik je gewoon een (random) filename: bitMapImage.Save(Guid.NewGuid().ToString() + ".png"); ofzo.

Verder: ik weet niet wat PrintLabel() precies doet, maar zorg ook dat je daar je streams e.d. netjes closed/disposed; anders zal je bestand "in use" zijn en dus niet-overschrijfbaar.

[ Voor 22% gewijzigd door RobIII op 19-06-2013 12:23 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • AzzKickah
  • Registratie: Juni 2001
  • Laatst online: 21-11 18:52

AzzKickah

06-CENSORED

Topicstarter
RobIII schreef op woensdag 19 juni 2013 @ 12:06:
Als je code wil posten, gebruik dan code tags a.u.b. Vandaag of morgen haal je 't plaatje van je host en is je topic onbruikbaar voor mensen die hier later middels de search nog eens op stuiten. Hetzelfde geldt voor keywords; "A generic error occurred in GDI+" of "ExternalException" e.d. zijn nu middels de search onvindbaar omdat ze simpelweg niet genoemd worden in je topic, enkel in de screenshot.
Fixed.

Nu maar eens uitvogelen wat je me verder allemaal vertelt hier :)

Edit: Huh, ik kan m'n startpost niet meer wijzigen? Eerst kreeg ik een melding dat ie gelocked was, en na een refresh is het hele Wijzigen-linkje foetsie.

[ Voor 10% gewijzigd door AzzKickah op 19-06-2013 12:15 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
AzzKickah schreef op woensdag 19 juni 2013 @ 12:10:
[...]
Edit: Huh, ik kan m'n startpost niet meer wijzigen? Eerst kreeg ik een melding dat ie gelocked was, en na een refresh is het hele Wijzigen-linkje foetsie.
My bad; ik had nog even \[code=C#] (syntax-hilighting FTW \0/) toegevoegd en per-ongeluk de editlock laten staan ;)

[ Voor 5% gewijzigd door RobIII op 19-06-2013 12:27 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • eek
  • Registratie: Februari 2001
  • Laatst online: 06-04-2020

eek

@MagickNET

Geen idee of het een oplossing voor je probleem is maar het is wel zo netjes om ook je 'labelplaatje' te 'Disposen'. Weet je ook op welke regel je die 'GDI+ error' krijgt?

Skill is when luck becomes a habit.


  • Rutix
  • Registratie: Augustus 2009
  • Laatst online: 05-09-2024
Wat meer informatie zou handig wezen. De exacte exception of inner exception, op welke regel de exception word gethrowed ect. En wat is PrintLabel? Je hebt namelijk maar een stukje van de method geposted en na PrintLabel("labeloutput.png"); afgekapt.

Nothing to see here!


  • AzzKickah
  • Registratie: Juni 2001
  • Laatst online: 21-11 18:52

AzzKickah

06-CENSORED

Topicstarter
Code in de startpost aangevuld. PrintLabel() functie nu ook erbij.

De fout gebeurt op regel 27 bij het Saven, als je voor de 2e keer op Button1 klikt (de print-button dus).

De error is: A generic error occurred in GDI+.
Details:
Afbeeldingslocatie: http://www.tboekholt.com/gdierror.png

Ik heb me tot nu toe redelijk zelf kunnen redden met het programmeren met o.a. behulp van internet en forums, maar hier snap ik echt niks van.

Ik héb 't toch allemaal gedisposed? Ik snap niet waar dat plaatje in het geheugen blijft zitten.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Heb je deze post al eens goed gelezen? Basic troubleshooting: sluit eerst eens uit of 't aan een gelockte file ligt door lekker lomp elke keer een random filename te genereren bijvoorbeeld. Geheid dat 't dan werkt.
En je disposed niet alles netjes; ook daarvoor staat een hint in die post ;)

Verder zou ik 't eens uitkleden in een testcase tot het bare-minimum; even uit de losse pols zou dat zoiets moeten worden:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void Test() {
    using (Bitmap bitMapImage = new System.Drawing.Bitmap("label.png")) {
        using (Graphics labelplaatje = Graphics.FromImage(bitMapImage)) {
            labelplaatje.DrawString("Test", new Font("Arial", 10, FontStyle.Regular), SystemBrushes.WindowText, new Point(150, 216)); 
            bitMapImage.Save("labeloutput.png"); 
        }
    }

    PrintLabel("labeloutput.png"); 
    PrintLabel("labeloutput.png"); 
    PrintLabel("labeloutput.png"); 
}

public void PrintLabel(string labelfile) 
{ 
    using (var pd = new System.Drawing.Printing.PrintDocument()) 
    { 
        pd.PrintPage += (k, e) => 
        { 
            using (var img = System.Drawing.Image.FromFile(labelfile))
                e.Graphics.DrawImage(img, new Point(75, 50)); 
        }; 
        pd.Print(); 
    } 
}

Dan kun je je al véél beter concentreren op 't probleem.

[edit]
Ik zie overigens nu pas dat PrintPage een event is; tegen de tijd dat je daar die file gaat lezen kan de gebruiker natuurlijk alweer op de knop geramd hebben waarna je gaat proberen die file te overschrijven die de EventHandler nog aan 't gebruiken is... De makkelijkste oplossing is dan denk ik sowieso de output naar %temp%/<random_filename>.png te schrijven i.p.v. labeloutput.png en na je do-while loop de file met File.Delete() weer te verwijderen.

[ Voor 73% gewijzigd door RobIII op 20-06-2013 11:07 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • AzzKickah
  • Registratie: Juni 2001
  • Laatst online: 21-11 18:52

AzzKickah

06-CENSORED

Topicstarter
Top, het is me gelukt met behulp van RobIII's voorbeeld met using.

Goeie tip, zo'n test-dingetje met het minimale erin. Kun je inderdaad wat overzichtelijker met het probleem bezig.
[edit]
Ik zie overigens nu pas dat PrintPage PrintLabel een event is; tegen de tijd dat je daar die file gaat lezen kan de gebruiker natuurlijk alweer op de knop geramd hebben waarna je gaat proberen die file te overschrijven die de EventHandler nog aan 't gebruiken is...
Dat was het probleem niet. Als je gewoon netjes wachtte tot de label daadwerkelijk was geprint, en dan pas weer op de printknop klikte, klapte hij er weer uit. Hij kon dat bestand gewoon niet 2x achter elkaar gebruiken omdat ik het niet goed Dispose-te. En dat .Dispose(); is hier dus of niet de juiste manier, of dat werkt niet.. Nu met using werkt het netjes.

Ik moet me nog wel verdiepen in using want ik heb het nu zeg maar 'nagemaakt' van je voorbeeld. Nu nog echt leren hoe het werkt ;)
De makkelijkste oplossing is dan denk ik sowieso de output naar %temp%/<random_filename>.png te schrijven i.p.v. labeloutput.png en na je do-while loop de file met File.Delete() weer te verwijderen.
Nah ik blijf gewoon labeloutput.png gebruiken, maar na de tijd ff deleten is wel zo netjes inderdaad :)

Thanks!!

Edit: Oh nee dat kan helemaal niet, na de do-while loop al deleten, want dan kan het PrintLabel event die file niet meer printen of course. In het PrintLabel event deleten dan.

[ Voor 6% gewijzigd door AzzKickah op 20-06-2013 19:23 ]


  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
AzzKickah schreef op donderdag 20 juni 2013 @ 19:20:
En dat .Dispose(); is hier dus of niet de juiste manier, of dat werkt niet.. Nu met using werkt het netjes.

Ik moet me nog wel verdiepen in using want ik heb het nu zeg maar 'nagemaakt' van je voorbeeld. Nu nog echt leren hoe het werkt ;)
Zal ik dan maar even je op weg helpen?

De constructie
C#:
1
2
3
4
using(Foo foo = new Foo())
{
  foo.DoSomething();
}


wordt door de C# compiler direct omgezet in
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
try
{
  Foo foo = new Foo();
  foo.DoSomething();
}
finally
{
  IDisposable disp = foo as IDisposable;
  if ( foo != null )
  {
    foo.Dispose();
  }
}


De Dispose method doet dan ook gewoon wat het moet doen, maar je hebt waarschijnlijk zelf iets bij de handmatige aanroep verkeerd opgezet.
Pagina: 1