IntPtr zu Bitmap in eine PictureBox?


Asterix-Ac

Erfahrenes Mitglied
#1
Hi Community,

ich habe mir den Wrapper für die Twain API von Codeproject.com (Projektseite) gesaugt und habe sie in meine App eingebaut. Doch ich komme damit noch nicht ganz zurecht.
Der Wrapper liefert mir einen IntPtr zurück und instaziiert ein neues MDI-Child.
In dem Child pinselt er auf den Background das Image (weiß der Teufel, wie er das umgerechnet bekommen hat.). Aber genau das ist es, was ich verstehen muss, weil ich das Image nicht auf den Background haben möchte, sondern in eine PictureBox. Aber wie geht das ? Hat da jemand eine Idee?

Danke schonmal im Vorraus. :)

Asterix :confused:
 

Asterix-Ac

Erfahrenes Mitglied
#4
Hy,

Danke für die Infos. Leider hat es nicht funktioniert.
Ich habe es probiert mit :
Code:
pictureBox1.Image = new Image.FromHbitmap(IntPtr)
Ich bekomme dann immer eine Exception, nach dem scannen, wenn das neue
child erstellt werden soll.
Das Problem ist, ich kann nicht debuggen, da ich zu Hause keinen Scanner habe und ich zum probieren immer ins Icafe laufen muss, wo nur das normale Framework installiert ist. :(

Asterix :confused:
 

Asterix-Ac

Erfahrenes Mitglied
#5
Hi Comunity,

alles klar ... nun hat es geklappt.
Auf der Tutorial-Seite von Codeprojekt (s.o.) habe ich mir das original nochmal angeschaut und bin zu dem Schluß gekommen, dass ich keinen IntPtr zurückbekomme von der TwainLib sondern eine ArrayList mit IntPtr'ern.
Das half mir aber erst nicht weiter, doch dann habe ich nochmal in dem MessageBoard der Seite nachgeschaut und da hat jemand eine Methode gepostet, die aus der ArrayList ein Bitmap macht (eigentlich unlogisch).
Aber ... Was sich hinter den IntPtr'ern verbirgt, sind GDI-Bitmaps.
Und das ist dann kein Problem mehr, die in eine PictureBox reinzubekommen.
Die Methode (muss übrigens in die MainFrame.cs in die TwainGui Class eingetragen werden) fuktioniert aber so nicht, da sie die Variable i nicht kennt.
Da aber immer nur 1 Bild gescannt wird und sich dann der Dialog vom Twain-Treiber automatisch schließt, enthällt die ArrayList immer nur ein Element.
Das kann man ausnutzen und einfach int i = 0; als erste Zeile in die Methode schreiben .... und voila ... es funktioniert ... :)
Da man ja nun ein ein Bitmap in der Hand hat, kann man das ja der PicForm übergeben (aber ... da es sich ja um nur 1 Bitmap handelt, einfach die Schleife in der MainFrame.cs auskommentieren und antstatt dem IntPtr das Bitmap beim instanziieren übergeben.
Alles an Code in der PicForm kann man getrost über Board werfen. Man pappt einfach eine PictureBox in die Form und im Konstruktor castet(richtig geschrieben?) man das erhaltene Bitmap in ein Image und weist das dann der PictureBox zu .

Fertig. ;-)

Asterix
 

Brunetti

Grünschnabel
#6
Bitmap aus Arraylist

Hi Community,

Dein Beitrag hat mir sehr weitergeholfen. Allerdings funktioniert es bei mir noch nicht, weil ich immer noch nicht weiss, wie man aus dieser ArrayList ein Bitmap macht. Ich benötige also diese Methode bzw. die Info, wo ich die Methode auf dem MessageBoard finden kann.

Vielen Dank im Voraus

R. Brunetti
 

Asterix-Ac

Erfahrenes Mitglied
#7
Hi Brunetti,

tschuldige bitte, dass ich erst jetzt antworte, aber ich habe diesen Beitrag erst jetzt wieder gelesen.

Das Messageboard ist auf der Projektseite, die ich im ersten Beitrag oben gepostet habe, ganz unten. Du must Dich ein wenig durchklicken, bis Du die Methode findest. Habe sie gerade nicht zu Hand, da ich in einem ICafe sitze.

Asterix
 
