[ Yu Raider @ 06.04.2006. 16:38 ] @
Dakle treba da izvucem ono sto se crta u PictureBox1_Paint eventu u sliku, tj image fajl... Jeli to moguce? |
[ Yu Raider @ 06.04.2006. 16:38 ] @
[ Shadowed @ 06.04.2006. 16:57 ] @
PictureBox.Image.Save(Path) [ Yu Raider @ 06.04.2006. 17:00 ] @
pbRadniProstor.Image.Save("c:\\a.bmp");
Daje error: Code: Object reference not set to an instance of an object. ??? [ akrosoft @ 06.04.2006. 17:08 ] @
Proveri da li ti je instnciran pbRadniProstor u momentu kada radis save.
[ Yu Raider @ 06.04.2006. 17:12 ] @
Instanciran? Mislis dal postoji :)... Da, postoji ako si to mislio... Da nije mozda to zato sto ne ucitavam nijednu sliku u njega?
Nego samo sve crtam pomocu _Paint eventa... [ Shadowed @ 06.04.2006. 17:21 ] @
Ocigledno da nemas Image objekat. Ne bi bilo lose da das relevantan deo koda kojim crtas.
[ Yu Raider @ 06.04.2006. 17:28 ] @
U pravu si - nemam Image objekat, vec crtam sve u pbRadniProstor_Paint rucno:
Code: private void pbRadniProstor_Paint(object sender, PaintEventArgs e) { Pen SivaLinija = new Pen(Brushes.LightGray); Pen CrvenaLinija = new Pen(Brushes.Red); Pen PlavaLinija = new Pen(Brushes.Blue); Pen CrnaLinija = new Pen(Brushes.Black); Pen LinijaZaCrtanje = new Pen(Brushes.Transparent); Font ObičanFont = new Font("Arial", 12, FontStyle.Bold, GraphicsUnit.Point); StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; int Brojac; CrvenaLinija.Width = 0.3f; SivaLinija.Width = 0.3f; PlavaLinija.Width = 4; CrnaLinija.Width = 4; if (Promenljive.MrežaUključena == true) { int VertikalnaRazdaljina = 10; int HorizontalnaRazdaljina = 10; if (edMrežaHoriz.Text != "" && edMrežaVert.Text != "") { VertikalnaRazdaljina = int.Parse(edMrežaVert.Text); HorizontalnaRazdaljina = int.Parse(edMrežaHoriz.Text); } e.Graphics.FillRectangle(Brushes.White, pbRadniProstor.Left, pbRadniProstor.Top, pbRadniProstor.Width, pbRadniProstor.Height); for (Brojac = 0; Brojac < pbRadniProstor.Height; Brojac += VertikalnaRazdaljina) { e.Graphics.DrawLine(SivaLinija, 0, Brojac, pbRadniProstor.Width, Brojac); } for (Brojac = 0; Brojac < pbRadniProstor.Width; Brojac += HorizontalnaRazdaljina) { e.Graphics.DrawLine(SivaLinija, Brojac, 0, Brojac, pbRadniProstor.Height); } } if (Promenljive.BrojProcesOblika != 0) { for (Brojac = 0; Brojac < Promenljive.BrojProcesOblika; Brojac++) { RectangleF privremenipravougaonik = new RectangleF(); privremenipravougaonik.X = Promenljive.ProcesOblik[Brojac].PozicijaX; privremenipravougaonik.Y = Promenljive.ProcesOblik[Brojac].PozicijaY; privremenipravougaonik.Width = Promenljive.ProcesOblik[Brojac].Širina; privremenipravougaonik.Height = Promenljive.ProcesOblik[Brojac].Dužina; e.Graphics.DrawString(Promenljive.ProcesOblik[Brojac].Tekst, ObičanFont, Brushes.Black, privremenipravougaonik, format); if (Promenljive.ProcesOblik[Brojac].Izabran == true) { e.Graphics.DrawRectangle(PlavaLinija, Rectangle.Round(privremenipravougaonik)); e.Graphics.DrawImage(ListaSlika2.Images[2], Promenljive.ProcesOblik[Brojac].PozicijaX + 10, Promenljive.ProcesOblik[Brojac].PozicijaY - 10); } else { e.Graphics.DrawRectangle(CrnaLinija, Rectangle.Round(privremenipravougaonik)); } } } } [ Yu Raider @ 06.04.2006. 17:58 ] @
Jooooj...
![]() ![]() [ Shadowed @ 06.04.2006. 18:16 ] @
Hm, nisam detaljno gledao sta se iscrtava ali sta mislis o tome da deklarises jedan globalni (na nivou klase) objekat tipa Bitmap, dodelis ga pbRadniProstor.Image-u i kreiras Graphics objekat iz njega. Napravis funkciju za crtanje i pozivas je kad ti treba (recimo pri tom Paint dogadjaju). Mozda ces cak i redje crtati jer ti slika ostaje kada se nesto nadje iznad PictureBox-a pa ukloni.
Onda mozes i izvrsiti i Save metodu. [ Yu Raider @ 06.04.2006. 18:21 ] @
Razmisljao sam o tome, ali kada deklarisem nesto ko objekat Bitmap on trazi ime fajla... To me je zbunilo. Da li da stavim neki blank bitmap fajl?
[ Shadowed @ 06.04.2006. 18:29 ] @
Imas konstruktor koji prihvata Image objekat kao argument. Koristi pbRadniProstor.Image za to:
bitmap MyBitmap = new bitmap(pcbRadniProstor); Mislim da je tako u C#-u [ Yu Raider @ 06.04.2006. 18:32 ] @
Hm... To ne radi... Razlog:
Code: Error 3 Argument '1': cannot convert from 'System.Windows.Forms.PictureBox' to 'string' E:\backup\Ivan\DiagramPro\DiagramPro\GlavniProzor.cs 410 38 DiagramPro Hehe ja sam kompletan noob ![]() Koristio sam bas to sto si napisao: Code: Image slika = new Bitmap(pbRadniProstor); ... samo sa drugim nazivima promenljivih... [ Shadowed @ 06.04.2006. 18:48 ] @
Sorry, vidim da ti se zuri pa sam i ja pozurio. Trebalo je:
Image slika = new Bitmap(pbRadniProstor.Image) Mada, sad mi pade na pamet da nece ici jer ti Image nije instaciran. Pogledaj u MSDN-u, imas i konstruktore gde prosledjujes dimenzije u pixel-ima i sl. [ Yu Raider @ 06.04.2006. 18:50 ] @
Ima dosta konstruktora... Ali svaki trazi image file... Ustvari postoji i jedan koji trazi Graphics kao argument...
![]() [ Yu Raider @ 06.04.2006. 18:53 ] @
Znam sta cu! Napravicu program iz jednog drugog prog jezika koji pravi bitmap, prazan bitmap, odredjenih dimenzija...
Ali moram da vas pitam: Kako se odavde runuje neki externi program, tj kojom komandom? [ Yu Raider @ 06.04.2006. 19:03 ] @
Hm... Nece to moci tako... Napravio sam test - blank sliku, loadovao je u pbRadniProstor i pokusao da sejvujem, ali nista, slika je izasla bas onakva kakva je bila - bela!
![]() [ Yu Raider @ 06.04.2006. 19:16 ] @
Pokusao sam i da stavim u pbRadniProstor_Paint() funkciju Crtaj() koja bi trebala da u Graphics objekat crta sve... Ali ne mogu da inicijalizujem Graphics objekat! Pri inicijalizaciji:
Code: Graphics grafika = new Graphics(); mi izbaci da Code: Error 2 The type 'System.Drawing.Graphics' has no constructors defined E:\backup\Ivan\DiagramPro\DiagramPro\GlavniProzor.cs 19 28 DiagramPro [ Shadowed @ 06.04.2006. 19:29 ] @
[ mmix @ 06.04.2006. 19:34 ] @
Nemoj me drzati za rec, ali mislim da bez BitBlt-a neces moci nista da uradis posto je GDI+ HDC koji koristis u tvom paint eventu screen HDC a ne memory HDC (uprosceno receno sve odmah ode na screen buffer, nista se ne cuva u objektnom svetu GDI+ pa da mozes da ga podignes/rekreiras nekako). Jedina opcija ti je da iskoristis BitBlt iz GDI+ (koji inace nije potpuno implementiran u .NETu) da sa screen HDCa iskopiras bitmapu u memorijski HDC odakle moze da se snimi.
Pogledaj code sample iz ove teme: http://www.elitesecurity.org/tema/162396/0#1056776 Taj code je predvidjen da sa screen buffera "mazne" sadrzaj kontrole. Samo umesto graph objekta iskoristi svoj graphics objekat iz paint eventa. [ Yu Raider @ 06.04.2006. 19:48 ] @
Mmix - ovo radi ali ima veeeeeliki problem. A to je - nije ceo PictureBox vidljiv odjednom, nego sam ga strpao u panel sa scroll barovima...
@Shadowed Dobro napravio sam bitmap :) Kako sad da uzmem sadrzaj samo PictureBoxa? [ Shadowed @ 06.04.2006. 19:53 ] @
Uh. Pod pretpostavkom da su ti dimenzije Bitmap objekata odgovarajuce:
Code: pbRadniProstor.Image=MyBitmap Gprahics MyGraph = Graphics.FromImage(MyBitmap) Sad taj MyGraph koristi za crtanje, a MyBitmap.Save() za snimanje fajla. Ponavljam, nisam gledao detaljno kod za crtanje, ako je tacno ono sto kaze mmix (a ja mu verujem) dzaba ti. [ dusans @ 06.04.2006. 20:00 ] @
Ako je tako onda ti lepo deklariši promenljivu za bitmap:
Code: private Bitmap Bmp; Zatim, u form load stavi ovaj kod: Code: this.Bmp=new Bitmap(this.pbRadniProstor.Width, this.pbRadniProstor.Height); U paint eventu ovaj: Code: Graphics G = Graphics.FromImage(Bmp); G.Clear(Color.Transparent); // Dalje koristi za crtanje G umesto e.Graphics // Npr. e.Graphics.DrawLine(SivaLinija, Brojac, 0, Brojac, pbRadniProstor.Height); // treba da bude G.DrawLine(SivaLinija, Brojac, 0, Brojac, pbRadniProstor.Height); // Na kraju paint event-a ide ovaj kod da bi video u picture box-u ono što si upravo iscrtao e.Graphics.DrawImageUnscaled(this.Bmp, 0, 0); Kasnije snimanje je posle valjda jasno: Code: this.Bmp.Save(@"C:\Test.Bmp"); Pozdrav! [Sad vidim da je Shadowed rekao istu stvar] [Ovu poruku je menjao dusans dana 06.04.2006. u 21:02 GMT+1] [ Yu Raider @ 06.04.2006. 20:06 ] @
Jeeeeeeeeeeeeee!!! Radi!!! Jeste da je program 90% sporiji iz nekog razloga ali barem radi
![]() [ Yu Raider @ 06.04.2006. 20:14 ] @
Hmmm cudno. Program je znatno sporiji iako usage procesora ne prelazi preko 50%. Ne bih sad da cepidlacim ali sto je veca slika tj njene dimenzije to radi sporije... jel to zbog
Code: Graphics G = Graphics.FromImage(slika); ...? [ dusans @ 06.04.2006. 20:19 ] @
Sporina dolazi iz ove linije ako je ti je PictureBox velik
Code: e.Graphics.DrawImageUnscaled(this.Bmp, 0, 0); Sad ako ne moraš da radiš iscrtavanje baš u Paint Event-u nego recimo na učitavanju forme ili na klik dugmeta onda možeš da dodaš u load event-u forme i liniju Code: pbRadniProstor.Image = Bmp; A zatim tamo gde radiš iscrtavanje (ali nikako u PaintEventu) pozoveš sledeću liniju: Code: pbRadniProstor.Refresh(); Ovo će ti raditi dosta brže. Pozdrav! [ Yu Raider @ 06.04.2006. 20:21 ] @
Ne znam kako radi - ali nisam ni stavio tu liniju... I bez nje se iscrtava... A kada je stavim onda je jos sporije
![]() [ Yu Raider @ 06.04.2006. 20:23 ] @
Ah - naravno, pa ja sam u timeru od 50 ms radio refresh... Zato se i ispisuje ;).
Cek da probam tvoju varijantu. [ Yu Raider @ 06.04.2006. 20:25 ] @
Tvoja varijanta : e.Graphics.DrawImageUnscaled(this.Bmp, 0, 0); mi uopste ne iscrtava na ekran :|. Oh well ako mora da bude sporo, sta da radim...
[ negyxo @ 07.04.2006. 10:37 ] @
Citat: Oh well ako mora da bude sporo, sta da radim... Ne mora da ide sporo. mmix ti je vec sve odgovorio. Treba samo da prebacis iscrtavanje u memory HDC a ne od kontrole. To ces uraditi tako sto ces kreirati prvo "kompatibilan" HDC na osnovu postojeceg a zatim sva ta iscrtavanja raditi na njemu a ne od kontrole. Na kraju na paint event samo uradis jedan BitBlt iz memory HDC u kontrolin HDC. Ovo je sigurno brze, valda :) Evo zakacio sam mali primer. Vodi racuna samo da je ovo VS2005 projekat. [Ovu poruku je menjao negyxo dana 07.04.2006. u 11:48 GMT+1] [ Yu Raider @ 07.04.2006. 12:01 ] @
Jupiiiiiiiiiiiiiiiiiiiiiiiiiiiii!!! :D
HVALA SVIMA MNOGO! [ Yu Raider @ 07.04.2006. 13:24 ] @
Hm... Jeste nekih 20 % brze ali je i dalje veoma sporo... Verovatno je to zbog samog crtanja, koje je jako glomazno i desava svaki frame.
[ mmix @ 07.04.2006. 13:29 ] @
Citat: Yu Raider: Hmmm cudno. Program je znatno sporiji iako usage procesora ne prelazi preko 50%. Ako imas P4 HT (Hyper Threading) ili jaci multi-core procesor onda ti single-thread aplikacija nikad nece uzeti vise od 50% ukupnog CPU vremena. [ Yu Raider @ 07.04.2006. 13:31 ] @
I ne uzima, cpu ne ide preko 50%, ali je izvrsavanje mnogo sporo. Glupi .NET
![]() [ mmix @ 07.04.2006. 13:38 ] @
Citat: Yu Raider: Hm... Jeste nekih 20 % brze ali je i dalje veoma sporo... Verovatno je to zbog samog crtanja, koje je jako glomazno i desava svaki frame. Jel ti to pravis neku GDI+ igricu? ![]() [ Yu Raider @ 07.04.2006. 13:43 ] @
Ne - nije igra. Nego Flowchart maker.
![]() koja treba da pokrije ceo radni prostor, ali kada treba mrezu da iscrtavam UZAS. Tad mi i strelica secka ![]() Inace kod koji koristim za crtanje mreze pri svakom Paint eventu je: Code: for (Brojac = 0; Brojac < pbRadniProstor.Height; Brojac += VertikalnaRazdaljina) { grafika.DrawLine(SivaLinija, 0, Brojac, pbRadniProstor.Width, Brojac); } for (Brojac = 0; Brojac < pbRadniProstor.Width; Brojac += HorizontalnaRazdaljina) { grafika.DrawLine(SivaLinija, Brojac, 0, Brojac, pbRadniProstor.Height); } [ negyxo @ 07.04.2006. 16:19 ] @
Pa jer bas moras na paint event da iscrtavas sve linije? Ako ti je ta mreza staticna zasto je onda ne nacrtas u memoriji pa je posle stalno samo kopiras. Na taj nacin ces i izbeci bespotrebno ponavljanje koje ti inace i usporava.
Ako si skinuo onaj primer probaj da zamenis DrawSomething f-ju sa ovim Code: int xDis = 5; int yDis = 5; Random rnd = new Random(); Color c = Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255)); Graphics g = Graphics.FromHdc(memHdc); g.Clear(Color.White); Pen p = new Pen(c); for (int i = 0; i < 10; i++) { for (int x = 0; x < pictureBox1.Width; x += xDis) { g.DrawLine(p, x, 0, x, pictureBox1.Height); } for (int y = 0; y < pictureBox1.Height; y += yDis) { g.DrawLine(p, 0, y, pictureBox1.Width, y); } } Ovako ce ti se DrawSomething iscrtati grid samo jednom u memoriji i posle toga na paint eventu ostaje samo da se kopira taj sadrzaj u pictureBox. Ovako imas samo jedan BitBlt naspram n poziva DrawLine. Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|