“everything worth doing is worth doing slowly” – Mae West
Sending Bitmap to Epson printer using Delphi and ESC/POS
I have previously tried to use http://nicholas.piasecki.name/blog/2009/12/sending-a-bit-image-to-an-epson-tm-t88iii-receipt-printer-using-c-and-escpos/ and the attached Delphi translation to send a TBitmap directly to Epson TM T20, TM T80 and TM88 printers. Unfortunately it never worked.
Recently I needed to print dynamically created QR codes using the printers so it was time to revisit this. I worked directly off the C# sources provided and created a Delphi class to replicate this.
I've added this to a GIT repository on Bitbucket in case anyway needs to use it in future.
Project Home: https://bitbucket.org/bernd_summerswell/delphi_escpos_bitmap/
Example Usage:
This uses the Synaser library from Synapse to send the buffer directly to a COM Port.
uses synaser, ssESCPOSPrintBitmap; var LBuffer : string; LDevice : TBlockSerial; begin LBuffer := #27'@'; // Initialise the printer LBuffer := LBuffer + _ESCPosPrintBitmap().RenderBitmap( 'pathtobitmapfile' ); LBuffer := #29'V'#1 // Paper cut full // Send LBuffer to Printer LDevice := TBlockSerial.Create(); try LDevice.Config( 115200, 8, 'N', 1, False, False ); LDevice.Connect( 'COM7' ); LDevice.SendString( LBuffer ); finally LDevice.Free(); end; end.Read More
TDocVariant CRUD Operations
This is based on http://blog.synopse.info/post/2014/02/25/TDocVariant-custom-variant-type and the corresponding forum http://synopse.info/forum/viewtopic.php?id=1631
Create
A TDocVariant custom variant type is declared as a Variant:
var LDocVariant : Variant;
The TDocVariant can be created as an object or from a JSON string. You can use the _Obj/_ObjFast, _JSON/_JSONFast and _Arr/_ArrFast methods to create the TDocVariant.
LDocVariant := _ObjFast( [ 'name', 'bernd' ] ); LDocVariant := _JsonFast( '{ "Person": { "First" : { "name" : "bernd" } } }' ); LDocVariant := _ArrFast( [ _ObjFast( [ 'name', 'bernd' ] ), _ObjFast( [ 'name', 'bob' ] ) ] );
Read
You can access items in the TDocVariant variable dynamically:
Writeln( LDocVariant.name ); Writeln( LDocVariant.Person.First.Name ) Writeln( LDocVariant._(0).name );
Each of these will output "bernd".
A TDocVariant will also be cast as JSON string when used in place of a string, for example, using the examples above, calling the following on each respectively:
Writeln( LDocVariant );
will output the following:
{"name":"bernd"} {"Person":{"First":"bernd"}} [{"name":"bernd"},{"name":"bob"}]
For arrays you also have _Count so you can iterate through the array:
for LIndex := 0 to LDocVariant._Count - 1 do Writeln( LDocVariant._(LIndex).name );
Update
Updating items and properties is really easy:
LDocVariant.name := "Bernd"; LDocVariant.Person.First.name := "Bernd"; LDocVariant._(1).name := "Bob";
You can add objects, array items or values to existing items as well.
LDocVariant.age := 31; LDocVariant.Person.Next := _ObjFast( ['name','bob'] ); LDocVariant.Person.Next.age = 43; LDocVariant.Add( _ObjFast( [ 'name', 'ned' ] ) );
Delete
All TDocVariant variables have the Delete method to remove an item from the object or array:
LDocVariant.Delete( 'name' ); LDocVariant.Person.Delete( 'Next' ); LDocVariant.Delete( 1 );
Read More
Using TDocVariant for settings
Arnaud from Synopse has just released a great new addition to the mORMot framework. TDocVariant is custom variant type which integrates effortless with JSON.
One area that this can be implemented is for the settings of an application. Usually an INI file is the easiest way to implement settings for an application, especially when it is a small utility. INI files mean that you can quickly edit the settings without needing a special editor. Unfortunately arrays, lists and collections are difficult to store in INI files without some sort of pre-determined structure.
JSON eliminates this problem, and allows a truly flexible structure. Now you can use the TDocVariant class to easily read and write the settings as well as access them in your application.
For the snomSwitcher application, the settings are stored in the following format:
{ "PhoneSettings":{ "IP":"192.168.1.100", "Username":"admin", "Password":"admin", "PhoneType":"Snom 300" }, "Users":[ { "DisplayName":"User 1", "Account":"101", "Password":"101", "Registrar":"your.voip.provider" }, { "DisplayName":"User 2", "Account":"102", "Password":"1234", "Registrar":"your.voip.provider" }, { "DisplayName":"User 3", "Account":"101", "Password":"101", "Registrar":"your.voip.provider" } ] }
We can load the the settings from file by calling:
FSettings := _JsonFast( StringFromFile( FSettingsFilename ) );
We can then access the settings easily from anywhere in code:
Writeln( FSettings.PhoneSettings.IP ); Writeln( FSettings.Users._(1).Username );Read More
Running two instances of the same Delphi Service
Recently there was a need to run two instances of the same service written in Delphi on the same server. While you can manually changed the service name in the registry or via the "sc" command, the service will not start up correctly unless the service name matches the TService.Name.
To get around this you can pass the name of the service as a parameter to the executable and dynamically set the Name and DisplayName properties when the service is created.
function GetParamValue( const ASwitch: string; var AValue: string ): Boolean; var LIndex : Integer; begin Result := False; for LIndex := 1 to ParamCount do if ( StartsText( ASwitch, ParamStr( LIndex ) ) ) then begin Result := True; AValue := ReplaceText( ParamStr( LIndex ), ASwitch, '' ); end; end; procedure TYourService.ServiceAfterInstall(Sender: TService); var LRegistry : TRegistry; begin LRegistry := TRegistry.Create(); try LRegistry.RootKey := HKEY_LOCAL_MACHINE; if ( LRegistry.OpenKey( 'SYSTEMCurrentControlSetServices' + Name, False ) ) then begin LRegistry.WriteString( 'ImagePath', ParamStr(0) + ' /name=' + Name ); end; finally LRegistry.Free(); end; end; procedure TYourService.ServiceCreate(Sender: TObject); var LNewName : string; begin if ( GetParamValue( '/name=', LNewName ) ) then begin Name := LNewName; DisplayName := LNewName; end; end;
The AfterInstall event makes sure that the /name parameter is passed to the service each time it starts up.
This should make your Delphi Service more flexible!
Read More