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 >
Pascal/Delphi Source File  |  2001-06-04  |  34KB  |  1,157 lines

  1. unit ah_tool;
  2. { Copyright 1995-200 Andreas H÷rstemeier            Version 1.1 2001-06-04   }
  3. { this utility functions are public domain. They are used by several of my   }
  4. { components. In case you have several version of this file always use the   }
  5. { latest one. Please check the file readme.txt of the component you found    }
  6. { this file at for more detailed info on usage and distributing.             }
  7. (*@/// interface *)
  8. interface
  9.  
  10. (*$b- *)
  11.   (*$i ah_def.inc *)
  12.  
  13. uses
  14. (*$ifdef delphi_1 *)
  15.   winprocs,
  16.   wintypes,
  17. (*$else *)
  18.   windows,
  19. (*$endif *)
  20.   messages,
  21.   sysutils,
  22.   classes,
  23.   controls,
  24.   forms;
  25.  
  26. (*@/// String utility functions *)
  27. { Find n'th occurence of a substring, from left or from right }
  28. function posn(const s,t:string; count:integer):integer;
  29.  
  30. { Find the n'th char unequal from left or from right }
  31. function poscn(c:char; const s:string; n: integer):integer;
  32.  
  33. { Exchange all occurances of a string by another (e.g. ,->.) }
  34. function exchange_s(const prior,after: string; const s:string):string;
  35.  
  36. { Delphi 1 didn't know these, but they are useful/necessary for D2/D3 }
  37. (*$ifdef delphi_1 *)
  38. function trim(const s:string):string;
  39. procedure setlength(var s:string; l: byte);
  40. (*$endif *)
  41.  
  42. { Write a string into a stream }
  43. procedure String2Stream(stream:TMemorystream; const s:string);
  44. (*@\\\0000001101*)
  45.  
  46. { The offset to UTC/GMT in minutes of the local time zone }
  47. function TimeZoneBias:longint;
  48.  
  49. { Convert a string to HTML - currently only for latin 1 }
  50. function text2html(const s:string):string;
  51.  
  52. { Why are these not in the language itself? }
  53. function min(x,y: longint):longint;
  54. function max(x,y: longint):longint;
  55.  
  56. (*@/// Create a windows HWnd avoiding the stuff from forms *)
  57. type
  58.   TWndProc = procedure (var Message: TMessage) of object;
  59.  
  60. function AH_AllocateHWnd(Method: TWndProc): HWND;
  61. procedure AH_DeallocateHWnd(Wnd: HWND);
  62. (*@\\\*)
  63.  
  64. (*@/// The routines to make the applications events use a list of methods *)
  65. (*$ifndef delphi_ge_3 *)
  66. procedure AddShowHintProc(proc:TShowHintEvent);
  67. procedure RemoveShowHintProc(proc:TShowHintEvent);
  68. (*$endif *)
  69. procedure AddIdleProc(proc:TIdleEvent);
  70. procedure RemoveIdleProc(proc:TIdleEvent);
  71. (*@\\\*)
  72.  
  73. (*@/// Make Stream and Clipboard work together *)
  74. procedure Stream2Clipboard(stream:TStream; format:integer);
  75. procedure Clipboard2Stream(stream:TStream; format:integer);
  76. (*@\\\*)
  77.  
  78. (*@/// Windows Resources and Languages *)
  79. (*$ifdef delphi_gt_1 *)
  80. function LoadStrEx(id:word; languageid: word):string;
  81. (*$endif *)
  82. function LoadStr(id:word):string;
  83. (*@\\\*)
  84.  
  85. function ScrollBarVisible(control: TWinControl; vertical: boolean):boolean;
  86. (*@\\\0000002501*)
  87. (*@/// implementation *)
  88. implementation
  89.  
  90. (*@/// Some string utility functions *)
  91. (*@/// function posn(const s,t:string; count:integer):integer; *)
  92. function posn(const s,t:string; count:integer):integer;
  93.  
  94. { find the count'th occurence of the substring,
  95.   if count<0 then look from the back }
  96.  
  97. var
  98.   i,h,last: integer;
  99.   u: string;
  100. begin
  101.   u:=t;
  102.   if count>0 then begin
  103.     result:=length(t);
  104.     for i:=1 to count do begin
  105.       h:=pos(s,u);
  106.       if h>0 then
  107.         u:=copy(u,pos(s,u)+1,length(u))
  108.       else begin
  109.         u:='';
  110.         inc(result);
  111.         end;
  112.       end;
  113.     result:=result-length(u);
  114.     end
  115.   else if count<0 then begin
  116.     last:=0;
  117.     for i:=length(t) downto 1 do begin
  118.       u:=copy(t,i,length(t));
  119.       h:=pos(s,u);
  120.       if (h<>0) and (h+i<>last) then begin
  121.         last:=h+i-1;
  122.         inc(count);
  123.         if count=0 then BREAK;
  124.         end;
  125.       end;
  126.     if count=0 then result:=last
  127.                else result:=0;
  128.     end
  129.   else
  130.     result:=0;
  131.   end;
  132. (*@\\\*)
  133. (*@/// function exchange_s(const prior,after: string; const s:string):string; *)
  134. function exchange_s(const prior,after: string; const s:string):string;
  135. var
  136.   h,p: integer;
  137. begin
  138.   result:=s;
  139.   p:=length(prior);
  140.   while true do begin
  141.     h:=pos(prior,result);
  142.     if h=0 then BREAK;
  143.     result:=copy(result,1,h-1)+after+copy(result,h+p,length(result));
  144.     end;
  145.   end;
  146. (*@\\\*)
  147. (*@/// function poscn(c:char; const s:string; n: integer):integer; *)
  148. function poscn(c:char; const s:string; n: integer):integer;
  149.  
  150. { Find the n'th occurence of a character different to c,
  151.   if n<0 look from the back }
  152.  
  153. var
  154.   i: integer;
  155. begin
  156.   if n=0 then  n:=1;
  157.   if n>0 then begin
  158.     for i:=1 to length(s) do begin
  159.       if s[i]<>c then begin
  160.         dec(n);
  161.         result:=i;
  162.         if n=0 then begin
  163.           EXIT;
  164.           end;
  165.         end;
  166.       end;
  167.     end
  168.   else begin
  169.     for i:=length(s) downto 1 do begin
  170.       if s[i]<>c then begin
  171.         inc(n);
  172.         result:=i;
  173.         if n=0 then begin
  174.           EXIT;
  175.           end;
  176.         end;
  177.       end;
  178.     end;
  179.   poscn:=0;
  180.   end;
  181. (*@\\\*)
  182. (*@/// function filename_of(const s:string):string; *)
  183. function filename_of(const s:string):string;
  184. var
  185.   t:integer;
  186. begin
  187.   t:=posn('\',s,-1);
  188.   if t>0 then
  189.     result:=copy(s,t+1,length(s))
  190.   else begin
  191.     t:=posn(':',s,-1);
  192.     if t>0 then
  193.       result:=copy(s,t+1,length(s))
  194.     else
  195.       result:=s;
  196.     end;
  197.   end;
  198. (*@\\\*)
  199. (*$ifdef delphi_1 *)
  200. (*@/// function trim(const s:string):string; *)
  201. function trim(const s:string):string;
  202. var
  203.   h: integer;
  204. begin
  205.   (* trim from left *)
  206.   h:=poscn(' ',s,1);
  207.   if h>0 then
  208.     result:=copy(s,h,length(s))
  209.   else
  210.     result:=s;
  211.   (* trim from right *)
  212.   h:=poscn(' ',result,-1);
  213.   if h>0 then
  214.     result:=copy(result,1,h);
  215.   end;
  216. (*@\\\*)
  217. (*@/// procedure setlength(var s:string; l: byte); *)
  218. procedure setlength(var s:string; l: byte);
  219. begin
  220.   s[0]:=char(l);
  221.   end;
  222. (*@\\\*)
  223. (*$endif *)
  224. (*@/// procedure String2Stream(stream:TMemorystream; const s:string); *)
  225. procedure String2Stream(stream:TMemorystream; const s:string);
  226. begin
  227.   stream.write(s[1],length(s));
  228.   end;
  229. (*@\\\*)
  230. (*@\\\*)
  231.  
  232. (*@/// function min(x,y: longint):longint; *)
  233. function min(x,y: longint):longint;
  234. begin
  235.   if x<y then result:=x
  236.          else result:=y;
  237.   end;
  238. (*@\\\*)
  239. (*@/// function max(x,y: longint):longint; *)
  240. function max(x,y: longint):longint;
  241. begin
  242.   if x>y then result:=x
  243.          else result:=y;
  244.   end;
  245. (*@\\\*)
  246.  
  247. (*@/// function TimeZoneBias:longint;          // in minutes ! *)
  248. function TimeZoneBias:longint;
  249. (*@/// 16 bit way: try a 32bit API call via thunking layer, if that fails try the TZ *)
  250. (*$ifdef delphi_1 *)
  251. (*@/// function GetEnvVar(const s:string):string; *)
  252. function GetEnvVar(const s:string):string;
  253. var
  254.   L: Word;
  255.   P: PChar;
  256. begin
  257.   L := length(s);
  258.   P := GetDosEnvironment;
  259.   while P^ <> #0 do begin
  260.     if (StrLIComp(P, PChar(@s[1]), L) = 0) and (P[L] = '=') then begin
  261.       GetEnvVar := StrPas(P + L + 1);
  262.       EXIT;
  263.       end;
  264.     Inc(P, StrLen(P) + 1);
  265.     end;
  266.   GetEnvVar := '';
  267.   end;
  268. (*@\\\*)
  269.  
  270. (*@/// function day_in_month(month,year,weekday: word; count: integer):TDateTime; *)
  271. function day_in_month(month,year,weekday: word; count: integer):TDateTime;
  272. var
  273.   h: integer;
  274. begin
  275.   if count>0 then begin
  276.     h:=dayofweek(encodedate(year,month,1));
  277.     h:=((weekday-h+7) mod 7) +1 + (count-1)*7;
  278.     result:=encodedate(year,month,h);
  279.     end
  280.   else begin
  281.     h:=dayofweek(encodedate(year,month,1));
  282.     h:=((weekday-h+7) mod 7) +1 + 6*7;
  283.     while count<0 do begin
  284.       h:=h-7;
  285.       try
  286.         result:=encodedate(year,month,h);
  287.         inc(count);
  288.         if count=0 then EXIT;
  289.       except
  290.         end;
  291.       end;
  292.     end;
  293.   end;
  294. (*@\\\*)
  295. (*@/// function DayLight_Start:TDateTime;     // american way ! *)
  296. function DayLight_Start:TDateTime;
  297. var
  298.   y,m,d: word;
  299. begin
  300.   DecodeDate(now,y,m,d);
  301.   result:=day_in_month(4,y,1,1);
  302.   (* for european one: day_in_month(3,y,1,-1) *)
  303.   end;
  304. (*@\\\*)
  305. (*@/// function DayLight_End:TDateTime;       // american way ! *)
  306. function DayLight_End:TDateTime;
  307. var
  308.   y,m,d: word;
  309. begin
  310.   DecodeDate(now,y,m,d);
  311.   result:=day_in_month(10,y,1,-1);
  312.   end;
  313. (*@\\\*)
  314. type    (* stolen from windows.pas *)
  315.   (*@/// TSystemTime = record ... end; *)
  316.   PSystemTime = ^TSystemTime;
  317.   TSystemTime = record
  318.     wYear: Word;
  319.     wMonth: Word;
  320.     wDayOfWeek: Word;
  321.     wDay: Word;
  322.     wHour: Word;
  323.     wMinute: Word;
  324.     wSecond: Word;
  325.     wMilliseconds: Word;
  326.   end;
  327.   (*@\\\*)
  328.   (*@/// TTimeZoneInformation = record ... end; *)
  329.   TTimeZoneInformation = record
  330.     Bias: Longint;
  331.     StandardName: array[0..31] of word;  (* wchar *)
  332.     StandardDate: TSystemTime;
  333.     StandardBias: Longint;
  334.     DaylightName: array[0..31] of word;  (* wchar *)
  335.     DaylightDate: TSystemTime;
  336.     DaylightBias: Longint;
  337.     end;
  338.   (*@\\\*)
  339. var
  340.   tz_info: TTimeZoneInformation;
  341.   LL32:function (LibFileName: PChar; handle: longint; special: longint):Longint;
  342.   FL32:function (hDll: Longint):boolean;
  343.   GA32:function (hDll: Longint; functionname: PChar):longint;
  344.   CP32:function (buffer:TTimeZoneInformation; prochandle,adressconvert,dwParams:Longint):longint;
  345.   hdll32,dummy,farproc: longint;
  346.   hdll:THandle;
  347.   sign: integer;
  348.   s: string;
  349. begin
  350.   hDll:=GetModuleHandle('kernel');                  { get the 16bit handle of kernel }
  351.   @LL32:=GetProcAddress(hdll,'LoadLibraryEx32W');   { get the thunking layer functions }
  352.   @FL32:=GetProcAddress(hdll,'FreeLibrary32W');
  353.   @GA32:=GetProcAddress(hdll,'GetProcAddress32W');
  354.   @CP32:=GetProcAddress(hdll,'CallProc32W');
  355.   (*@/// if possible then   call GetTimeZoneInformation via Thunking *)
  356.   if (@LL32<>NIL) and
  357.      (@FL32<>NIL) and
  358.      (@GA32<>NIL) and
  359.      (@CP32<>NIL) then begin
  360.     hDll32:=LL32('kernel32.dll',dummy,1);            { get the 32bit handle of kernel32 }
  361.     farproc:=GA32(hDll32,'GetTimeZoneInformation');  { get the 32bit adress of the function }
  362.     case CP32(tz_info,farproc,1,1) of                { and call it }
  363.       1: result:=tz_info.StandardBias+tz_info.Bias;
  364.       2: result:=tz_info.DaylightBias+tz_info.Bias;
  365.       else result:=0;
  366.       end;
  367.     FL32(hDll32);                                    { and free the 32bit dll }
  368.     end
  369.   (*@\\\*)
  370.   (*@/// else  calculate the bias out of the TZ environment variable *)
  371.   else begin
  372.     s:=GetEnvVar('TZ');
  373.     while (length(s)>0) and (not(s[1] in ['+','-','0'..'9'])) do
  374.       s:=copy(s,2,length(s));
  375.     case s[1] of
  376.       (*@/// '+': *)
  377.       '+': begin
  378.         sign:=1;
  379.         s:=copy(s,2,length(s));
  380.         end;
  381.       (*@\\\*)
  382.       (*@/// '-': *)
  383.       '-': begin
  384.         sign:=-1;
  385.         s:=copy(s,2,length(s));
  386.         end;
  387.       (*@\\\*)
  388.       else sign:=1;
  389.       end;
  390.     try
  391.       result:=strtoint(copy(s,1,2))*60;
  392.       s:=copy(s,3,length(s));
  393.     except
  394.       try
  395.         result:=strtoint(s[1])*60;
  396.         s:=copy(s,2,length(s));
  397.       except
  398.         result:=0;
  399.         end;
  400.       end;
  401.     (*@/// if s[1]=':' then    minutes offset *)
  402.     if s[1]=':' then begin
  403.       try
  404.         result:=result+strtoint(copy(s,2,2));
  405.         s:=copy(s,4,length(s));
  406.       except
  407.         try
  408.           result:=result+strtoint(s[2]);
  409.           s:=copy(s,3,length(s));
  410.         except
  411.           end;
  412.         end;
  413.       end;
  414.     (*@\\\*)
  415.     (*@/// if s[1]=':' then    seconds offset - ignored *)
  416.     if s[1]=':' then begin
  417.       try
  418.         strtoint(copy(s,2,2));
  419.         s:=copy(s,4,length(s));
  420.       except
  421.         try
  422.           strtoint(s[2]);
  423.           s:=copy(s,3,length(s));
  424.         except
  425.           end;
  426.         end;
  427.       end;
  428.     (*@\\\*)
  429.     result:=result*sign;
  430.     (*@/// if length(s)>0 then daylight saving activated, calculate it *)
  431.     if length(s)>0 then begin
  432.       (* forget about the few hours on the start/end day *)
  433.       if (now>daylight_start) and (now<DayLight_End+1) then
  434.         result:=result-60;
  435.       end;
  436.     (*@\\\*)
  437.     end;
  438.   (*@\\\*)
  439.   end;
  440. (*@\\\0000001C01*)
  441. (*@/// 32 bit way: API call GetTimeZoneInformation *)
  442. (*$else *)
  443. var
  444.   tz_info: TTimeZoneInformation;
  445. begin
  446.   case GetTimeZoneInformation(tz_info) of
  447.     1: result:=tz_info.StandardBias+tz_info.Bias;
  448.     2: result:=tz_info.DaylightBias+tz_info.Bias;
  449.     else result:=0;
  450.     end;
  451.   end;
  452. (*$endif *)
  453. (*@\\\*)
  454. (*@\\\0000000301*)
  455.  
  456. (*@/// function text2html(const s:string):string; *)
  457. function text2html(const s:string):string;
  458. var
  459.   i: integer;
  460.   t: string;
  461. begin
  462.   result:='';
  463.   for i:=1 to length(s) do begin
  464.     case s[i] of
  465.       (*@/// iso latin 1 *)
  466.       (*$ifdef iso_latin1 *)
  467.             '&' : t:='&';
  468.             '<' : t:='<';
  469.             '>' : t:='>';
  470.             #160: t:=' ';
  471.             'í' : t:='¡';
  472.             'ó' : t:='¢';
  473.             'ú' : t:='£';
  474.             'ñ' : t:='¤';   (* € ??? *)
  475.             'Ñ' : t:='¥';
  476.             'ª' : t:='¦';
  477.             'º' : t:='§';
  478.             '¿' : t:='¨';
  479.             '⌐' : t:='©';
  480.             '¬' : t:='ª';
  481.             '½' : t:='«';
  482.             '¼' : t:='¬';
  483.             '¡' : t:='­';
  484.             '«' : t:='®';
  485.             '»' : t:='¯';
  486.             '░' : t:='°';
  487.             '▒' : t:='±';
  488.             '▓' : t:='²';
  489.             '│' : t:='³';
  490.             '┤' : t:='´';
  491.             '╡' : t:='µ';
  492.             '╢' : t:='¶';
  493.             '╖' : t:='·';
  494.             '╕' : t:='¸le;';
  495.             '╣' : t:='¹';
  496.             '║' : t:='º';
  497.             '╗' : t:='»';
  498.             '╝' : t:='¼';
  499.             '╜' : t:='½';
  500.             '╛' : t:='¾';
  501.             '┐' : t:='¿';
  502.             '└' : t:='À';
  503.             '┴' : t:='Á';
  504.             '┬' : t:='Â';
  505.             '├' : t:='Ã';
  506.             '─' : t:='Ä';
  507.             '┼' : t:='Å';
  508.             '╞' : t:='Æ';
  509.             '╟' : t:='Ç';
  510.             '╚' : t:='È';
  511.             '╔' : t:='É';
  512.             '╩' : t:='Ê';
  513.             '╦' : t:='Ë';
  514.             '╠' : t:='Ì';
  515.             '═' : t:='Í';
  516.             '╬' : t:='Î';
  517.             '╧' : t:='Ï';
  518.             '╨' : t:='Ð';
  519.             '╤' : t:='Ñ';
  520.             '╥' : t:='Ò';
  521.             '╙' : t:='Ó';
  522.             '╘' : t:='Ô';
  523.             '╒' : t:='Õ';
  524.             '╓' : t:='Ö';
  525.             '╫' : t:='×';
  526.             '╪' : t:='Ø';
  527.             '┘' : t:='Ù';
  528.             '┌' : t:='Ú';
  529.             '█' : t:='Û';
  530.             '▄' : t:='Ü';
  531.             '▌' : t:='Ý';
  532.             '▐' : t:='Þ';
  533.             '▀' : t:='ß';
  534.             'α' : t:='à';
  535.             'ß' : t:='á';
  536.             'Γ' : t:='â';
  537.             'π' : t:='ã';
  538.             'Σ' : t:='ä';
  539.             'σ' : t:='å';
  540.             'µ' : t:='æ';
  541.             'τ' : t:='ç';
  542.             'Φ' : t:='è';
  543.             'Θ' : t:='é';
  544.             'Ω' : t:='ê';
  545.             'δ' : t:='ë';
  546.             '∞' : t:='ì';
  547.             'φ' : t:='í';
  548.             'ε' : t:='î';
  549.             '∩' : t:='ï';
  550.             '≡' : t:='ð';
  551.             '±' : t:='ñ';
  552.             '≥' : t:='ò';
  553.             '≤' : t:='ó';
  554.             '⌠' : t:='ô';
  555.             '⌡' : t:='õ';
  556.             '÷' : t:='ö';
  557.             '≈' : t:='÷';
  558.             '°' : t:='ø';
  559.             '∙' : t:='ù';
  560.             '·' : t:='ú';
  561.             '√' : t:='û';
  562.             'ⁿ' : t:='ü';
  563.             '²' : t:='ý';
  564.             '■' : t:='þ';
  565.             #255: t:='ÿ';
  566.       (*$endif *)
  567.       (*@\\\000000650C*)
  568.       else  t:=s[i];
  569.       end;
  570.     result:=result+t;
  571.     end;
  572.   end;
  573. (*@\\\*)
  574.  
  575. (*@/// To have OnShowHint/OnIdle lists instead of single methods *)
  576. { These are just a few help tools for the Application.OnShowHint and      }
  577. { Application.OnIdle methods - Borland didn't thought of the need to      }
  578. { put more than one method in these places, so I had to do it myself.     }
  579. { At least there's a way to avoid this stuff with Delphi 2/3 with         }
  580. { the cm_hintshow message which is sent just before the OnSHowHint event, }
  581. { but as this stuff should work with any version of Delphi I stay with    }
  582. { the event list...                                                       }
  583. { Some nice internals how to work with method pointer are presented here. }
  584.  
  585. (*@/// TObjectList = class(TList)       // A list which frees it's objects *)
  586. type
  587.   TObjectList = class(TList)
  588.   public
  589.     destructor Destroy; override;
  590.  
  591. { Why hasn't Borland made the delete method virtual??? Now I must create      }
  592. { a new virtual slot with all the problems this may cause just because        }
  593. { of a missing word... - first cause is the remove method which is absolutely }
  594. { the same as in TList, but as Delete isn't virtual I need it here again.     }
  595.  
  596. { I you want to use this component anywhere else be VERY careful, any call    }
  597. { as a TList may cause problems                                               }
  598.  
  599.     procedure Delete(Index:Integer);  virtual;
  600.     function Remove(Item:Pointer):Integer; virtual;
  601.     end;
  602.  
  603. { TObjectList }
  604. (*@/// destructor TObjectList.Destroy; *)
  605. destructor TObjectList.Destroy;
  606. var
  607.   i: integer;
  608. begin
  609.   for i:=count-1 downto 0 do
  610.     TObject(items[i]).Free;
  611.   inherited destroy;
  612.   Clear;
  613. end;
  614. (*@\\\*)
  615. (*@/// procedure TObjectList.Delete(Index:Integer); *)
  616. procedure TObjectList.Delete(Index:Integer);
  617. begin
  618.   TObject(items[index]).Free;
  619.   inherited delete(index);
  620.   end;
  621. (*@\\\*)
  622. (*@/// function TObjectList.Remove(Item:Pointer):Integer; *)
  623. function TObjectList.Remove(Item:Pointer):Integer;
  624. begin
  625.   Result := IndexOf(Item);
  626.   if Result <> -1 then Delete(Result);
  627.   end;
  628. (*@\\\*)
  629. (*@\\\*)
  630.  
  631. type
  632.   TMethodPointer = procedure of object;
  633.   (*@/// TMethod = class(TObject)       // Object with just one methodpointer *)
  634.   TMethod = class(TObject)
  635.   public
  636.     methodpointer: TMethodPointer;
  637.     end;
  638.   (*@\\\*)
  639.  
  640. const
  641. (*$ifndef delphi_ge_3 *)
  642.   ShowHintProcs: TObjectList =NIL;
  643. (*$endif *)
  644.   IdleProcs: TObjectList     =NIL;
  645.  
  646. (*@/// TDummyObject = class(TObject)    // A dummy object for the Application events *)
  647. { TDummyObject }
  648.  
  649. { A little dummy object which provides the methods to be put in the     }
  650. { application's method pointers; if you use this you shouldn't access   }
  651. { Application.OnIdle and Application.OnShowHint directly but always use }
  652. { the Add/RemoveXXXProc routines                                        }
  653. { You can add any other Application.OnXXX method here if you need it    }
  654.  
  655. type
  656.   TDummyObject=class(TObject)
  657. (*$ifndef delphi_ge_3 *)
  658. (*$ifdef shortstring *)
  659.   procedure ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo);
  660. (*$else *)
  661.   procedure ShowHint(var HintStr: ansistring; var CanShow: Boolean; var HintInfo: THintInfo);
  662. (*$endif *)
  663. (*$endif *)
  664.   procedure DoIdle(sender: TObject; var done:Boolean);
  665.   end;
  666. (*$ifndef delphi_ge_3 *)
  667. (*@/// procedure TDummyObject.ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo); *)
  668.  
  669. (*$ifdef shortstring *)
  670. procedure TDummyObject.ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo);
  671. (*$else *)
  672. procedure TDummyObject.ShowHint(var HintStr: ansistring; var CanShow: Boolean; var HintInfo: THintInfo);
  673. (*$endif *)
  674. var
  675.   i:integer;
  676. begin
  677.   for i:=ShowHintProcs.Count-1 downto 0 do
  678.     if ShowHintProcs.Items[i]<>NIL then begin
  679.       TShowHintEvent(TMethod(ShowHintProcs.Items[i]).methodpointer)(HintStr,CanShow,HintInfo);
  680.       end;
  681.   end;
  682. (*@\\\*)
  683. (*$endif *)
  684. (*@/// procedure TDummyObject.DoIdle(sender: TObject; var done:Boolean); *)
  685. procedure TDummyObject.DoIdle(sender: TObject; var done:Boolean);
  686. var
  687.   i:integer;
  688.   temp_done: boolean;
  689. begin
  690.   done:=false;
  691.   for i:=IdleProcs.Count-1 downto 0 do
  692.     if IdleProcs.Items[i]<>NIL then begin
  693.       TIdleEvent(TMethod(IdleProcs.Items[i]).methodpointer)(sender, temp_done);
  694.       done:=done and temp_done;   (* done when all idle procs say done *)
  695.       end;
  696.   end;
  697. (*@\\\*)
  698. (*@\\\0000000301*)
  699.  
  700. const
  701.   Dummy: TDummyObject        =NIL;
  702.  
  703. (*@/// Compare two method pointers *)
  704. function compare_method(proc1,proc2:TMethodpointer):boolean;
  705.  
  706. { A method pointer is just a record of two pointers, one the procedure }
  707. { pointer itself, then the self pointer which is pushed as the first   }
  708. { parameter of the procedure                                           }
  709.  
  710. type
  711.   (*@/// T_Method=packed record *)
  712.   T_Method=packed record
  713.     proc: Pointer;
  714.     self: TObject;
  715.     end;
  716.   (*@\\\*)
  717. begin
  718.   result:=(T_Method(proc1).proc=T_Method(proc2).proc) and
  719.           (T_Method(proc1).self=T_Method(proc2).self);
  720.   end;
  721. (*@\\\*)
  722. (*@/// Include and remove the Methodpointer from the according lists *)
  723. (*$ifndef delphi_ge_3 *)
  724. (*@/// procedure AddShowHintProc(proc:TShowHintEvent); *)
  725. procedure AddShowHintProc(proc:TShowHintEvent);
  726. var
  727.   method: TMethod;
  728. begin
  729.   if (dummy=NIL) or (showhintprocs=NIL) then exit;
  730.   method:=TMethod.Create;
  731.   method.methodpointer:=TMethodPointer(proc);
  732.   showhintprocs.add(method);
  733.   Application.OnShowHint:=dummy.ShowHint;
  734.   end;
  735. (*@\\\0000000501*)
  736. (*@/// procedure RemoveShowHintProc(proc:TShowHintEvent); *)
  737. procedure RemoveShowHintProc(proc:TShowHintEvent);
  738. var
  739.   i: integer;
  740. begin
  741.   if (dummy=NIL) or (showhintprocs=NIL) then exit;
  742.   for i:=showhintprocs.count-1 downto 0 do
  743.     if (showhintprocs.items[i]<>NIL) and
  744.        compare_method(TMethod(showhintprocs.items[i]).methodpointer,
  745.                       TMethodpointer(proc))  then
  746.       showhintprocs.delete(i);
  747.   end;
  748. (*@\\\*)
  749. (*$endif *)
  750. (*@/// procedure AddIdleProc(proc:TIdleEvent); *)
  751. procedure AddIdleProc(proc:TIdleEvent);
  752. var
  753.   method: TMethod;
  754. begin
  755.   if (dummy=NIL) or (idleprocs=NIL) then exit;
  756.   method:=TMethod.Create;
  757.   method.methodpointer:=TMethodPointer(proc);
  758.   idleprocs.add(method);
  759.   Application.OnIdle:=dummy.DoIdle;
  760.   end;
  761. (*@\\\*)
  762. (*@/// procedure RemoveIdleProc(proc:TIdleEvent); *)
  763. procedure RemoveIdleProc(proc:TIdleEvent);
  764. var
  765.   i: integer;
  766. begin
  767.   if (dummy=NIL) or (idleprocs=NIL) then exit;
  768.   for i:=idleprocs.count-1 downto 0 do
  769.     if (idleprocs.items[i]<>NIL) and
  770.        compare_method(TMethod(idleprocs.items[i]).methodpointer,
  771.                       TMethodpointer(proc))  then
  772.       idleprocs.delete(i);
  773.   end;
  774. (*@\\\*)
  775. (*@\\\000000062B*)
  776. (*@\\\*)
  777. (*@/// Generating HWnd's without the routines in forms *)
  778. { Creating a new HWnd with a WndProc for an arbitrary class. Just the same   }
  779. { as the routines in forms, but without the assembler stuff and using simple }
  780. { TList's for the storage - maybe not as fast the original routines, but     }
  781. { much easier to understand and to use. This is only for fun here as the     }
  782. { routines in forms do absolutely the same, but this stuff may be used to    }
  783. { create an console application without using forms but receiving Windows    }
  784. { messages.                                                                  }
  785.  
  786. const
  787.   (*@/// UtilWindowClass: TWndClass = (...); *)
  788.   UtilWindowClass: TWndClass = (
  789.     style: 0;
  790.     lpfnWndProc: @DefWindowProc;
  791.     cbClsExtra: 0;
  792.     cbWndExtra: 0;
  793.     hInstance: 0;
  794.     hIcon: 0;
  795.     hCursor: 0;
  796.     hbrBackground: 0;
  797.     lpszMenuName: nil;
  798.     lpszClassName: 'TAHUtilWindow');
  799.   (*@\\\*)
  800.   WndProcs: TObjectList =NIL;
  801.   WndWnds: TList        =NIL;
  802.  
  803. { Converts a Windows WndProc (HWnd as parameter) to a Delphi method with }
  804. { self as implicit first parameter by looking up the HWnd in the List    }
  805. (*@/// function AH_StdWndProc(Window: HWND; Message,WParam,LParam: Word/Longint); *)
  806. (*$ifdef delphi_1 *)
  807. function AH_StdWndProc(Window: HWND; Message: Longint; WParam: Word;
  808.   LParam: Longint): Longint; export;
  809. (*$else *)
  810. function AH_StdWndProc(Window: HWND; Message: Word; WParam: Longint;
  811.   LParam: Longint): Longint; stdcall;
  812. (*$endif *)
  813. var
  814.   p: integer;
  815.   m: TMessage;
  816. begin
  817.   m.msg:=message;
  818.   m.wparam:=wparam;
  819.   m.lparam:=lparam;
  820.   m.result:=0;
  821.   p:=wndwnds.indexof(pointer(window));
  822.   if p>=0 then
  823.     TWndProc(TMethod(wndprocs.Items[p]).methodpointer)(m);
  824.   result:=m.result;
  825.   end;
  826. (*@\\\0000000112*)
  827. { Creates a new HWnd and link it with the given Method }
  828. (*@/// function AH_AllocateHWnd(Method: TWndProc): HWND; *)
  829. function AH_AllocateHWnd(Method: TWndProc): HWND;
  830. var
  831.   tempmethod: TMethod;
  832.   TempClass: TWndClass;
  833. begin
  834.   result:=0;
  835.   if (wndprocs=NIL) then exit;
  836.  
  837.   UtilWindowClass.hInstance := HInstance;
  838.   if not GetClassInfo(HInstance, UtilWindowClass.lpszClassName, TempClass) then
  839. (*$ifdef delphi_1 *)
  840.     WinProcs.RegisterClass(UtilWindowClass);
  841. (*$else *)
  842.     Windows.RegisterClass(UtilWindowClass);
  843. (*$endif *)
  844.   Result := CreateWindow(UtilWindowClass.lpszClassName, '', 0,
  845.     0, 0, 0, 0, 0, 0, HInstance, nil);
  846.  
  847.   tempmethod:=TMethod.Create;
  848.   tempmethod.methodpointer:=TMethodPointer(method);
  849.  
  850.   { These two lists must be absolutely parallel, otherwise the messages may }
  851.   { go to the wrong object                                                  }
  852.   wndprocs.add(tempmethod);
  853.   wndwnds.add(pointer(result));
  854.  
  855.   SetWindowLong(Result, GWL_WNDPROC, Longint(@AH_StdWndProc));
  856. end;
  857. (*@\\\0000000B12*)
  858. { Removes the HWnd both in Windows an in the internal lists }
  859. (*@/// procedure AH_DeallocateHWnd(Wnd: HWND); *)
  860. procedure AH_DeallocateHWnd(Wnd: HWND);
  861. var
  862.   p: integer;
  863. begin
  864.   DestroyWindow(Wnd);
  865.   p:=wndwnds.remove(pointer(Wnd));
  866.   if p>=0 then
  867.     wndprocs.delete(p);
  868. end;
  869. (*@\\\*)
  870. (*@\\\0000001401*)
  871.  
  872. (*@/// Make Stream and Clipboard work together *)
  873. (*@/// function GetPointer(index: integer; memblock: THandle):pointer; *)
  874. function GetPointer(index: integer; memblock: THandle):pointer;
  875. (*$ifdef delphi_1 *)
  876. var
  877.   selector, offset: word;
  878.   P: pointer;
  879. begin
  880.   selector:=(index div 65536) * selectorinc + memblock;
  881.   offset:=(index mod 65536);
  882.   p:=GlobalLock(Selector);
  883.   result:=Ptr(selector,offset);
  884.   end;
  885. (*$else *)
  886. begin
  887.   result:=pointer(longint(GlobalLock(memblock))+index);
  888.   end;
  889. (*$endif *)
  890. (*@\\\0000000212*)
  891. (*@/// procedure Stream2Clipboard(stream:TStream; format:integer); *)
  892. procedure Stream2Clipboard(stream:TStream; format:integer);
  893. const
  894.   max_write = $8000;    (* must obey ($10000 mod max_write = 0) for Delphi 1 *)
  895. var
  896.   size: longint;
  897.   s: word;
  898.   curpos: longint;
  899.   Memblock: THandle;
  900.   FClipboardWindow: THandle;
  901. begin
  902.   FClipboardWindow := Application.Handle;
  903.   if FClipboardWindow = 0 then
  904.     FClipboardWindow := AllocateHWnd(NIL);
  905.   OpenClipboard(FClipboardWindow);
  906.  
  907.   stream.seek(0,0);
  908.   size:=stream.size;
  909.   stream.seek(0,0);
  910.   MemBlock:=GlobalAlloc(gmem_moveable or gmem_zeroinit,size+1);
  911.   curpos:=0;
  912.   while curpos+1<size do begin
  913.     s:=stream.read(getPointer(curpos,MemBlock)^,min(max_write,size-curpos));
  914.     inc(curpos,s);
  915.     GlobalUnLock(MemBlock);
  916.     if s=0 then BREAK;
  917.     end;
  918.   char(getPointer(curpos,memblock)^):=#0;
  919.   GlobalUnLock(MemBlock);
  920.   EmptyClipBoard;
  921.   SetClipBoardData(format,memblock);
  922.  
  923.   CloseClipboard;
  924.   if FClipboardWindow<>Application.Handle then
  925.     DeallocateHWnd(FClipboardWindow);
  926.   end;
  927. (*@\\\0000001601*)
  928. (*@/// procedure Clipboard2Stream(stream:TStream; format:integer); *)
  929. procedure Clipboard2Stream(stream:TStream; format:integer);
  930. const
  931.   max_read = $8000;   (* must obey ($10000 mod max_read = 0) for Delphi 1 *)
  932. var
  933.   size: longint;
  934.   curpos: longint;
  935.   Memblock: THandle;
  936.   FClipboardWindow: THandle;
  937. begin
  938.   FClipboardWindow := Application.Handle;
  939.   if FClipboardWindow = 0 then
  940.     FClipboardWindow := AllocateHWnd(NIL);
  941.   OpenClipboard(FClipboardWindow);
  942.  
  943.   stream.seek(0,0);
  944.   MemBlock:=GetClipboardData(format);
  945.   size:=GlobalSize(Memblock);
  946.   curpos:=0;
  947.   while curpos+1<size do begin
  948.     stream.write(getPointer(curpos,MemBlock)^,min(max_read,size-curpos-1));
  949.     inc(curpos,min(max_read,size-curpos-1));
  950.     GlobalUnLock(MemBlock);
  951.     end;
  952.  
  953.   CloseClipboard;
  954.   if FClipboardWindow<>Application.Handle then
  955.     DeallocateHWnd(FClipboardWindow);
  956.   end;
  957. (*@\\\0000000C01*)
  958. (*@\\\0000000301*)
  959.  
  960. (*@/// Windows Resources and Languages *)
  961. (*$ifdef delphi_gt_1 *)
  962. (*@/// function makelangid(language,sublanguage: word):longint; *)
  963. function makelangid(language,sublanguage: word):longint;
  964. begin
  965.   result:=((language and $3FF) or ((sublanguage and $3F) shl 10)) and $FFFF;
  966.   end;
  967. (*@\\\*)
  968. (*@/// function primarylangid(language:word):word; *)
  969. function primarylangid(language:word):word;
  970. begin
  971.   result:=language and $3FF;
  972.   end;
  973. (*@\\\*)
  974. (*@/// function sublangid(language:word):word; *)
  975. function sublangid(language:word):word;
  976. begin
  977.   result:=(language shr 10) and $3F;
  978.   end;
  979. (*@\\\*)
  980. (*@/// function langidfromlcid(lcid:longint):word; *)
  981. function langidfromlcid(lcid:longint):word;
  982. begin
  983.   result:=lcid and $FFFF;
  984.   end;
  985. (*@\\\*)
  986.  
  987. (*@/// function MyLoadStringInternal(Instance: THandle; Id: word; languageid: word):string; *)
  988. function MyLoadStringInternal(Instance: THandle; Id: word; languageid: word):string;
  989. var
  990.   h,h1: THandle;
  991.   p: ^word;
  992.   _length: word;
  993.   i: integer;
  994. begin
  995.   h:=FindResourceEx(Instance,rt_string,MakeIntResource((id div 16)+1),languageid);
  996.   if h<>0 then begin
  997.     h1:=Loadresource(Instance,h);
  998.     p:=LockResource(h1);
  999.     i:=id mod 16;
  1000.     while i>0 do begin
  1001.       _length:=p^;
  1002.       inc(p,_length+1);
  1003.       dec(i);
  1004.       end;
  1005.     _length:=p^;
  1006.     inc(p);
  1007.     setlength(result,WideCharToMultiByte(cp_acp,0,PWideChar(p),_length,NIL,0,NIL,NIL));
  1008.     WideCharToMultiByte(cp_acp,0,PWideChar(p),_length,@result[1],length(result),NIL,NIL);
  1009.     FreeResource(h1);
  1010.     end
  1011.   else
  1012.     result:='';
  1013.   end;
  1014. (*@\\\*)
  1015. (*@/// function MyLoadString(Instance: THandle; Id: word; languageid: word):string; *)
  1016. function MyLoadString(Instance: THandle; Id: word; languageid: word):string;
  1017. begin
  1018.   result:=MyLoadStringInternal(Instance,id,languageid);
  1019.   if result='' then
  1020.     result:=MyLoadStringInternal(Instance,id,makelangid(primarylangid(languageid),sublang_default));
  1021.   if result='' then
  1022.     result:=MyLoadStringInternal(Instance,id,makelangid(primarylangid(languageid),sublang_neutral));
  1023.   if result='' then
  1024.     result:=MyLoadStringInternal(Instance,id,makelangid(lang_neutral,sublang_neutral));
  1025.   end;
  1026. (*@\\\*)
  1027. (*@/// function LoadStrEx(id:word; languageid: word):string; *)
  1028. function LoadStrEx(id:word; languageid: word):string;
  1029. begin
  1030.   result:=MyLoadString(HInstance,id,languageid);
  1031.   end;
  1032. (*@\\\*)
  1033. (*$endif *)
  1034. (*@/// function LoadStr(id:word):string; *)
  1035. function LoadStr(id:word):string;
  1036. begin
  1037.   (*$ifdef delphi_gt_1 *)
  1038.   result:=MyLoadString(HInstance,id,GetUserDefaultLangId);
  1039.   (*$else *)
  1040.   result:=sysutils.loadstr(id);
  1041.   (*$endif *)
  1042.   end;
  1043. (*@\\\003C00050100060100070100080100070B*)
  1044. (*@\\\*)
  1045.  
  1046. (*@/// function ScrollBarVisible(control: TWinControl; vertical: boolean):boolean; *)
  1047. function ScrollBarVisible(control: TWinControl; vertical: boolean):boolean;
  1048. (*$ifdef delphi_1 *)
  1049. var
  1050.   code: integer;
  1051.   min,max: integer;
  1052. begin
  1053.   if vertical then
  1054.     code:=sb_vert
  1055.   else
  1056.     code:=sb_horz;
  1057.   GetScrollRange(control.handle,code,min,max);
  1058.   result:=(min<>max);
  1059.   end;
  1060. (*$else *)
  1061. var
  1062.   code: integer;
  1063.   ScrollInfo: TScrollInfo;
  1064. begin
  1065.   if vertical then
  1066.     code:=sb_vert
  1067.   else
  1068.     code:=sb_horz;
  1069.   scrollinfo.cbsize:=sizeof(scrollinfo);
  1070.   scrollinfo.fmask:=sif_all;
  1071.   if GetScrollInfo(control.handle,code,scrollinfo) then
  1072.     result:=(scrollinfo.nmax<>scrollinfo.nmin)
  1073.   else
  1074.     result:=false;
  1075.   end;
  1076. (*$endif *)
  1077. (*@\\\*)
  1078.  
  1079. (*@/// procedure DoneUnit;  // The cleanup of the unit, called in finalization *)
  1080. procedure DoneUnit; far;
  1081. begin
  1082. (*$ifndef delphi_ge_3 *)
  1083. { For design mode: relink the OnShowHint back to it's default value;   }
  1084. { only needed since with Delphi 3 packages the finalization may be     }
  1085. { called without Delphi itself is closed                               }
  1086.  
  1087.   if (ShowHintProcs<>NIL) and
  1088.      (ShowHintProcs.Count>0) then
  1089.        Application.OnShowHint:=TShowHintEvent(TMethod(ShowHintProcs.Items[0]).methodpointer);
  1090.  
  1091. { The explicit removing of the list entries is needed since the delete method }
  1092. {  of the TLIst isn't virtual an therefore not called by the Free             }
  1093.   if ShowHintProcs<>NIL then
  1094.     while ShowHintProcs.Count>0 do
  1095.       ShowHintProcs.delete(0);
  1096.   ShowHintProcs.Free;
  1097.   ShowHintProcs:=NIL;
  1098. (*$endif *)
  1099.   if IdleProcs<>NIL then
  1100.     while IdleProcs.Count>0 do
  1101.       IdleProcs.delete(0);
  1102.   IdleProcs.Free;
  1103.   IdleProcs:=NIL;
  1104.   Dummy.Free;
  1105.   Dummy:=NIL;
  1106.  
  1107. { The explicit removing of the list entries is needed since the delete method }
  1108. {  of the TLIst isn't virtual an therefore not called by the Free             }
  1109.   if WndProcs<>NIL then
  1110.     while WndProcs.Count>0 do
  1111.       WndProcs.delete(0);
  1112.   WndProcs.Free;
  1113.   WndProcs:=NIL;
  1114.   WndWnds.Free;
  1115.   WndWnds:=NIL;
  1116.   end;
  1117. (*@\\\*)
  1118. (*@\\\0000001101*)
  1119. (*@/// initialization *)
  1120. (*$ifndef delphi_ge_3 *)
  1121. var
  1122.   t:TShowHintEvent;
  1123. (*$endif *)
  1124. (*$ifdef delphi_1 *)
  1125. begin
  1126. (*$else *)
  1127. initialization
  1128. begin
  1129. (*$endif *)
  1130.   Dummy:=TDummyObject.Create;
  1131.   IdleProcs:=TObjectList.Create;
  1132.  
  1133.   (* Since Delphi 3 there is the CM_HINTSHOW instead,
  1134.      so this isn't needed anymore *)
  1135. (*$ifndef delphi_ge_3 *)
  1136.   ShowHintProcs:=TObjectList.Create;
  1137.   t:=application.OnShowHint;
  1138.   if assigned(t) then      { D1 can't do a assigned of a property          }
  1139.     AddShowHintProc(t);    { In design mode the OnShowHint is responsible  }
  1140.                            { for the hints of the component palette so I   }
  1141.                            { need to remember this                         }
  1142. (*$endif *)
  1143.   WndProcs:=TObjectList.Create;
  1144.   WndWnds:=TList.Create;
  1145. (*@\\\000000040C*)
  1146. (*@/// finalization *)
  1147. (*$ifdef delphi_1 *)
  1148.   AddExitProc(DoneUnit);
  1149. (*$else *)
  1150.   end;
  1151. finalization
  1152.   DoneUnit;
  1153. (*$endif *)
  1154. (*@\\\0000000201*)
  1155. end.
  1156. (*@\\\0003000701000011000701*)
  1157.