The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,862 other subscribers

Archive for the ‘Delphi’ Category

Delphi – The use of AlignAttribute: indicate the alignment of a field

Posted by jpluimers on 2020/09/25

Great answer by Stefan Glienke at [WayBack] What’s the use of AlignAttribute? The documentation only says Internal use only.  – 丽丽乌克 – Google+:

It forces the element it annotates to be aligned like specified – valid values are the same as for $A (1, 2, 4, 8, 16)

Example:

{$A4}
type
  TMyRecordA = record
    x: Integer;
    y: Int64;
  end;

  TMyRecordB = record
    x: Integer;
    [Align(8)]
    y: Int64;
  end;
var
  a: TMyRecordA;
  b: TMyRecordB;
  offset: Integer;
begin
  offset := PByte(@a.y) - PByte(@a);
  Writeln(SizeOf(a));
  Writeln(offset);
  offset := PByte(@b.y) - PByte(@b);
  Writeln(SizeOf(b));
  Writeln(offset);

this will output:
12
4
16
8

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

Delphi XE6 .. 10.1 Berlin truncating non-VCL-control texts to 256 characters when styled

Posted by jpluimers on 2020/09/23

As of Delphi XE6, the VCL also styles non-VCL controls, but this truncates the texts to 256 characters, for instance in non-balloon hints. This is fixed in Delphi 10.2 Berlin, by making the buffer dynamic and switching obtaining those texts from using GetWindowText to sending a WM_GETTEXT message.

A fix for Delphi XE6..10.1 Berlin is at gitlab.com/wiert.me/public/delphi/DelphiVclStylesAndHintText, with many thanks to Stefan Glienke who based the patch on the ones used in Spring4D. I think they are similar to the ones in [Archive.is] VCL Fix Pack 1.4 | Andy’s Blog and Tools.

The Old New Thing explains the difference between GetWindowText and WM_GETTEXT in [WayBack] The secret life of GetWindowText – The Old New Thing. TL;DR:

GetWindowText strikes a compromise.

  • If you are trying to GetWindowText() from a window in your own process, then GetWindowText() will send the WM_GETTEXT message.
  • If you are trying to GetWindowText() from a window in another process, then GetWindowText() will use the string from the “special place” and not send a message.

So for your own process, it does not matter as GetWindowText uses WM_GETTEXT.

–jeroen

Related:

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development, The Old New Thing, Windows Development | Leave a Comment »

Can we truly assert that an array returned from a function is always a true copy?

Posted by jpluimers on 2020/09/23

The answer is no: [WayBack] Hi all, Can we truly assert that an array returned from a function is always a new true copy and that this is guaranteed to not change in between compil… – Ugochukwu Mmaduekwe – Google+

From Primož book and comment:

Depending on how you create this array.

For example, the following code outputs 42, not 17.

program Project142;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils;

function Bypass(const a: TArray<integer>): TArray<integer>;
begin
Result := a;
end;

var
a, b: TArray<integer>;

begin
SetLength(a, 1);
a[0] := 17;
b := Bypass(a);
a[0] := 42;
Writeln(b[0]);
Readln;
end.

You can use `SetLength(arr, Length(arr))` to make array unique. Changing Bypass to the following code would make the test program emit 17.

function Bypass(const a: TArray<integer>): TArray<integer>;
begin
Result := a;
SetLength(Result, Length(Result));
end;

–jeroen

Posted in Delphi, Development, Software Development | 1 Comment »

Delphi Gem of the day: putting “reintroduce” on a destructor. destructor…

Posted by jpluimers on 2020/09/22

A nice thread with examples of all the things you should not do with the Delphi reintroduce keyword:

[WayBack] Delphi Gem of the day: putting “reintroduce” on a destructor.     destructor Destroy(); reintroduce; overload; In our case all we got was a memory lea… – Moz Le – Google+

The problem is that in the original (archived) documentation, not much waring is given around using reintroduce; it is merely posted as solving a nuisance to absolve a compiler warning.

When using it though, all your alarm systems should go off at their highest level as you break polymorphism, but through careful language usage, the pattern you hide can still be used.

One day I will write a longer blog article on this.

Documentation:

A decade of progress has not changed much on this documentation apart from some nicer formatting:

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

Delphi: TInvokableClassRegistryHelper.GetInterfaceNamespace as the opposite of TInvokableClassRegistry.RegisterInterface

Posted by jpluimers on 2020/09/17

