xsharp.eu • Gma.QrCodeNet.Encoding.dll - Page 6
Page 6 of 7

Gma.QrCodeNet.Encoding.dll

Posted: Fri Apr 08, 2022 7:04 am
by Chris
Hi Franz,

Unfortunately again this code is not complete, so it is very difficult to tell why it does not work. Can you please zip your full test project and post it here, so we can have a close look?

lagraf wrote:Ich teste noch ein wenig mit .NET und X# zu Lernzwecken herum und habe den Code um Folgendes zur Anzeige des QRCodes erweitert:

Code: Select all

LOCAL panel AS Panel
LOCAL padding AS System.Drawing.Point
LOCAL dSize AS DrawingSize

qrEncoder := QrEncoder{ErrorCorrectionLevel.H}
qrCode := qrEncoder:Encode(cText)
renderer := GraphicsRenderer{FixedModuleSize{nSize, QuietZoneModules.Two}, System.Drawing.Brushes.Black, System.Drawing.Brushes.White}

panel := Panel{}
padding := System.Drawing.Point{10, 16}
dSize := renderer:SizeCalculator:GetSize(qrCode:Matrix:Width)
panel:AutoSize := FALSE
panel:Size := Size{dSize:CodeWidth, dSize:CodeWidth} + Size{2*padding:X, 2*padding:Y}
BEGIN USING VAR graphics := panel:CreateGraphics()
	renderer:Draw(graphics, qrCode:Matrix, padding)
END USING
Der Code compiliert ohne Fehler, aber eine Anzeige über Panel erfolgt nicht.

Gma.QrCodeNet.Encoding.dll

Posted: Mon Apr 11, 2022 8:16 am
by lagraf
Hi Chris,
attached you find the complete code of the test project.
VOGuiWinforms.zip
(67.93 KiB) Downloaded 58 times

Gma.QrCodeNet.Encoding.dll

Posted: Mon Apr 11, 2022 8:31 am
by lagraf
Hallo Wolfgang,
ich sehe auf der Seite github.com/3F/DllExport nur *.cs und *.csproj Files, aber keine Dll, muß die erst noch selber compiliert werden? Was mich dabei auch wundert: Ich dachte bisher anhand deiner Aussage dass das nur mit Functions funktioniert, für Klassen und Methoden ist COM notwendig?

Gma.QrCodeNet.Encoding.dll

Posted: Mon Apr 11, 2022 8:42 am
by wriedmann
Hallo Franz,
1) nochmal zum Vorgang: um eine .NET-DLL wie eine normale C-DLL verwenden zu können, muss die DLL nach dem Erstellen verändert werden. Das passiert über die PostBuild-Action, und auf der 3F-Seite findest Du auch eine entsprechende cmd-Datei, die das mit Aufrufen von ILAsm und ILDasm erledigt (der originale Code von Robert Giesecke macht das nur für .NET 2.0, also untauglich für X#).
Die DLL wird nur gebraucht, damit in der DLL die Informationen für die Konvertierung vorhanden sind
2) die funktionale Schnittstelle per C-API exportiert nur Funktionen, wiel das C-API nichts anderes kennt.
Per Attribut wird in der C#-DLL dann festgelegt, wie die entsprechende statische Methode exportiert wird.
Nochmal zum besseren Verständnis: statische Methoden sind Methoden, die im Kontext einer Klasse, aber nicht im Kontext eines Objektes ausgeführt werden. Daher sind sie eigentlich mehr wie Funktionen zu sehen (und die Xbase-Funktionen werden vom X#-Compiler als statische Methoden einer versteckten Klasse implementiert, weil .NET gar keine Funktionen kennt).
3) die COM-Schnittstelle ist per Definition objekt-orientiert, d.h. über diese Schnittstelle werden Objekte transportiert, es kann auf ihre Eigenschaften zugegriffen werden und Methoden auf ihnen ausgeführt werden. Zudem kann COM die Bitness-Grenze überschreiten, man kann also mit einer x64-Applikation auch x86-DLLs laden und umgekehrt.
Wolfgang

Gma.QrCodeNet.Encoding.dll

Posted: Mon Apr 11, 2022 4:08 pm
by Chris
Hi Franz,
lagraf wrote:Hi Chris,
attached you find the complete code of the test project.
VOGuiWinforms.zip
Can you please also zip and post the QrCode dll that you are using?

.

Gma.QrCodeNet.Encoding.dll

Posted: Mon Apr 11, 2022 4:11 pm
by lagraf
The QRCode Dll ist included in the already attached VOGuiWinforms.zip with name Gma.QrCodeNet.Encoding.dll

Gma.QrCodeNet.Encoding.dll

Posted: Mon Apr 11, 2022 4:30 pm
by Chris
Hi Franz,
lagraf wrote:The QRCode Dll ist included in the already attached VOGuiWinforms.zip with name Gma.QrCodeNet.Encoding.dll
Oops, sorry, somehow I missed it!

The problem with showing the QR, is that you are painting it before the window is actually shown. When the window does show up, then the OS repaints it again and clears the QR code. Normally you would put such drawing code in a handler method of the Paint event, or in the OnPaint() method, which is the equivalent of VO's Expose().

Something like the code below should do it, although it's not a good idea to redraw the code every time the panel needs repainting, you should instead draw it once (in a separate bitmap maybe) and the reuse it every time to draw it on the window. Can you also show us the full c# sample code that you used, so we can directly translate it so it works the same way in X#?

