home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 October
/
Chip_2001-10_cd1.bin
/
zkuste
/
delphi
/
kompon
/
d123456
/
ALIGRID.ZIP
/
AH_TOOL.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
2001-06-04
|
34KB
|
1,157 lines
unit ah_tool;
{ Copyright 1995-200 Andreas H÷rstemeier Version 1.1 2001-06-04 }
{ this utility functions are public domain. They are used by several of my }
{ components. In case you have several version of this file always use the }
{ latest one. Please check the file readme.txt of the component you found }
{ this file at for more detailed info on usage and distributing. }
(*@/// interface *)
interface
(*$b- *)
(*$i ah_def.inc *)
uses
(*$ifdef delphi_1 *)
winprocs,
wintypes,
(*$else *)
windows,
(*$endif *)
messages,
sysutils,
classes,
controls,
forms;
(*@/// String utility functions *)
{ Find n'th occurence of a substring, from left or from right }
function posn(const s,t:string; count:integer):integer;
{ Find the n'th char unequal from left or from right }
function poscn(c:char; const s:string; n: integer):integer;
{ Exchange all occurances of a string by another (e.g. ,->.) }
function exchange_s(const prior,after: string; const s:string):string;
{ Delphi 1 didn't know these, but they are useful/necessary for D2/D3 }
(*$ifdef delphi_1 *)
function trim(const s:string):string;
procedure setlength(var s:string; l: byte);
(*$endif *)
{ Write a string into a stream }
procedure String2Stream(stream:TMemorystream; const s:string);
(*@\\\0000001101*)
{ The offset to UTC/GMT in minutes of the local time zone }
function TimeZoneBias:longint;
{ Convert a string to HTML - currently only for latin 1 }
function text2html(const s:string):string;
{ Why are these not in the language itself? }
function min(x,y: longint):longint;
function max(x,y: longint):longint;
(*@/// Create a windows HWnd avoiding the stuff from forms *)
type
TWndProc = procedure (var Message: TMessage) of object;
function AH_AllocateHWnd(Method: TWndProc): HWND;
procedure AH_DeallocateHWnd(Wnd: HWND);
(*@\\\*)
(*@/// The routines to make the applications events use a list of methods *)
(*$ifndef delphi_ge_3 *)
procedure AddShowHintProc(proc:TShowHintEvent);
procedure RemoveShowHintProc(proc:TShowHintEvent);
(*$endif *)
procedure AddIdleProc(proc:TIdleEvent);
procedure RemoveIdleProc(proc:TIdleEvent);
(*@\\\*)
(*@/// Make Stream and Clipboard work together *)
procedure Stream2Clipboard(stream:TStream; format:integer);
procedure Clipboard2Stream(stream:TStream; format:integer);
(*@\\\*)
(*@/// Windows Resources and Languages *)
(*$ifdef delphi_gt_1 *)
function LoadStrEx(id:word; languageid: word):string;
(*$endif *)
function LoadStr(id:word):string;
(*@\\\*)
function ScrollBarVisible(control: TWinControl; vertical: boolean):boolean;
(*@\\\0000002501*)
(*@/// implementation *)
implementation
(*@/// Some string utility functions *)
(*@/// function posn(const s,t:string; count:integer):integer; *)
function posn(const s,t:string; count:integer):integer;
{ find the count'th occurence of the substring,
if count<0 then look from the back }
var
i,h,last: integer;
u: string;
begin
u:=t;
if count>0 then begin
result:=length(t);
for i:=1 to count do begin
h:=pos(s,u);
if h>0 then
u:=copy(u,pos(s,u)+1,length(u))
else begin
u:='';
inc(result);
end;
end;
result:=result-length(u);
end
else if count<0 then begin
last:=0;
for i:=length(t) downto 1 do begin
u:=copy(t,i,length(t));
h:=pos(s,u);
if (h<>0) and (h+i<>last) then begin
last:=h+i-1;
inc(count);
if count=0 then BREAK;
end;
end;
if count=0 then result:=last
else result:=0;
end
else
result:=0;
end;
(*@\\\*)
(*@/// function exchange_s(const prior,after: string; const s:string):string; *)
function exchange_s(const prior,after: string; const s:string):string;
var
h,p: integer;
begin
result:=s;
p:=length(prior);
while true do begin
h:=pos(prior,result);
if h=0 then BREAK;
result:=copy(result,1,h-1)+after+copy(result,h+p,length(result));
end;
end;
(*@\\\*)
(*@/// function poscn(c:char; const s:string; n: integer):integer; *)
function poscn(c:char; const s:string; n: integer):integer;
{ Find the n'th occurence of a character different to c,
if n<0 look from the back }
var
i: integer;
begin
if n=0 then n:=1;
if n>0 then begin
for i:=1 to length(s) do begin
if s[i]<>c then begin
dec(n);
result:=i;
if n=0 then begin
EXIT;
end;
end;
end;
end
else begin
for i:=length(s) downto 1 do begin
if s[i]<>c then begin
inc(n);
result:=i;
if n=0 then begin
EXIT;
end;
end;
end;
end;
poscn:=0;
end;
(*@\\\*)
(*@/// function filename_of(const s:string):string; *)
function filename_of(const s:string):string;
var
t:integer;
begin
t:=posn('\',s,-1);
if t>0 then
result:=copy(s,t+1,length(s))
else begin
t:=posn(':',s,-1);
if t>0 then
result:=copy(s,t+1,length(s))
else
result:=s;
end;
end;
(*@\\\*)
(*$ifdef delphi_1 *)
(*@/// function trim(const s:string):string; *)
function trim(const s:string):string;
var
h: integer;
begin
(* trim from left *)
h:=poscn(' ',s,1);
if h>0 then
result:=copy(s,h,length(s))
else
result:=s;
(* trim from right *)
h:=poscn(' ',result,-1);
if h>0 then
result:=copy(result,1,h);
end;
(*@\\\*)
(*@/// procedure setlength(var s:string; l: byte); *)
procedure setlength(var s:string; l: byte);
begin
s[0]:=char(l);
end;
(*@\\\*)
(*$endif *)
(*@/// procedure String2Stream(stream:TMemorystream; const s:string); *)
procedure String2Stream(stream:TMemorystream; const s:string);
begin
stream.write(s[1],length(s));
end;
(*@\\\*)
(*@\\\*)
(*@/// function min(x,y: longint):longint; *)
function min(x,y: longint):longint;
begin
if x<y then result:=x
else result:=y;
end;
(*@\\\*)
(*@/// function max(x,y: longint):longint; *)
function max(x,y: longint):longint;
begin
if x>y then result:=x
else result:=y;
end;
(*@\\\*)
(*@/// function TimeZoneBias:longint; // in minutes ! *)
function TimeZoneBias:longint;
(*@/// 16 bit way: try a 32bit API call via thunking layer, if that fails try the TZ *)
(*$ifdef delphi_1 *)
(*@/// function GetEnvVar(const s:string):string; *)
function GetEnvVar(const s:string):string;
var
L: Word;
P: PChar;
begin
L := length(s);
P := GetDosEnvironment;
while P^ <> #0 do begin
if (StrLIComp(P, PChar(@s[1]), L) = 0) and (P[L] = '=') then begin
GetEnvVar := StrPas(P + L + 1);
EXIT;
end;
Inc(P, StrLen(P) + 1);
end;
GetEnvVar := '';
end;
(*@\\\*)
(*@/// function day_in_month(month,year,weekday: word; count: integer):TDateTime; *)
function day_in_month(month,year,weekday: word; count: integer):TDateTime;
var
h: integer;
begin
if count>0 then begin
h:=dayofweek(encodedate(year,month,1));
h:=((weekday-h+7) mod 7) +1 + (count-1)*7;
result:=encodedate(year,month,h);
end
else begin
h:=dayofweek(encodedate(year,month,1));
h:=((weekday-h+7) mod 7) +1 + 6*7;
while count<0 do begin
h:=h-7;
try
result:=encodedate(year,month,h);
inc(count);
if count=0 then EXIT;
except
end;
end;
end;
end;
(*@\\\*)
(*@/// function DayLight_Start:TDateTime; // american way ! *)
function DayLight_Start:TDateTime;
var
y,m,d: word;
begin
DecodeDate(now,y,m,d);
result:=day_in_month(4,y,1,1);
(* for european one: day_in_month(3,y,1,-1) *)
end;
(*@\\\*)
(*@/// function DayLight_End:TDateTime; // american way ! *)
function DayLight_End:TDateTime;
var
y,m,d: word;
begin
DecodeDate(now,y,m,d);
result:=day_in_month(10,y,1,-1);
end;
(*@\\\*)
type (* stolen from windows.pas *)
(*@/// TSystemTime = record ... end; *)
PSystemTime = ^TSystemTime;
TSystemTime = record
wYear: Word;
wMonth: Word;
wDayOfWeek: Word;
wDay: Word;
wHour: Word;
wMinute: Word;
wSecond: Word;
wMilliseconds: Word;
end;
(*@\\\*)
(*@/// TTimeZoneInformation = record ... end; *)
TTimeZoneInformation = record
Bias: Longint;
StandardName: array[0..31] of word; (* wchar *)
StandardDate: TSystemTime;
StandardBias: Longint;
DaylightName: array[0..31] of word; (* wchar *)
DaylightDate: TSystemTime;
DaylightBias: Longint;
end;
(*@\\\*)
var
tz_info: TTimeZoneInformation;
LL32:function (LibFileName: PChar; handle: longint; special: longint):Longint;
FL32:function (hDll: Longint):boolean;
GA32:function (hDll: Longint; functionname: PChar):longint;
CP32:function (buffer:TTimeZoneInformation; prochandle,adressconvert,dwParams:Longint):longint;
hdll32,dummy,farproc: longint;
hdll:THandle;
sign: integer;
s: string;
begin
hDll:=GetModuleHandle('kernel'); { get the 16bit handle of kernel }
@LL32:=GetProcAddress(hdll,'LoadLibraryEx32W'); { get the thunking layer functions }
@FL32:=GetProcAddress(hdll,'FreeLibrary32W');
@GA32:=GetProcAddress(hdll,'GetProcAddress32W');
@CP32:=GetProcAddress(hdll,'CallProc32W');
(*@/// if possible then call GetTimeZoneInformation via Thunking *)
if (@LL32<>NIL) and
(@FL32<>NIL) and
(@GA32<>NIL) and
(@CP32<>NIL) then begin
hDll32:=LL32('kernel32.dll',dummy,1); { get the 32bit handle of kernel32 }
farproc:=GA32(hDll32,'GetTimeZoneInformation'); { get the 32bit adress of the function }
case CP32(tz_info,farproc,1,1) of { and call it }
1: result:=tz_info.StandardBias+tz_info.Bias;
2: result:=tz_info.DaylightBias+tz_info.Bias;
else result:=0;
end;
FL32(hDll32); { and free the 32bit dll }
end
(*@\\\*)
(*@/// else calculate the bias out of the TZ environment variable *)
else begin
s:=GetEnvVar('TZ');
while (length(s)>0) and (not(s[1] in ['+','-','0'..'9'])) do
s:=copy(s,2,length(s));
case s[1] of
(*@/// '+': *)
'+': begin
sign:=1;
s:=copy(s,2,length(s));
end;
(*@\\\*)
(*@/// '-': *)
'-': begin
sign:=-1;
s:=copy(s,2,length(s));
end;
(*@\\\*)
else sign:=1;
end;
try
result:=strtoint(copy(s,1,2))*60;
s:=copy(s,3,length(s));
except
try
result:=strtoint(s[1])*60;
s:=copy(s,2,length(s));
except
result:=0;
end;
end;
(*@/// if s[1]=':' then minutes offset *)
if s[1]=':' then begin
try
result:=result+strtoint(copy(s,2,2));
s:=copy(s,4,length(s));
except
try
result:=result+strtoint(s[2]);
s:=copy(s,3,length(s));
except
end;
end;
end;
(*@\\\*)
(*@/// if s[1]=':' then seconds offset - ignored *)
if s[1]=':' then begin
try
strtoint(copy(s,2,2));
s:=copy(s,4,length(s));
except
try
strtoint(s[2]);
s:=copy(s,3,length(s));
except
end;
end;
end;
(*@\\\*)
result:=result*sign;
(*@/// if length(s)>0 then daylight saving activated, calculate it *)
if length(s)>0 then begin
(* forget about the few hours on the start/end day *)
if (now>daylight_start) and (now<DayLight_End+1) then
result:=result-60;
end;
(*@\\\*)
end;
(*@\\\*)
end;
(*@\\\0000001C01*)
(*@/// 32 bit way: API call GetTimeZoneInformation *)
(*$else *)
var
tz_info: TTimeZoneInformation;
begin
case GetTimeZoneInformation(tz_info) of
1: result:=tz_info.StandardBias+tz_info.Bias;
2: result:=tz_info.DaylightBias+tz_info.Bias;
else result:=0;
end;
end;
(*$endif *)
(*@\\\*)
(*@\\\0000000301*)
(*@/// function text2html(const s:string):string; *)
function text2html(const s:string):string;
var
i: integer;
t: string;
begin
result:='';
for i:=1 to length(s) do begin
case s[i] of
(*@/// iso latin 1 *)
(*$ifdef iso_latin1 *)
'&' : t:='&';
'<' : t:='<';
'>' : t:='>';
#160: t:=' ';
'í' : t:='¡';
'ó' : t:='¢';
'ú' : t:='£';
'ñ' : t:='¤'; (* € ??? *)
'Ñ' : t:='¥';
'ª' : t:='¦';
'º' : t:='§';
'¿' : t:='¨';
'⌐' : t:='©';
'¬' : t:='ª';
'½' : t:='«';
'¼' : t:='¬';
'¡' : t:='';
'«' : t:='®';
'»' : t:='¯';
'░' : t:='°';
'▒' : t:='±';
'▓' : t:='²';
'│' : t:='³';
'┤' : t:='´';
'╡' : t:='µ';
'╢' : t:='¶';
'╖' : t:='·';
'╕' : t:='¸le;';
'╣' : t:='¹';
'║' : t:='º';
'╗' : t:='»';
'╝' : t:='¼';
'╜' : t:='½';
'╛' : t:='¾';
'┐' : t:='¿';
'└' : t:='À';
'┴' : t:='Á';
'┬' : t:='Â';
'├' : t:='Ã';
'─' : t:='Ä';
'┼' : t:='Å';
'╞' : t:='Æ';
'╟' : t:='Ç';
'╚' : t:='È';
'╔' : t:='É';
'╩' : t:='Ê';
'╦' : t:='Ë';
'╠' : t:='Ì';
'═' : t:='Í';
'╬' : t:='Î';
'╧' : t:='Ï';
'╨' : t:='Ð';
'╤' : t:='Ñ';
'╥' : t:='Ò';
'╙' : t:='Ó';
'╘' : t:='Ô';
'╒' : t:='Õ';
'╓' : t:='Ö';
'╫' : t:='×';
'╪' : t:='Ø';
'┘' : t:='Ù';
'┌' : t:='Ú';
'█' : t:='Û';
'▄' : t:='Ü';
'▌' : t:='Ý';
'▐' : t:='Þ';
'▀' : t:='ß';
'α' : t:='à';
'ß' : t:='á';
'Γ' : t:='â';
'π' : t:='ã';
'Σ' : t:='ä';
'σ' : t:='å';
'µ' : t:='æ';
'τ' : t:='ç';
'Φ' : t:='è';
'Θ' : t:='é';
'Ω' : t:='ê';
'δ' : t:='ë';
'∞' : t:='ì';
'φ' : t:='í';
'ε' : t:='î';
'∩' : t:='ï';
'≡' : t:='ð';
'±' : t:='ñ';
'≥' : t:='ò';
'≤' : t:='ó';
'⌠' : t:='ô';
'⌡' : t:='õ';
'÷' : t:='ö';
'≈' : t:='÷';
'°' : t:='ø';
'∙' : t:='ù';
'·' : t:='ú';
'√' : t:='û';
'ⁿ' : t:='ü';
'²' : t:='ý';
'■' : t:='þ';
#255: t:='ÿ';
(*$endif *)
(*@\\\000000650C*)
else t:=s[i];
end;
result:=result+t;
end;
end;
(*@\\\*)
(*@/// To have OnShowHint/OnIdle lists instead of single methods *)
{ These are just a few help tools for the Application.OnShowHint and }
{ Application.OnIdle methods - Borland didn't thought of the need to }
{ put more than one method in these places, so I had to do it myself. }
{ At least there's a way to avoid this stuff with Delphi 2/3 with }
{ the cm_hintshow message which is sent just before the OnSHowHint event, }
{ but as this stuff should work with any version of Delphi I stay with }
{ the event list... }
{ Some nice internals how to work with method pointer are presented here. }
(*@/// TObjectList = class(TList) // A list which frees it's objects *)
type
TObjectList = class(TList)
public
destructor Destroy; override;
{ Why hasn't Borland made the delete method virtual??? Now I must create }
{ a new virtual slot with all the problems this may cause just because }
{ of a missing word... - first cause is the remove method which is absolutely }
{ the same as in TList, but as Delete isn't virtual I need it here again. }
{ I you want to use this component anywhere else be VERY careful, any call }
{ as a TList may cause problems }
procedure Delete(Index:Integer); virtual;
function Remove(Item:Pointer):Integer; virtual;
end;
{ TObjectList }
(*@/// destructor TObjectList.Destroy; *)
destructor TObjectList.Destroy;
var
i: integer;
begin
for i:=count-1 downto 0 do
TObject(items[i]).Free;
inherited destroy;
Clear;
end;
(*@\\\*)
(*@/// procedure TObjectList.Delete(Index:Integer); *)
procedure TObjectList.Delete(Index:Integer);
begin
TObject(items[index]).Free;
inherited delete(index);
end;
(*@\\\*)
(*@/// function TObjectList.Remove(Item:Pointer):Integer; *)
function TObjectList.Remove(Item:Pointer):Integer;
begin
Result := IndexOf(Item);
if Result <> -1 then Delete(Result);
end;
(*@\\\*)
(*@\\\*)
type
TMethodPointer = procedure of object;
(*@/// TMethod = class(TObject) // Object with just one methodpointer *)
TMethod = class(TObject)
public
methodpointer: TMethodPointer;
end;
(*@\\\*)
const
(*$ifndef delphi_ge_3 *)
ShowHintProcs: TObjectList =NIL;
(*$endif *)
IdleProcs: TObjectList =NIL;
(*@/// TDummyObject = class(TObject) // A dummy object for the Application events *)
{ TDummyObject }
{ A little dummy object which provides the methods to be put in the }
{ application's method pointers; if you use this you shouldn't access }
{ Application.OnIdle and Application.OnShowHint directly but always use }
{ the Add/RemoveXXXProc routines }
{ You can add any other Application.OnXXX method here if you need it }
type
TDummyObject=class(TObject)
(*$ifndef delphi_ge_3 *)
(*$ifdef shortstring *)
procedure ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo);
(*$else *)
procedure ShowHint(var HintStr: ansistring; var CanShow: Boolean; var HintInfo: THintInfo);
(*$endif *)
(*$endif *)
procedure DoIdle(sender: TObject; var done:Boolean);
end;
(*$ifndef delphi_ge_3 *)
(*@/// procedure TDummyObject.ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo); *)
(*$ifdef shortstring *)
procedure TDummyObject.ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo);
(*$else *)
procedure TDummyObject.ShowHint(var HintStr: ansistring; var CanShow: Boolean; var HintInfo: THintInfo);
(*$endif *)
var
i:integer;
begin
for i:=ShowHintProcs.Count-1 downto 0 do
if ShowHintProcs.Items[i]<>NIL then begin
TShowHintEvent(TMethod(ShowHintProcs.Items[i]).methodpointer)(HintStr,CanShow,HintInfo);
end;
end;
(*@\\\*)
(*$endif *)
(*@/// procedure TDummyObject.DoIdle(sender: TObject; var done:Boolean); *)
procedure TDummyObject.DoIdle(sender: TObject; var done:Boolean);
var
i:integer;
temp_done: boolean;
begin
done:=false;
for i:=IdleProcs.Count-1 downto 0 do
if IdleProcs.Items[i]<>NIL then begin
TIdleEvent(TMethod(IdleProcs.Items[i]).methodpointer)(sender, temp_done);
done:=done and temp_done; (* done when all idle procs say done *)
end;
end;
(*@\\\*)
(*@\\\0000000301*)
const
Dummy: TDummyObject =NIL;
(*@/// Compare two method pointers *)
function compare_method(proc1,proc2:TMethodpointer):boolean;
{ A method pointer is just a record of two pointers, one the procedure }
{ pointer itself, then the self pointer which is pushed as the first }
{ parameter of the procedure }
type
(*@/// T_Method=packed record *)
T_Method=packed record
proc: Pointer;
self: TObject;
end;
(*@\\\*)
begin
result:=(T_Method(proc1).proc=T_Method(proc2).proc) and
(T_Method(proc1).self=T_Method(proc2).self);
end;
(*@\\\*)
(*@/// Include and remove the Methodpointer from the according lists *)
(*$ifndef delphi_ge_3 *)
(*@/// procedure AddShowHintProc(proc:TShowHintEvent); *)
procedure AddShowHintProc(proc:TShowHintEvent);
var
method: TMethod;
begin
if (dummy=NIL) or (showhintprocs=NIL) then exit;
method:=TMethod.Create;
method.methodpointer:=TMethodPointer(proc);
showhintprocs.add(method);
Application.OnShowHint:=dummy.ShowHint;
end;
(*@\\\0000000501*)
(*@/// procedure RemoveShowHintProc(proc:TShowHintEvent); *)
procedure RemoveShowHintProc(proc:TShowHintEvent);
var
i: integer;
begin
if (dummy=NIL) or (showhintprocs=NIL) then exit;
for i:=showhintprocs.count-1 downto 0 do
if (showhintprocs.items[i]<>NIL) and
compare_method(TMethod(showhintprocs.items[i]).methodpointer,
TMethodpointer(proc)) then
showhintprocs.delete(i);
end;
(*@\\\*)
(*$endif *)
(*@/// procedure AddIdleProc(proc:TIdleEvent); *)
procedure AddIdleProc(proc:TIdleEvent);
var
method: TMethod;
begin
if (dummy=NIL) or (idleprocs=NIL) then exit;
method:=TMethod.Create;
method.methodpointer:=TMethodPointer(proc);
idleprocs.add(method);
Application.OnIdle:=dummy.DoIdle;
end;
(*@\\\*)
(*@/// procedure RemoveIdleProc(proc:TIdleEvent); *)
procedure RemoveIdleProc(proc:TIdleEvent);
var
i: integer;
begin
if (dummy=NIL) or (idleprocs=NIL) then exit;
for i:=idleprocs.count-1 downto 0 do
if (idleprocs.items[i]<>NIL) and
compare_method(TMethod(idleprocs.items[i]).methodpointer,
TMethodpointer(proc)) then
idleprocs.delete(i);
end;
(*@\\\*)
(*@\\\000000062B*)
(*@\\\*)
(*@/// Generating HWnd's without the routines in forms *)
{ Creating a new HWnd with a WndProc for an arbitrary class. Just the same }
{ as the routines in forms, but without the assembler stuff and using simple }
{ TList's for the storage - maybe not as fast the original routines, but }
{ much easier to understand and to use. This is only for fun here as the }
{ routines in forms do absolutely the same, but this stuff may be used to }
{ create an console application without using forms but receiving Windows }
{ messages. }
const
(*@/// UtilWindowClass: TWndClass = (...); *)
UtilWindowClass: TWndClass = (
style: 0;
lpfnWndProc: @DefWindowProc;
cbClsExtra: 0;
cbWndExtra: 0;
hInstance: 0;
hIcon: 0;
hCursor: 0;
hbrBackground: 0;
lpszMenuName: nil;
lpszClassName: 'TAHUtilWindow');
(*@\\\*)
WndProcs: TObjectList =NIL;
WndWnds: TList =NIL;
{ Converts a Windows WndProc (HWnd as parameter) to a Delphi method with }
{ self as implicit first parameter by looking up the HWnd in the List }
(*@/// function AH_StdWndProc(Window: HWND; Message,WParam,LParam: Word/Longint); *)
(*$ifdef delphi_1 *)
function AH_StdWndProc(Window: HWND; Message: Longint; WParam: Word;
LParam: Longint): Longint; export;
(*$else *)
function AH_StdWndProc(Window: HWND; Message: Word; WParam: Longint;
LParam: Longint): Longint; stdcall;
(*$endif *)
var
p: integer;
m: TMessage;
begin
m.msg:=message;
m.wparam:=wparam;
m.lparam:=lparam;
m.result:=0;
p:=wndwnds.indexof(pointer(window));
if p>=0 then
TWndProc(TMethod(wndprocs.Items[p]).methodpointer)(m);
result:=m.result;
end;
(*@\\\0000000112*)
{ Creates a new HWnd and link it with the given Method }
(*@/// function AH_AllocateHWnd(Method: TWndProc): HWND; *)
function AH_AllocateHWnd(Method: TWndProc): HWND;
var
tempmethod: TMethod;
TempClass: TWndClass;
begin
result:=0;
if (wndprocs=NIL) then exit;
UtilWindowClass.hInstance := HInstance;
if not GetClassInfo(HInstance, UtilWindowClass.lpszClassName, TempClass) then
(*$ifdef delphi_1 *)
WinProcs.RegisterClass(UtilWindowClass);
(*$else *)
Windows.RegisterClass(UtilWindowClass);
(*$endif *)
Result := CreateWindow(UtilWindowClass.lpszClassName, '', 0,
0, 0, 0, 0, 0, 0, HInstance, nil);
tempmethod:=TMethod.Create;
tempmethod.methodpointer:=TMethodPointer(method);
{ These two lists must be absolutely parallel, otherwise the messages may }
{ go to the wrong object }
wndprocs.add(tempmethod);
wndwnds.add(pointer(result));
SetWindowLong(Result, GWL_WNDPROC, Longint(@AH_StdWndProc));
end;
(*@\\\0000000B12*)
{ Removes the HWnd both in Windows an in the internal lists }
(*@/// procedure AH_DeallocateHWnd(Wnd: HWND); *)
procedure AH_DeallocateHWnd(Wnd: HWND);
var
p: integer;
begin
DestroyWindow(Wnd);
p:=wndwnds.remove(pointer(Wnd));
if p>=0 then
wndprocs.delete(p);
end;
(*@\\\*)
(*@\\\0000001401*)
(*@/// Make Stream and Clipboard work together *)
(*@/// function GetPointer(index: integer; memblock: THandle):pointer; *)
function GetPointer(index: integer; memblock: THandle):pointer;
(*$ifdef delphi_1 *)
var
selector, offset: word;
P: pointer;
begin
selector:=(index div 65536) * selectorinc + memblock;
offset:=(index mod 65536);
p:=GlobalLock(Selector);
result:=Ptr(selector,offset);
end;
(*$else *)
begin
result:=pointer(longint(GlobalLock(memblock))+index);
end;
(*$endif *)
(*@\\\0000000212*)
(*@/// procedure Stream2Clipboard(stream:TStream; format:integer); *)
procedure Stream2Clipboard(stream:TStream; format:integer);
const
max_write = $8000; (* must obey ($10000 mod max_write = 0) for Delphi 1 *)
var
size: longint;
s: word;
curpos: longint;
Memblock: THandle;
FClipboardWindow: THandle;
begin
FClipboardWindow := Application.Handle;
if FClipboardWindow = 0 then
FClipboardWindow := AllocateHWnd(NIL);
OpenClipboard(FClipboardWindow);
stream.seek(0,0);
size:=stream.size;
stream.seek(0,0);
MemBlock:=GlobalAlloc(gmem_moveable or gmem_zeroinit,size+1);
curpos:=0;
while curpos+1<size do begin
s:=stream.read(getPointer(curpos,MemBlock)^,min(max_write,size-curpos));
inc(curpos,s);
GlobalUnLock(MemBlock);
if s=0 then BREAK;
end;
char(getPointer(curpos,memblock)^):=#0;
GlobalUnLock(MemBlock);
EmptyClipBoard;
SetClipBoardData(format,memblock);
CloseClipboard;
if FClipboardWindow<>Application.Handle then
DeallocateHWnd(FClipboardWindow);
end;
(*@\\\0000001601*)
(*@/// procedure Clipboard2Stream(stream:TStream; format:integer); *)
procedure Clipboard2Stream(stream:TStream; format:integer);
const
max_read = $8000; (* must obey ($10000 mod max_read = 0) for Delphi 1 *)
var
size: longint;
curpos: longint;
Memblock: THandle;
FClipboardWindow: THandle;
begin
FClipboardWindow := Application.Handle;
if FClipboardWindow = 0 then
FClipboardWindow := AllocateHWnd(NIL);
OpenClipboard(FClipboardWindow);
stream.seek(0,0);
MemBlock:=GetClipboardData(format);
size:=GlobalSize(Memblock);
curpos:=0;
while curpos+1<size do begin
stream.write(getPointer(curpos,MemBlock)^,min(max_read,size-curpos-1));
inc(curpos,min(max_read,size-curpos-1));
GlobalUnLock(MemBlock);
end;
CloseClipboard;
if FClipboardWindow<>Application.Handle then
DeallocateHWnd(FClipboardWindow);
end;
(*@\\\0000000C01*)
(*@\\\0000000301*)
(*@/// Windows Resources and Languages *)
(*$ifdef delphi_gt_1 *)
(*@/// function makelangid(language,sublanguage: word):longint; *)
function makelangid(language,sublanguage: word):longint;
begin
result:=((language and $3FF) or ((sublanguage and $3F) shl 10)) and $FFFF;
end;
(*@\\\*)
(*@/// function primarylangid(language:word):word; *)
function primarylangid(language:word):word;
begin
result:=language and $3FF;
end;
(*@\\\*)
(*@/// function sublangid(language:word):word; *)
function sublangid(language:word):word;
begin
result:=(language shr 10) and $3F;
end;
(*@\\\*)
(*@/// function langidfromlcid(lcid:longint):word; *)
function langidfromlcid(lcid:longint):word;
begin
result:=lcid and $FFFF;
end;
(*@\\\*)
(*@/// function MyLoadStringInternal(Instance: THandle; Id: word; languageid: word):string; *)
function MyLoadStringInternal(Instance: THandle; Id: word; languageid: word):string;
var
h,h1: THandle;
p: ^word;
_length: word;
i: integer;
begin
h:=FindResourceEx(Instance,rt_string,MakeIntResource((id div 16)+1),languageid);
if h<>0 then begin
h1:=Loadresource(Instance,h);
p:=LockResource(h1);
i:=id mod 16;
while i>0 do begin
_length:=p^;
inc(p,_length+1);
dec(i);
end;
_length:=p^;
inc(p);
setlength(result,WideCharToMultiByte(cp_acp,0,PWideChar(p),_length,NIL,0,NIL,NIL));
WideCharToMultiByte(cp_acp,0,PWideChar(p),_length,@result[1],length(result),NIL,NIL);
FreeResource(h1);
end
else
result:='';
end;
(*@\\\*)
(*@/// function MyLoadString(Instance: THandle; Id: word; languageid: word):string; *)
function MyLoadString(Instance: THandle; Id: word; languageid: word):string;
begin
result:=MyLoadStringInternal(Instance,id,languageid);
if result='' then
result:=MyLoadStringInternal(Instance,id,makelangid(primarylangid(languageid),sublang_default));
if result='' then
result:=MyLoadStringInternal(Instance,id,makelangid(primarylangid(languageid),sublang_neutral));
if result='' then
result:=MyLoadStringInternal(Instance,id,makelangid(lang_neutral,sublang_neutral));
end;
(*@\\\*)
(*@/// function LoadStrEx(id:word; languageid: word):string; *)
function LoadStrEx(id:word; languageid: word):string;
begin
result:=MyLoadString(HInstance,id,languageid);
end;
(*@\\\*)
(*$endif *)
(*@/// function LoadStr(id:word):string; *)
function LoadStr(id:word):string;
begin
(*$ifdef delphi_gt_1 *)
result:=MyLoadString(HInstance,id,GetUserDefaultLangId);
(*$else *)
result:=sysutils.loadstr(id);
(*$endif *)
end;
(*@\\\003C00050100060100070100080100070B*)
(*@\\\*)
(*@/// function ScrollBarVisible(control: TWinControl; vertical: boolean):boolean; *)
function ScrollBarVisible(control: TWinControl; vertical: boolean):boolean;
(*$ifdef delphi_1 *)
var
code: integer;
min,max: integer;
begin
if vertical then
code:=sb_vert
else
code:=sb_horz;
GetScrollRange(control.handle,code,min,max);
result:=(min<>max);
end;
(*$else *)
var
code: integer;
ScrollInfo: TScrollInfo;
begin
if vertical then
code:=sb_vert
else
code:=sb_horz;
scrollinfo.cbsize:=sizeof(scrollinfo);
scrollinfo.fmask:=sif_all;
if GetScrollInfo(control.handle,code,scrollinfo) then
result:=(scrollinfo.nmax<>scrollinfo.nmin)
else
result:=false;
end;
(*$endif *)
(*@\\\*)
(*@/// procedure DoneUnit; // The cleanup of the unit, called in finalization *)
procedure DoneUnit; far;
begin
(*$ifndef delphi_ge_3 *)
{ For design mode: relink the OnShowHint back to it's default value; }
{ only needed since with Delphi 3 packages the finalization may be }
{ called without Delphi itself is closed }
if (ShowHintProcs<>NIL) and
(ShowHintProcs.Count>0) then
Application.OnShowHint:=TShowHintEvent(TMethod(ShowHintProcs.Items[0]).methodpointer);
{ The explicit removing of the list entries is needed since the delete method }
{ of the TLIst isn't virtual an therefore not called by the Free }
if ShowHintProcs<>NIL then
while ShowHintProcs.Count>0 do
ShowHintProcs.delete(0);
ShowHintProcs.Free;
ShowHintProcs:=NIL;
(*$endif *)
if IdleProcs<>NIL then
while IdleProcs.Count>0 do
IdleProcs.delete(0);
IdleProcs.Free;
IdleProcs:=NIL;
Dummy.Free;
Dummy:=NIL;
{ The explicit removing of the list entries is needed since the delete method }
{ of the TLIst isn't virtual an therefore not called by the Free }
if WndProcs<>NIL then
while WndProcs.Count>0 do
WndProcs.delete(0);
WndProcs.Free;
WndProcs:=NIL;
WndWnds.Free;
WndWnds:=NIL;
end;
(*@\\\*)
(*@\\\0000001101*)
(*@/// initialization *)
(*$ifndef delphi_ge_3 *)
var
t:TShowHintEvent;
(*$endif *)
(*$ifdef delphi_1 *)
begin
(*$else *)
initialization
begin
(*$endif *)
Dummy:=TDummyObject.Create;
IdleProcs:=TObjectList.Create;
(* Since Delphi 3 there is the CM_HINTSHOW instead,
so this isn't needed anymore *)
(*$ifndef delphi_ge_3 *)
ShowHintProcs:=TObjectList.Create;
t:=application.OnShowHint;
if assigned(t) then { D1 can't do a assigned of a property }
AddShowHintProc(t); { In design mode the OnShowHint is responsible }
{ for the hints of the component palette so I }
{ need to remember this }
(*$endif *)
WndProcs:=TObjectList.Create;
WndWnds:=TList.Create;
(*@\\\000000040C*)
(*@/// finalization *)
(*$ifdef delphi_1 *)
AddExitProc(DoneUnit);
(*$else *)
end;
finalization
DoneUnit;
(*$endif *)
(*@\\\0000000201*)
end.
(*@\\\0003000701000011000701*)