GetHDC und ReleaseHDC für CLI/Formsanwendung
-
Hallo Forum,
in einem Cli basiertem Programm verwende ich die PictureBox, um aus einem Thread heraus Bilder einer Kamera mit der Methode „Setpixel“ anzuzeigen:
delegate void putbmp(Bitmap^bmp); void Form1::Setpixel(Bitmap^ bmp) { if (this->pictureBox1->InvokeRequired) { putbmp^ d = gcnew putbmp(this, &Form1::Setpixel); try { this->Invoke(d, gcnew array<Object^> { bmp }); } catch(Exception ^e) { MessageBox::Show(Convert::ToString(e)); } } else { this->pictureBox1->Image = bmp; //this->pictureBox1->Invalidate(); this->pictureBox1->Update(); } }
Das Ganze funktioniert ungefähr solange, bis man das Fenster der Anwendung mit der Maus verschiebt, oder ein anderes Fenster die picturebox zu mehr als 1/3 verdeckt. Die Anwendung stürtzt darauf mit der Fehlermeldung:
„Rufen Sie die ReleaseHDC Methode auf, wenn Sie das Grafikobjekt nach der GetHDC Methode verwenden“
In einem anderem Forum scheint das Problem auf mir nicht verständlicher Weise bereits gelöst zu sein :“ So wie AFingerhut schon vorgeschlagen hat, erzeugt nun ein Aufnahmethread die Bitmap, setzt ein Signal an den Anzeigethread (beinhaltet die Form und die Controls) ab, der Anzeigethread erzeugt eine Kopie der Bitmap z.B. mit Clone() und zeigt die Kopie an.“ (http://www.mycsharp.de/wbb2/thread.php?postid=273335)
Vielleicht kennt ja jemand ein Codeschnipzel wie das konkret umgesetzt werden kann – vielleicht kann mir aber auch jemand konkret weiterhelfen.
(Bisher wurde das Problem durch hinzufügen eines zweiten Bildschirmes umgangen, der jedoch nun anderweitig benötigt wird)
MfG
-
Zeichnen tut man in OnPaint bzw. dem entsprechenden EventHandler.
-
Hallo Jochen,
ich habe Deinen Hinweis verfolgt und in diesem Zusammenhang folgende Seite angeschaut: (http://msdn.microsoft.com/de-de/library/system.windows.forms.control.onpaint.aspx#Y439)
Leider kann ich damit nicht viel anfangen. Darüber hinaus konnte ich auch nicht abklären, ob ich die beschriebene Setpixel Methode weiter verwenden kann, oder ob eine ganz andere Vorgehensweise erforderlich ist, um aufgrund der Daten aus dem Bildakquise-Thread ein sich kontinuierlich aktualisierendes Livebild in pictureBox1 zu realisieren. (Die Methode Setpixel wird aus dem Thread aufgerufen, der die Bilddaten akquiriert.)
MFG.
-
Hallo Forum,
scheinbar führt der threadbasierte Aufruf:this->pictureBox1->InvokeRequired
zum Crash der Form, wenn die Form von einem anderen Fenster verdeckt ist.
Laut Suchfunktion gab es wohl mal früher eine Methode, mit welcher man eine Form immer aktiv im Vordergrund halten kann: http://www.c-plusplus.net/forum/80738
Leider scheint es diese Funktion heute nicht mehr zu geben – stattdessen müsste man wohl so etwas ähnliches machen, wie hier beschrieben :
http://www.c-plusplus.net/forum/236676
..aber ich kann leider nicht auf die Fenstererzeugung zugreifen.
Könnte man vielleicht mit this->Invoke( ????) aus dem Thread heraus, eine Funktion aufrufen, die überprüft, ob der Focus noch auf der Form ist ?
Ich könnte dann ein bool setzen, um dem Thread zu sagen, ob die pictureBox1 möglicherweise durch etwas anderes verdeckt ist, oder nicht.Ich würde mich sehr über Support freuen…
MfG.
-
So Leute,
hier ist die Lösung des Problems nach http://www.mycsharp.de/wbb2/thread.php?postid=273335 et al. : Offensichtlich gibt’s hier in meinem Beispielchen wohl auch zwei oder mehr Zugriffe auf ein und das selbe Bitmap-Objekt zur selben Zeit, die man mit der Methode Clone ohne Crash ermöglichen kann:
void Setpixel(Bitmap^ bmp) { if (this->InvokeRequired ) { //MessageBox::Show("InvokeReq = true)"); putbmp^ d = gcnew putbmp(this, &Form1::Setpixel); this->Invoke(d, gcnew array<Object^> { bmp->Clone(System::Drawing::Rectangle(0,0,bmp->Width,bmp->Height),bmp->PixelFormat)}); } else { this->pictureBox1->Image = bmp; this->pictureBox1->Update(); } }
Vielleicht hilft es ja dem einen oder anderen weiter.
MFG.