You do not need to change the source of the VCL to follow the German example; you can simply fix the code execution time.
DISCALMER I wanted to test my code on Delphi 6, but my installation of Delphi 6 did not start this morning, so it is tested only on Delphi XE!
But I think this will work on Delphi 6 as well.
First you need a class to fix the execution time of the method:
unit PatchU; interface type pPatchEvent = ^TPatchEvent; // "Asm" opcode hack to patch an existing routine TPatchEvent = packed record Jump: Byte; Offset: Integer; end; TPatchMethod = class private PatchedMethod, OriginalMethod: TPatchEvent; PatchPositionMethod: pPatchEvent; public constructor Create(const aSource, aDestination: Pointer); destructor Destroy; override; procedure Restore; procedure Hook; end; implementation uses Windows, Sysutils; { TPatchMethod } constructor TPatchMethod.Create(const aSource, aDestination: Pointer); var OldProtect: Cardinal; begin PatchPositionMethod := pPatchEvent(aSource); OriginalMethod := PatchPositionMethod^; PatchedMethod.Jump := $E9; PatchedMethod.Offset := PByte(aDestination) - PByte(PatchPositionMethod) - SizeOf(TPatchEvent); if not VirtualProtect(PatchPositionMethod, SizeOf(TPatchEvent), PAGE_EXECUTE_READWRITE, OldProtect) then RaiseLastOSError; Hook; end; destructor TPatchMethod.Destroy; begin Restore; inherited; end; procedure TPatchMethod.Hook; begin PatchPositionMethod^ := PatchedMethod; end; procedure TPatchMethod.Restore; begin PatchPositionMethod^ := OriginalMethod; end; end.
Then we need to use it. Pau listview on the form and then on this code:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, PatchU; type TListView = class(ComCtrls.TListView) protected procedure ColClick(Column: TListColumn); override; end; TForm1 = class(TForm) ListView1: TListView; private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses CommCtrl; var ListView_UpdateColumn_Patch: TPatchMethod; type THooked_ListView = class(TListView) procedure HookedUpdateColumn(AnIndex: Integer); end; { TListView } procedure TListView.ColClick(Column: TListColumn); var Header: HWND; Item: THDItem; NewFlag: DWORD; begin Header := ListView_GetHeader(Handle); ZeroMemory(@Item, SizeOf(Item)); Item.Mask := HDI_FORMAT; Header_GetItem(Header, Column.Index, Item); if Item.fmt and HDF_SORTDOWN <> 0 then NewFlag := HDF_SORTUP else NewFlag := HDF_SORTDOWN; Item.fmt := Item.fmt and not(HDF_SORTUP or HDF_SORTDOWN); // remove both flags Item.fmt := Item.fmt or NewFlag; Header_SetItem(Header, Column.Index, Item); inherited; end; { THooked_ListView } procedure THooked_ListView.HookedUpdateColumn(AnIndex: Integer); begin ListView_UpdateColumn_Patch.Restore; try UpdateColumn(AnIndex); finally ListView_UpdateColumn_Patch.Hook; end; end; initialization ListView_UpdateColumn_Patch := TPatchMethod.Create(@TListView.UpdateColumn, @THooked_ListView.HookedUpdateColumn); finalization ListView_UpdateColumn_Patch.Free; end.
As you can see, my demo is very inspired by the code you posted. I just deleted global vars. In my example, I do nothing but call the original procedure, but you must call the code from the Geraman example.
So basically I just wanted to show you how you can change the VCL without editing the source code. That should make you go.