Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to use QR barcodes in an easy way 3

Status
Not open for further replies.

wibenji

Programmer
Oct 16, 2017
21
0
0
DE
We were using FoxbarcodeQR for the longest time, but just realized that it´s QR capabilities are capped to 255 characters. Is anyone using something free/cheap that´s comparable to Foxbarcode?

Best regards Benjamin
 
I see.

Project descroiption said:
BarCodeLibrary.dll has the limitation of encoding only up to 255 characters, so FoxBarcodeQR also has this limitation.

I first thought you'd fallen for a string literal limit of VFP and not a general String length limit, which is much higher.
But the limit is described as a dependency of a DLL this is based on.

No, I don't have an idea, but I likely may need something more capable, too. The QR Code specifications limit a QR Code to 2953 Bytes of net embeddable information. So it's not a QR specification limit.

Bye, Olaf.

Olaf Doschke Software Engineering
 
you could switch to a web based QR generator?

e.g.
[pre]
set library to vfpconnection.fll additive
httpsget("
httpsget("[/pre]


google has a 2k limit


of course this runs the risk that one day the api may get deprecated.

hth

n
 
Indeed possible, but for a POS system that should be able to continue working when the internet connection is lost, I'd need an offline solution. In large amounts any online service could collect too much information, so it should remain a DLL. Currently, I simply hope the 255 character limit doesn't really hit me.

Bye, Olaf.

Olaf Doschke Software Engineering
 
That´s a great solution Nigel, but we need an solution that´s working offline. I didn´t say that in my initial post. Maybe someone else has an idea
 
Thanks Nigel,

with best intentions. Searching something also new to me I have to first test to work is easy. ActiveX should always work with VFP, but always has the redistribution overhead. I'd even rather take an assembly and Rick Strahls .net Bridge. That's also using COM visibility, but generates it on the fly. And I think I'll use this.


Bye, Olaf.

Olaf Doschke Software Engineering
 
Are you just after a barcode, or one on a report or what?

I have something that makes a .jpg of anything you want in a QR code - you can then drop that onto a pdf easily enough

Is that the kind of thing you are looking for?

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
I print POS receipts, there are very specific opes commands for that and indeed I just need a picture file. I need to look what's supported, I think just JPG or BMP/GIF, but I can tell you more on Monday.
Only QR, normal Barcodes are covered by the OPOS printer.

But sorry for the hijacking, of course, the question also goes to wibenji.

I think I get along with what QRCoder gives me. Let me see if that DLL is easy enough to use...

Bye, Olaf.

Olaf Doschke Software Engineering
 
Sorry, I use FoxbarcodeQR - I forgot, and didn't reach the limitation.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
Well, it comes down to fiscal signatures including a lot of information. It was manageable without FoxBarcdeQR as a DLL I used for Austria included QR Code image generation. For Germany it'll be different. I think they managed to allow printing on usual rather slim receipts. not as Deutsche Bahn Tickets that have to be printed in letter size and are scanned by an equally large scanner that lights up the whole train wagon when your ticket is scanned.

At least that still was so in the 2010s. I think now your phone display is sufficient to display such codes and there are other means, even the simplest paper ticket is often still the simpllest.

I still hope I won't even need to exceed the limit, as I think it'll be unbearable to print small and still scannable. The DLL I used for Austria actually had the option for two QR codes, one larger with more error correction pixels, though. If irony would fit here the smaller one with less error correction would have scanned better, but indeed correction codes worked out fine.

Bye, Olaf.

Olaf Doschke Software Engineering
 
I got my way into the QRCoder assembly
The assembly itself fails to be used with Rick Strahls .NET Bridge. I think it's because of too convoluted overloading of methods.
But it's not hard to build a helper assembly for VFP using the QRCoder Nuget package and then essentially the 4 lines of code given as getting started example.

Code:
using System;
using System.Drawing;
using QRCoder;

namespace VFPQRCoder
{
    public class VFPQRCode
    {
        private QRCodeGenerator _QrGen;

        public VFPQRCode()
        {
            _QrGen = new QRCodeGenerator();
        }

        public void CreateImage(string QrData, string FileName)
        {
            System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
            QRCodeData QrCodeData = _QrGen.CreateQrCode(enc.GetBytes(QrData), QRCodeGenerator.ECCLevel.Q);
            QRCode QrCode = new QRCode(QrCodeData);
            QrCode.GetGraphic(20).Save(FileName);
        }
    }
}

This is just basic usage without making use of all the features the QRCoder assembly offers in terms of payload definitions etc, but it's easy to extend. For example not hardcode the ECC-level but make that another parameter. What's essential: I tested more than 256 characters string and that's not a problem.

My phone scans the results, for example, this one (that's shorter than 255 bytes, but includes non-ASCII characters like the € sign and umlauts, which are double-byte UTF-8 characters not in the overlap of the first UTF-8 characters with ASCII, just to see that it decodes correctly. (Actual image size was 820x820, I sized it down, and I assume to control that also just needs a bit tweaking).

testutf8_waxopt.png


Bye, Olaf.

Olaf Doschke Software Engineering
 
Just by the way, there is a top banner message on stating this API is deprecated and instead Google Charts should be used.

This bears a few questions: Charts is a much less specific topic, where are QR codes in there? But what's more annoying to you is that they make it a selling point that this API isn't only free but guarantees three years' backward compatibility. I personally would guarantee a longer technical working for a DLL or OCX just from the usual experience of how long legacy software works. And I think the data privacy concern is even a stronger constraint for more cases than you deem it unimportant. Google may not fish all information out of the use of a QR Code generation of every POS receipt, but that they could is concern enough to not use a cloud service like that.

At many times I was standing with the way modern development doesn't only mean shorter release cycles as an advantage for faster progress, but also a pressure on keeping dependencies in sync with current versions and incompatibilities. And here you see the variety of choices will make it easy to switch in three years if it's necessary. But especially a topic like QR codes you develop for a certain central need you don't want to need to come back to as an API you use changes, I'd always pick something that works local for such reasons.

And it's never been an issue that you depend on an older C++ runtime or .net framework. QRCoder does even target .NET standard 1.0, if you need it in a .NET legacy application. It makes a good impression in that aspect. Also what flaws some ActiveX controls we still use and share with the legacy VB community are only deprecated for modern UI reasons, if at all. Not for technical reasons. And that's even lesser a concern for a pixel bitmap that looks like outdated technology from the start anyway.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Olaf I'm looking for the exact same thing. So no problem for hijacking :p.
I'll take a look at your last post when I have the time.
 
So i got this working with
Code:
LOCAL qrcoder as VFPQRCoder.VFPQRCode
qrcoder = CREATEOBJECT("VFPQRCoder.VFPQRCode")
qrcoder.CreateImage(LC_CSV,"C:/arbeiten/img.jpg")
but this means i have to register the .dll file. Is there a way to use the CreateImage() method with a
Code:
DECLARE CreateImage in vfpqrcode.dll
CreateImage()
statement? Because right now it says "Cannot find entry point CreateImage in the DLL" when trying this way.
 
What is the problem with registering the dll?

You can easily incorporate the dll into your exe, extract it at run time and then register it using the code below:

To incorporate the dll, make a free table within your project with two columns, one for an identfier and the other as a binary blob, pop a record in it
complete the identifier (in case you want more binaries later) and use replace mybinary with filetostr("my.dll") to get the binary field populated.
Then when you start the app, write the .dll out to the current folder using strtofile() and register it.


Code:
FUNCTION REGSVR
	* Author.....: William GC Steinford
	* Date.......: Jan 23, 2003
	* Abstract...: Programmatically Register, Unregister an OCX control
	LPARAMETERS PCOCX,PLREG
	LOCAL LLREG
	LLREG = IIF( PCOUNT()>1, PLREG, .T. ) && Default to register

	DECLARE INTEGER LoadLibrary IN kernel32 AS LoadLibraryA STRING lpLibFileName

	LOCAL LHLIB
	LHLIB = LOADLIBRARYA( PCOCX )

	IF (LHLIB < 32) && HINSTANCE_ERROR
		RETURN "ERROR: Could not Load Library "+PCOCX
	ENDIF

	*// Find the entry point.
	DECLARE INTEGER GetProcAddress IN kernel32 INTEGER hModule, STRING lpProcName

	IF LLREG
		LPREGPROC = GETPROCADDRESS(LHLIB, 'DllRegisterServer')
		IF LPREGPROC>0 && Procedure exists!
			DECLARE INTEGER DllRegisterServer IN &pcOCX
			**AS OcxReg
			LNRES = DLLREGISTERSERVER()
			IF LNRES=0
				RETURN "SUCCESS"
			ELSE
				RETURN "ERROR: DllRegisterServer returned "+TRAN(LNRES)
			ENDIF
		ELSE
			* //unable to locate entry point
			RETURN "ERROR: Library "+PCOCX+" has no entry point for DllRegisterServer"
		ENDIF
	ELSE && Unregister
		LPREGPROC = GETPROCADDRESS(LHLIB, 'DllUnregisterServer')
		IF LPREGPROC>0 && Procedure exists!
			DECLARE INTEGER DllUnregisterServer IN &pcOCX
			**AS OcxUnReg
			LNRES = DLLUNREGISTERSERVER()
			IF LNRES=0
				RETURN "SUCCESS"
			ELSE
				RETURN "ERROR: DllUnregisterServer returned "+TRAN(LNRES)
			ENDIF
		ELSE
			* //unable to locate entry point
			RETURN "ERROR: Library "+PCOCX+" has no entry point for DllUnregisterServer"
		ENDIF
	ENDIF
ENDFUNC

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
The idea is to use Rick Strtahls bridge on the helper assembly, as the QRCoder.dll seems to evade being controlled by proxy the bridge generates, the VFPQRCoder is that proxy now. So you can avoid registering the self-made helper assmenbly by using Rick Strahls .NET bridge. With the much simpler class structure of just a single method in one parameterization, the bridge has no problems, it only has problems with the much more complex original Qrcoder.DLL assembly, but with the helper that won't become a topic of the bridge.

Maybe Rick Strahl could look into what goes wrong there, but if his bridge doesn't work on a complex assembly, it does work on simpler assemblies and this is the reason I made the helper assembly. To be able to use the bridge.

Otherwise, I could also set some methods and properties COM visible to not need the bridge. But then you need registering.

It's a bit complex logic, but it's relatively easy, just move the goal post a little. The bridge really is a good metaphor you can think of more literally, when you extend the .NET world with a place the bridge can reach, you also can use attached areas of the -NET world, the bridge only needs to be able to reach one landmark of the .NET world, it won't create proxy code to also use System.Drawing, for example, that happens exclusively in the VFPQRCoder when I call Save() and within QRCoder,DLL, when it generates the QRCode image.

The other viable solution would of course is to register that VFPQRCode DLL now, which in turn can use QRCoder.dll unregistered (as it has no COM visibility itself. The original .NET solution owner also suggests using .NET COM visibility as a solution. I could get his solution to compile, I tried to tweak away some of the overloads I didn't need, but still couldn't get it to work with the bridge and didn't want COM visibility as the end solution.

So actually the only goal of the helper assembly is to make it usable for the bridge and avoid a COM visible solution. You can't create assembly DLLs usable via DECLARE. That's just vice versa of why you also can't create VFP DLLs that are usable via declare. Assemblies are closer to COM Servers, just with .NET specific interface and ability to reference them in other .NET projects. Assemblies just keep out of the OLE world but are very similar, which reagasm also suggests. You just have a development platform that allows inclusion of assemblies in projects as part of the project, quite like libs are for C++, so assembly namespaces and "type libs" allow easier code integration into further projects with just DLL inclusion, not heaving over all project source code, too.

Bye, Olaf.

Olaf Doschke Software Engineering
 
GriffMG said:
What is the problem with registering the dll?
Short answer: admin rights.

But thanks anyway for your code, maybe i can use this sometime in the future

Also thanks Olaf for your explanation with the .net Bridge. I´ll have to look deeper into that.
 
Griff, just one question about registering DLLs with such routines:

Sice Vista, any effort to register something is rerouted to a virtual registry branch and if OLE classes then work, they only can do for the user having these keys. I still think this doesn't work, only when you accept another requirement you can add through manifest: To let your exe require to be run with admin privileges aka elevated. And I like to avoid that need. I don't want an end user application to require him to be admin.

And I don't have customers running all XP or older systems for which such programmatic registering also works non administrative.

It would perhaps be acceptable if all users will need to have their own virtual keys and that works, but I don't think it really does, does it, Griff?

I think this method is broken since Vista.

Last time I remember someone needing registering was just recently with Chilkat solutions. And yes, there is an easy to use bat file available. But isn't it preferable to not need registering? Also not need to put assembles into the global assembly cache (GAC) when they only are special purpose extensions for your applications? I don't see a protection in all this registering need so OLE can find its classes. It doesn't prevent us developers from being very free to do anything on a system within the EXEs we're able to build. And it's only hardship to be able to easier integrate third party libraries in some form of DLL. I would easily do without OLEs class finding mechanism and and reg free usage of them through manifests is another solution, AFAIR that only works for EXEs using the OLE classes.

Bye, Olaf.

Olaf Doschke Software Engineering
 
By the way, bridge usage for the VFPQRCoder assembly now:

1. put all the files for Rick Strahls' bridge, qrcoder.dll, vfpqrcoder.dll and the following PRG into one folder
2. CD into it (adjust line 2 in the PRG)

Code:
* QRCoder usage
Cd <<qrcoderbridgefolder>> && adjust
Do wwDotNetBridge

LOCAL loBridge as wwDotNetBridge
loBridge = CreateObject("wwDotNetBridge","V4",.f.)
loBridge.LoadAssembly("VFPQRCoder")

Local loVFPQRCoder
loVFPQRCoder = loBridge.CreateInstance('VFPQRCoder.VFPQRCode')
loVFPQRCoder.CreateImage("Test of VFPQRCoder - Äöüßäöüß@€",ADDBS(GETENV("TEMP"))+"testutf8.png")

No need for registering, neither QRCoder.dll nor VFPQrcoder.dll, only target VFPQRcode.dll to use .NET Framework 4.0, the bridge uses that as default. you could adjust which .NET framework it uses at runtime. That's the part needing to dig a bit deeper into the bridge. Besides loading assemblies and instancing unregistered assembly classes, it also has an InvokeMethod method, where a direct method call doesn't work, but that mechanism also didn't work for the pure QRCoder.dll.

This can be a little bit streamlined as finally all is included in the final EXE anyway (except all the DLL files, I recommend putting them to the EXE = main project folder). So in terms of sorting file type in the project folder structure, you don't need to pull DLLs and PRGs into a libs folder just to get it going within the IDE and in debug sessions of your project, too.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top