#8
Hi Asterix,

vielen Dank für Deine Hilfe. Brauchst Dich doch nicht entschuldigen. Ich bin doch schon froh, dass Du Dich überhaupt mal meldest.

Ich habe auf Codeprojekt auch etwas gefunden, komme aber trotzdem noch nicht ganz klar. Es ist sicherlich nur eine Kleinigkeit.

Ich wäre Dir überaus dankbar, wenn Du mir die Methode bzw. den Link, oder noch besser ein Beispielprojekt zusenden würdest.

Ich habe zusätzlich noch das Problem die Sache in vb.net zu übersetzen.

Da ich einen Computerservice habe, kann ich Dir vielleicht auch irgendwie weiter helfen. (z.B. günstige Preise, beim Coden oder sonst irgendwie)

Habe mir mal kurz Deine HP angekuckt. Sehr gelungen, weiter so.

Viele Grüsse
R. Brunetti
 

Asterix-Ac

Erfahrenes Mitglied
#9
Hi Brunetti,

hier habe ich die komplette Methode :
Code:
public Bitmap GetBitMap(ArrayList alPics)
{
	int i=0; // das habe ich der Methode hinzugefügt
	Rectangle rPic = new Rectangle(0,0,0,0);
	IntPtr ipNonLockedBitMap = (IntPtr)alPics[i];
	IntPtr ipBitMap = GlobalLock(ipNonLockedBitMap); // TODO: Grab GlobalLock & GlobalFree from PicForm.cs
	BITMAPINFOHEADER bmihInfo = new BITMAPINFOHEADER(); // TODO: Grab BITMAPINFOHEADER from PicForm.cs
	Marshal.PtrToStructure(ipBitMap, bmihInfo);
	rPic.X = rPic.Y = 0;
	rPic.Width = bmihInfo.biWidth;
	rPic.Height = bmihInfo.biHeight;

	if( bmihInfo.biSizeImage == 0 )
		bmihInfo.biSizeImage = ((((bmihInfo.biWidth * bmihInfo.biBitCount) + 31) & ~31) >> 3) * bmihInfo.biHeight;

	int p = bmihInfo.biClrUsed;
	if( (p == 0) && (bmihInfo.biBitCount <= 8) )
		p = 1 << bmihInfo.biBitCount;
	p = (p * 4) + bmihInfo.biSize + (int) ipBitMap;

	IntPtr ipPixel = (IntPtr)p;

	Bitmap bmp = new Bitmap(rPic.Width, rPic.Height);
	Graphics g = Graphics.FromImage((Image)bmp);
	IntPtr hdc = g.GetHdc();

	SetDIBitsToDevice(hdc, 0, 0, bmp.Width, bmp.Height, 0, 0, 0, bmp.Height, ipPixel, ipBitMap, 0);
	g.ReleaseHdc(hdc);

	if (ipNonLockedBitMap != IntPtr.Zero)
	{
		GlobalFree(ipNonLockedBitMap);
		ipNonLockedBitMap = IntPtr.Zero;
	}
	return bmp;
}
hier die Aufrufe für die Twain
Code:
bool IMessageFilter.PreFilterMessage( ref Message m )
{
	try
	{
		TwainCommand cmd = tw.PassMessage( ref m );
		if( cmd == TwainCommand.Not )
			return false;

		switch( cmd )
		{
			case TwainCommand.CloseRequest:
			{
				EndingScan();
				tw.CloseSrc();
				break;
			}
			case TwainCommand.CloseOk:
			{
				EndingScan();
				tw.CloseSrc();
				break;
			}
			case TwainCommand.DeviceEvent:
			{
				break;
			}
			case TwainCommand.TransferReady:
			{
				ArrayList pics = tw.TransferPictures();
				Bitmap bmp = GetBitMap(pics);
				break;
			}
		}
	}
	catch(Exception ex)
	{
		MessageBox.Show(ex.Message);
	}
}
den Rest solltest Du Dir selber zusammenbasteln können.
Zu VB.NET kann ich Dir nicht weiterhelfen, da ich VB nicht kann.
Das müßtest Du schon selber machen. Aber es ist doch eh alles .NET.
Damit kannst Du doch Sprachenunabhängig programmieren.
Mache Dir eine DLL aus der ArrayList2Bitmap - Methode. Kompiliere sie und füge einen Verweis in Dein Projekt ein. Fertig.
Die Twain-Aufrufe must Du natürlich in Deine Anwendung einfügen, aber das sollte nicht das Problem sein.