A while ago, I needed the opposite of InvRegistry.RegisterInterface(TypeInfo(MySoapInterfacePortType, 'urn:myURN', 'utf-8');, so instead of registering an interface with a namespace URN, obtain the URN by passing the interface inverting [WayBack] TInvokableClassRegistry.RegisterInterface.

This is the class helper I wrote:

type
  TInvokableClassRegistryHelper = class helper for TInvokableClassRegistry
  public
    function GetInterfaceNamespace(Info: PTypeInfo): string;
  end;

function TInvokableClassRegistryHelper.GetInterfaceNamespace(Info: PTypeInfo): string;
var
  InfoGuid: TGUID;
begin
  // call like `Result := InvRegistry.GetInterfaceNamespace(TypeInfo(MySoapInterfaceType));`
  InfoGuid := GetTypeData(Info)^.Guid; // uses TypInfo; see https://stackoverflow.com/questions/8439246/is-it-possible-to-get-the-value-of-a-guid-on-an-interface-using-rtti
  Result := GetNamespaceByGUID(InfoGuid);
end;

It would have been a lot easier if TInvokableClassRegistry.GetIntfIndex has been public, because then [WayBack]TInvokableClassRegistry.GetRegInterfaceEntry could have been used.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, SOAP/WebServices, Software Development | Leave a Comment »

FireDAC can do DBMS back-end conditional SQL via Conditional Substitution

Posted by jpluimers on 2020/09/17

Though the field-types mentioned in the problem and solution are equal (so either is wrong), the solution in [WayBackI have a little problem with FireDAC and the TStringField and TWideStringField design time generation… – Juan C. Cilleruelo – Google+ pointed out by Jeff Weir is interesting: FireDAC supports conditionals that depend on the DBMS back-end, so you can differentiate between them.

The feature is called Conditional Substitution and has been present ever since AnyDAC (which got bought by Embarcadero, transformed into FireDAC, then after Idera bought Embarcadero, the main developer got pink-slipped).

The AnyDAC documentation is in the wayback machine, though you have to disable the onload event in order to read it.

The [Archive.is] XE5: Preprocessing Command Text (FireDAC) – RAD Studio documentation is not much different from the current state [Archive.is].

More background reading is at [WayBack] www.freepascal.org/~michael/articles/anydac2/anydac2.pdf and Cary Jensen covered it in his 2017 course on FireDAC of which you can see the free ToC.

Example from that thread:

SELECT ART.CD_ITEM                ,
       ART.CD_FAMILY              ,
       ART.CD_CATALOGUE           ,
       CAT.DS_CATALOGUE           ,
       FAM.DS_FAMILY              ,
{IF MSSQL}
       CASE WHEN EXISTS(SELECT 1 FROM CONFIGURATIONS COM WHERE COM.CD_PARENT = ART.CD_ITEM)
          THEN CAST('Y' AS NVARCHAR) 
          ELSE CAST('N' AS NVARCHAR) 
       END HAS_CONFIGURATION      ,
{fi}
{IF FIREBIRD}
       CASE WHEN EXISTS(SELECT 1 FROM CONFIGURATIONS COM WHERE COM.CD_PARENT = ART.CD_ITEM)
          THEN 'Y'  
          ELSE 'N'  
       END HAS_CONFIGURATION      ,
{fi}
       ART.DS_ITEM                ,
       ART.CD_TAX                 ,
       TAX.DS_TAX                 ,
       TAX.PRC_TAX               ,
...

Given the problem statement, the casts likely should have been VARCHAR instead of NVARCHAR, but the construct can be very powerful.

–jeroen

Posted in Database Development, Delphi, Development, Firebird, InterBase, Software Development, SQL, SQL Server | Leave a Comment »

GitHub – gabr42/MultiBuilder: Runs multiple programs in parallel, shows results

Posted by jpluimers on 2020/09/17

Given a Delphi build-VM with enough CPU cores to run many builds in parallel: [WayBack] GitHub – gabr42/MultiBuilder: Runs multiple programs in parallel, shows results.

Much more on this at [WayBack] The Delphi Geek: Introducing MultiBuilder.

Via: [WayBackParallel build/test systems made easy(er) – Primož Gabrijelčič – Google+

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

Using Delphi for jiggling the mouse – twm’s blog

Posted by jpluimers on 2020/09/16

To prevent a screen-saver from kicking in [WayBack] jiggling the mouse – twm’s blog:

My solution then is this procedure:

procedure JiggleMouse;
var
  Inpt: TInput;
begin
  Inpt.Itype := INPUT_MOUSE;
  Inpt.mi.dx := 0;
  Inpt.mi.dy := 0;
  Inpt.mi.mouseData := 0;
  Inpt.mi.dwFlags := MOUSEEVENTF_MOVE;
  Inpt.mi.time := 0;
  Inpt.mi.dwExtraInfo := 0;
  SendInput(1, Inpt, SizeOf(Inpt));
end;

Call it in regular intervals and the screen saver will not start.

This is now (or soon will be) in the u_dzOsUtils unit which is part of my dzlib utility library.

–jeroen

Posted in Delphi, Development, Power User, Software Development, Windows | 1 Comment »

Delphi, soap and wrapping values in cdata – Stack Overflow

Posted by jpluimers on 2020/09/15

For my link archive: [WayBack] Delphi, soap and wrapping values in cdata – Stack Overflow

–jeroen

Posted in Delphi, Development, SOAP/WebServices, Software Development, XML/XSD | Leave a Comment »

Reminder to self: iocp-delphi/ThreadPool.pas at master · tondrej/iocp-delphi · GitHub

Posted by jpluimers on 2020/09/15

If I ever need a thread pool in Delphi, then I need to look at this class: [WayBack] iocp-delphi/ThreadPool.pas at master · tondrej/iocp-delphi · GitHub.

Via: [WayBack] Don’t lose time with a known Delphi bug affecting TParallel.Join Don’t lose time with a known Delphi bug affecting TParallel.Join; Ondrej Kelle – Google+

Full repository: [WayBack] GitHub – tondrej/iocp-delphi: Windows I/O Completion Port wrapper class for Delphi and Free Pascal. Wide support too:

  • compilers: Delphi 7 or higher, Free Pascal 3.0.4 or higher
  • targets: Windows XP/Windows Server 2003 or higher, both 32 and 64-bit

–jeroen

Posted in Delphi, Development, Software Development | 1 Comment »