Code: Select all

METHOD QrCode(cText AS STRING, nSize AS DWORD) AS VOID
	LOCAL panel AS Panel
	panel := Panel{}
	panel:AutoSize := TRUE
	panel:Paint += PaintEventHandler{ SELF , @Paint_handler() }
	SELF:Controls:Add(panel)

METHOD Paint_handler(sender AS OBJECT , e AS PaintEventArgs) AS VOID
	LOCAL panel AS Panel
	LOCAL qrEncoder AS QrEncoder
	LOCAL qrCode AS QrCode
	LOCAL renderer AS GraphicsRenderer
	LOCAL padding AS System.Drawing.Point
	LOCAL dSize AS DrawingSize
	LOCAL graphics AS Graphics
	
	panel := (Panel)sender

	qrEncoder := QrEncoder{ErrorCorrectionLevel.H}
	qrCode := qrEncoder:Encode("Hellow world")
	renderer := GraphicsRenderer{FixedModuleSize{5, QuietZoneModules.Two}, System.Drawing.Brushes.Black, System.Drawing.Brushes.White}
	padding := System.Drawing.Point{10, 16}
	dSize := renderer:SizeCalculator:GetSize(qrCode:Matrix:Width)
	panel:Size := System.Drawing.Size{dSize:CodeWidth + 20, dSize:CodeWidth + 20}

	BEGIN USING VAR stream := FileStream{"c:tempVOGuiWinforms.bmp", FileMode.Create}
		renderer:WriteToStream(qrCode:Matrix, ImageFormat.Bmp, stream)
	END USING

	graphics := panel:CreateGraphics()
	renderer:Draw(graphics, qrCode:Matrix, padding)	
.

Gma.QrCodeNet.Encoding.dll

Posted: Tue Apr 12, 2022 8:05 am
by lagraf
Hi Chris,thank you for your code, I putted it in my app and now it shows qrCode, zip attached!
How can I save renderer into a bitmap (WriteToStream?) and use it for drawing?
The C# example has same problem, it does not show the qrCode, but it's not necessary to make it run.
VOGuiWinforms.zip
(67.9 KiB) Downloaded 70 times
I tried OnPaint like this:

Code: Select all

CLASS WFWindow INHERIT System.Windows.Forms.Form
PROTECT _graphics AS Graphics
...
METHOD DoQrCode(cText AS STRING, nSize AS DWORD) AS VOID
// Generate qrCode and save it in protected var
_graphics := _panel:CreateGraphics()
...
PROTECTED METHOD OnPaint(e AS PaintEventArgs) AS VOID
// Draw graphic each time it is painted
SUPER:OnPaint(e)
_renderer:Draw(_graphics, _qrCode:Matrix, System.Drawing.Point{182, 66})
RETURN
But this brings an error and no graphic is painted:
Unhandled exception -> Object reference not set to an instance of an object

Gma.QrCodeNet.Encoding.dll

Posted: Tue Apr 12, 2022 10:41 pm
by Chris
Hi Franz,

Most likely this error is thrown because the method is called even before you assign the _renderer var. Also when you respond to OnPaint(), you need to use the Graphics object provided by the PaintEventArgs parameter, not create or reuse your own.

But in any case, it's much easier if you just assign the BackgroundImage property of the control to the bitmap you want to show, so everything happens automatically. Something like this:

Code: Select all

METHOD QrCode(cText AS STRING, nSize AS DWORD) AS VOID
	LOCAL panel AS Panel
	LOCAL qrEncoder AS QrEncoder
	LOCAL qrCode AS QrCode
	LOCAL renderer AS GraphicsRenderer
	LOCAL padding AS System.Drawing.Point
	LOCAL dSize AS DrawingSize

	panel := Panel{}
	panel:AutoSize := TRUE
	SELF:Controls:Add(panel)

	qrEncoder := QrEncoder{ErrorCorrectionLevel.H}
	qrCode := qrEncoder:Encode(cText)
	renderer := GraphicsRenderer{FixedModuleSize{nSize, QuietZoneModules.Two}, System.Drawing.Brushes.Black, System.Drawing.Brushes.White}
	padding := System.Drawing.Point{10, 16}
	dSize := renderer:SizeCalculator:GetSize(qrCode:Matrix:Width)
	panel:Size := System.Drawing.Size{dSize:CodeWidth + padding:X, dSize:CodeWidth + padding:Y}

	LOCAL oBitmap, oCopy AS System.Drawing.Bitmap
	BEGIN USING VAR stream := MemoryStream{}
		renderer:WriteToStream(qrCode:Matrix, ImageFormat.Bmp, stream)
		oBitmap := System.Drawing.Bitmap{stream}
	END USING
	// create a copy of the bitmap, otherwise need to keep the memory stream open till the original bitmap is no longer needed
	oCopy := System.Drawing.Bitmap{oBitmap}

	panel:BackgroundImage := oCopy
	panel:BackgroundImageLayout := System.Windows.Forms.ImageLayout.Center
.

Gma.QrCodeNet.Encoding.dll

Posted: Wed Apr 13, 2022 8:36 am
by lagraf
Hi Chris,
I implemented all 3 examples (Paint_handler, OnPaint, BackgroundImage) to show qrCode in my test app to keep it for later use in other apps.
Thank you for help!