Ich hätte schon was, womit Du mit eventuell helfen könntest.
Ich suche eine Klasse zum Faxen unter .NET. Schau mal unter http://www.java4less.com. Diese Fax-Klasse suche ich, aber ohne Bezahlung :)
Wenn Du was weist, oder hast, was dem ähnlich kommt, wäre das super.

Viel Erfolg,
Asterix

// Edit von Alex: Bitte unnötige Tabs entfernen, da die Zeilen sonst zu lange werden. Danke
 
Zuletzt bearbeitet von einem Moderator:
#10
Hi Asterix,

erstmal tausend Dank.

Bin noch nicht dazugekommen, den Code auszuprobieren. Melde mich aber deswegen nochmal.
Ich mache mich in den nächsten Tagen auf die Suche nach einer Fax Klasse.
Ich glaube so etwas schon einmal kostenlos gesehen zu haben. In meinen vb.net Büchern steht so viel ich weiss auch etwas darüber drin.
Bitte noch etwas Geduld. Bei der Übersetzung in C# kann ich Dir natürlich nicht weiter helfen. Aber so wie ich Dich einschätze, machst Du das auch noch nach ner Kiste Bier.

Bis die Tage
Roman Brunetti
 

Asterix-Ac

Erfahrenes Mitglied
#11
Hi,

mir ist aufgefallen, dass der original Twain Wrapper von CodeProject nicht funktioniert. Im Anhang habe ich ein VS-Projekt, mit dem man eine DLL bilden kann, die funktioniert.

Asterix
 
#12
Hi Asterix,

weiß gar nicht wie ich Dir danken soll.

Wie funktioniert das mit dem Anhang in tuturials.de?
Bin neu hier.

Deine Fax Klasse habe ich nicht vergessen. Bin zur Zeit leider voll ausgelastet.
Gesucht habe ich sie schon, aber bis jetzt noch nicht gefunden.
Ich suche so bald es geht weiter.

Vielen Dank.

R. Brunetti
 

Asterix-Ac

Erfahrenes Mitglied
#13
Hi,

ups, hatte den Anhang vergessen ... bin gerade im ICafe und habe nur die DLL mit. Reicht ja auch.Wenn Du das ganze Projekt haben möchtest, sag nochmal bescheid. Namespace ist Twainlib.
 

Anhänge

#14
Hi Asterix,

vielen Dank. Die TwainLib habe ich. Ich habe nur keine Ahnung wie ich das gescannte in eine Picture Box bringen kann. Oder stelle ich mich dumm an?

Ich habe so etwas:

Dim pics As ArrayList = tw.TransferPictures()
EndingScan()
tw.CloseSrc()

Dim i As Integer = 0
Dim img As IntPtr = CType(pics(0), IntPtr)
Dim newpic As PicForm = New PicForm(img)
newpic.MdiParent = Me
newpic.Show()

Damit befindet sich das Bild in der Form newpic.

Und jenes hier geht bekanntlich nicht:

PictureBox1.Image = Image.FromHbitmap(img)

picturebox1.image=img

Vielleicht hilft mir das ganze Project, oder die Tatsache, dass Du jetzt genau weißt was mein Problem ist?

Bis die Tage
Roman Brunetti
 

Asterix-Ac

Erfahrenes Mitglied
#15
Hallo Brunetti,

Du benutzt auch nicht die Methode, die ich oben gepostet habe. Du selber hast nichts mit 'FromHBitmap' zu tun. Einfach die Arraylist(pics) der Methode übergeben und Du bekommst ein Bitmap zurück. Du kannst mit :
Me.PictureBox1.Image = (Image)GetBitMap(pics)
das Image direkt an die PictureBox übergeben.
Da Du ein Bitmap zurückbekommst, must Du es noch in ein Image casten.

Asterix
 
#16
Hab zwar nicht das ganze Post gelesen ... aber zu den IntPtr'ern *lach*

IntPtr ist ein Type der einen Pointer oder Handler representiert! (kein Bild!)

:p
 

Neue Beiträge