Fixing permanently the TWinControl 64 character limit

Once you have the TWinControl descendant with the class name longer than 64 characters you cannot construct it:

Related SO question: https://stackoverflow.com/questions/14446979/why-do-i-get-access-violations-when-a-controls-class-name-is-very-very-long

Related QC entry: http://qc.embarcadero.com/wc/qcmain.aspx?d=112101

The suggested solution does the local override of the CreateParams method. But you can do this permanently for whole VCL application if you wish so by adding the following unit to your project (it requires the beautiful Detours library):

unit uWinControlClassNameFix;

interface

implementation

uses
  DDetours,
  Vcl.Controls,
  System.SysUtils,
  System.Hash;

type
  TWinControlEx = class(TWinControl);

  TCreateParamsMethod = procedure (var AParams: TCreateParams) of object;

  TCreateParamsEx = record
    SourceParams: TCreateParams;
    Overflow: array [0..4096] of Char;
  end;

var
  FOldCreateParams: Pointer;

procedure CreateParamsFix(Sender: TObject; var AParams: TCreateParams);
const
  HASH_LEN = 8;
var
  LParams: TCreateParamsEx;
  LHash: String;
  LInherited: TCreateParamsMethod;
begin
  TMethod(LInherited).Code := FOldCreateParams;
  TMethod(LInherited).Data := Sender;

  if Length(Sender.ClassName) < Length(AParams.WinClassName) then
    begin
      LInherited(AParams);
      Exit;
    end;

  LParams := Default(TCreateParamsEx);
  LParams.SourceParams := AParams;

  LInherited(LParams.SourceParams);

  LHash := IntToHex(THashBobJenkins.GetHashValue(LParams.SourceParams.WinClassName), HASH_LEN);
  Move(LHash[1], LParams.SourceParams.WinClassName[High(LParams.SourceParams.WinClassName) - HASH_LEN], HASH_LEN * SizeOf(Char));
  LParams.SourceParams.WinClassName[High(LParams.SourceParams.WinClassName)] := #0;
  AParams := LParams.SourceParams;
end;

begin
 InterceptCreate(@TWinControlEx.CreateParams, @CreateParamsFix, FOldCreateParams);
end.

P.S. I have used the code of Cosmin Prund for making this possible with some adjustments I believed are more compact and readable. The code is tested on Delphi Berlin 10.1.2. Feel free to use/modify and whatever you want with this 😉

But make sure you handle the use of FindWindow or similar API where you use the class name – because it will be different from actual ClassName!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s