initial commit
[rofl0r-KOL.git] / Kol.pas.200to208-000.old
blob06e1777e5578eda0fab10cdc75a5d362367f2198
1 //[START OF KOL.pas]\r
2 {****************************************************************\r
3 \r
4         KKKKK    KKKKK    OOOOOOOOO    LLLLL\r
5         KKKKK    KKKKK  OOOOOOOOOOOOO  LLLLL\r
6         KKKKK    KKKKK  OOOOO   OOOOO  LLLLL\r
7         KKKKK  KKKKK    OOOOO   OOOOO  LLLLL\r
8         KKKKKKKKKK      OOOOO   OOOOO  LLLLL\r
9         KKKKK  KKKKK    OOOOO   OOOOO  LLLLL\r
10         KKKKK    KKKKK  OOOOO   OOOOO  LLLLL\r
11         KKKKK    KKKKK  OOOOOOOOOOOOO  LLLLLLLLLLLLL\r
12         KKKKK    KKKKK    OOOOOOOOO    LLLLLLLLLLLLL\r
14   Key Objects Library (C) 2000 by Kladov Vladimir.\r
16 //[VERSION]\r
17 ****************************************************************\r
18 * VERSION 2.00\r
19 ****************************************************************\r
20 //[END OF VERSION]\r
22   K.O.L. - is a set of objects to create small programs\r
23   with the Delphi, but without the VCL. KOL allows to\r
24   create executables of size about 10 times smaller then\r
25   those created with the VCL. But this does not mean that\r
26   KOL is less power then the VCL - perhaps just the opposite...\r
28   KOL is provided free with the source code.\r
29   Copyright (C) Vladimir Kladov, 2000-2003.\r
31   For code provided by other  developers (even if later\r
32   changed by me) authors are noted in the source.\r
34   mailto: bonanzas@online.sinor.ru\r
35   Web-Page: http://bonanzas.rinet.ru\r
37   See also Mirror Classes Kit (M.C.K.) which allows\r
38   to create KOL programs visually.\r
40 ****************************************************************}\r
42 //[UNIT DEFINES]\r
43 {$INCLUDE delphidef.inc}\r
45 //[START OF UNIT]\r
46 unit KOL;\r
47 {-}\r
48 {*\r
49    Please note, that KOL does not use keyword 'class'. Instead,\r
50    poor Pascal 'object' is the base of our objects. So, remember,\r
51    how we worked earlier with such Object Pascal's objects:\r
52 |<br>\r
53    - to create objects dynamically, use P<objname> instead of\r
54      T<objname> to allocate a pointer for dynamically created\r
55      object instance;\r
56 |<br>\r
57    - remember, that constructors of objects can not be virtual.\r
58      Override procedure Init instead in your own derived objects;\r
59 |<br>\r
60    - rather then call constructors of objects, call global procedures\r
61      New<objname> (e.g. NewLabel). If not, first (for virtualally\r
62      created objects) call New( ); then call constructor Create\r
63      (which calls Init) - but this is possible only if the constructor\r
64      is overriden by a new one.\r
65 |<br>\r
66    - the operator 'is' is not applicable to objects. And operator 'as'\r
67      is not necessary (and is not applicable too), use typecast to desired\r
68      object type, e.g.: "PSomeObjectType( C )" inplace of "C as TSomeClassType".\r
69 |<br>\r
70 |<hr>\r
71      Also remember, that IF [ MyObj: PMyObj ] THEN\r
73      NOT[ with MyObj do ] BUT[ with MyObj^ do ]\r
75      Though it is possible to skip '^' symbol when accessing member\r
76      fields, methods, properties, e.g. [ MyObj.Execute; ]\r
77 |<hr>\r
78 |&U=&nbsp;&nbsp;&nbsp;<a href="#%0">%0</a><br>\r
79 |&B=<a href="%1.htm">%0</a><br>\r
80 |&C=<a href="%1.htm">%0</a>\r
81 |     <table border=1 cellpadding=6 width=100%>\r
82 |     <colgroup valign=top span=2>\r
83 |       <tr>\r
84 |         <td>  objects  </td>     <td>   functions by category </td>\r
85 |       </tr>\r
86 |         <td>\r
87               <C _TObj> <B TObj>\r
88               <C TList> <C TListEx> <C TStrList> <B TStrListEx>\r
89               <C TTree> <C TDirList> <C TIniFile> <C TCabFile>\r
90               <B TStream>\r
91               <B TControl>\r
92               <C TGraphicTool> <C TCanvas> <C TImageList> <C TIcon> <C TBitmap>\r
93               <C TGif> <C TGifDecoder> <B TJpeg>\r
94               <C TTimer> <C TThread> <C TTrayIcon> <C TDirChange> <B TMediaPlayer>\r
95               <C TMenu> <C TOpenSaveDialog> <C TOpenDirDialog> <B TColorDialog>\r
96               <C TAction> <B TActionList>\r
97               <B Exception>\r
98 |         </td>\r
99 |         <td>\r
100 |<a href="kol_pas.htm#visual_objects_constructors">\r
101       Visual objects constructing functions\r
102 |</a><br><br>\r
103               <U Working with null-terminated and ansi strings>\r
104               <U Small bit arrays (max 32 bits in array)>\r
105               <U Arithmetics, geometry and other utility functions>\r
106               <U Data sorting (quicksort implementation)>\r
107               <U String to number and number to string conversions>\r
108               <U 64-bit integer numbers>\r
109               <U Floating point numbers>\r
110               <U Date and time handling>\r
111               <U File and directory routines>\r
112               <U System functions and working with windows>\r
113               <U Text in clipboard operations>\r
114               <U Wrappers to registry API functions>\r
115 |         </td>\r
116 |     </table>\r
118   Several conditional symbols can be used in a project\r
119   (Project | Options | Directories/Conditional Defines)\r
120   to change code generated a bit. There are following:\r
121 |<pre>\r
123   PAS_VERSION           - to use Pascal version of the code.\r
124   PARANOIA              - to force short versions of asm instructions (for D5\r
125                         and below, D6 and higher use those instructions always).\r
126   USE_CONSTRUCTORS      - to use constructors like in VCL.\r
127   USE_CUSTOMEXTENSIONS  - to extend TControl with custom additions.\r
128   UNICODE_CTRLS         - to use Unicode versions of controls (WM_XXXXW messages,\r
129                         etc.)\r
130   USE_MHTOOLTIP         - to use MHTOOLTIP.\r
131   NOT_USE_OnIdle        - to stop using OnIdle event (to make code smaller\r
132                         if it is not used actually).\r
133   USE_ASM_DODRAG        - to use assembler version of code for DoDrag.\r
134   ENUM_DYN_HANDLERS_AFTER_RUN - to allow all the events handling even when\r
135                         AppletTerminated become TRUE.\r
136   ALL_BUTTONS_RESPOND_TO_ENTER - obvious (by default, buttons respond to key\r
137                         SPACE, since those are working this way in Windows).\r
138   ESC_CLOSE_DIALOGS     - to allow closing all dialogs with ESCAPE.\r
139   OpenSaveDialog_Extended - to allow using custom extensions for OpenSaveDialog.\r
140   AUTO_CONTEXT_HELP     - to use automatic respond to WM_CONTEXTMENU to call\r
141                         context help.\r
142   NOT_FIX_CURINDEX      - to use old version of TControl.SetItems, which could\r
143                         lead to loose CurIndex value (e.g. for Combobox)\r
144   NEW_MODAL             - to use extended madalness.\r
145   USE_SETMODALRESULT    - to guarantee ModalResult property assigninig handling.\r
146   USE_MENU_CURCTL       - to use CurCtl property in popup menu to detect which\r
147                         control initiated a pop-up.\r
148   NEW_MENU_ACCELL       - to use another menu accelerators handling, without\r
149                         AcceleratorTable\r
150   USE_DROPDOWNCOUNT     - to force setting combobox dropdown count.\r
151   NOT_UNLOAD_RICHEDITLIB - to stop unload Rich Edit library in finalization\r
152                         section (to economy several byte of code).\r
153   DEBUG_GDIOBJECTS      - to allow counting all the GDI objects used.\r
154   CHK_BITBLT            - to check BitBlt operations.\r
155   DEBUG_ENDSESSION      - to allow debugging WM_ENDSESSION handling.\r
156   DEBUG_CREATEWINDOW    - to debug CreateWindow.\r
157   TEST_CLOSE            - to debug Close.\r
158   DEBUG_MENU            - to debug menu.\r
159   DEBUG_DBLBUFF         - to debug DoubleBuffered.\r
160   DEBUG                 - other debugging.\r
162 |</pre>\r
164 {= K.O.L - êëþ÷åâàÿ áèáëèîòåêà îáúåêòîâ. (C) Êëàäîâ Âëàäèìèð, 2000-2003.\r
167 //[OPTIONS]\r
168 {$A-} // align off, otherwise code is not good\r
169 {+}\r
171 {$Q-} // no overflow check: this option makes code wrong\r
172 {$R-} // no range checking: this option makes code wrong\r
173 {$T-} // not typed @-operator\r
174 //{$D+}\r
175 {$IFDEF INPACKAGE} // use this symbol in packages requiring kol.pas\r
176   {$WARNINGS OFF}\r
177 {$ENDIF}\r
178 {$IFDEF _D7orHigher}\r
179   {$WARN UNSAFE_TYPE OFF} // Too many such warnings in Delphi7\r
180   {$WARN UNSAFE_CODE OFF}\r
181   {$WARN UNSAFE_CAST OFF}\r
182 {$ENDIF}\r
185 //[START OF INTERFACE]\r
186 interface\r
188 //{$DEFINE DEBUG_GDIOBJECTS}\r
189 //{$DEFINE CHK_GDI}\r
191 //[USES]\r
192 uses\r
193     messages, windows, RichEdit {$IFDEF CHK_GDI}, ChkGdi {$ENDIF};\r
194 //[END OF USES]\r
196 {$IFDEF DEBUG_GDIOBJECTS}\r
197 var\r
198   BrushCount: Integer;\r
199   FontCount: Integer;\r
200   PenCount: Integer;\r
201 {$ENDIF}\r
204 //{_#IF [DELPHI]}\r
205 {$INCLUDE delphicommctrl.inc}\r
206 //{_#ENDIF}\r
208 type\r
209 //[_TObj DEFINITION]\r
211 {-}\r
212    _TObj = object\r
213    {* auxiliary object type. See TObj. }\r
214    protected\r
215      procedure Init; virtual;\r
216      {* Is called from a constructor to initialize created object instance\r
217         filling its fields with 0. Can be overriden in descendant objects\r
218         to add another initialization code there. (Main reason of intending\r
219         is what constructors can not be virtual in poor objects). }\r
220      {= Âûçûâàåòñÿ äëÿ èíèöèàëèçàöèè îáúåêòà. }\r
221    public\r
222      function VmtAddr: Pointer;\r
223      {* Returns addres of virtual methods table of object. ? }\r
224      {= âîçâðàùàåò àäðåñ òàáëèöû âèðòóàëüíûõ ìåòîäîâ (VMT). ? }\r
225    end;\r
226 {+}\r
228   {++}(* TObj = class;*){--}\r
229   PObj = {-}^{+}TObj;\r
230   {* }\r
232   {++}(* TList = class;*){--}\r
233   PList = {-}^{+}TList;\r
234   {* }\r
236 //[TObjectMethod DECLARATION]\r
237   TObjectMethod = procedure of object;\r
238   {* }\r
239   TOnEvent = procedure( Sender: PObj ) of object;\r
240   {* This type of event is the most common - event handler when called can\r
241      know only what object was a sender of this call. Replaces good known\r
242      VCL TNotifyEvent event type. }\r
244 //[TPointerList DECLARATION]\r
245    PPointerList = ^TPointerList;\r
246    TPointerList = array[0..MaxInt div 4 - 1] of Pointer;\r
248 { ---------------------------------------------------------------------\r
250                   TObj - base object to derive all others\r
252 ---------------------------------------------------------------------- }\r
253 //[TObj DEFINITION]\r
254    TObj = {-} object( _TObj ) {+}{++}(*class*){--}\r
255    {* Prototype for all objects of KOL. All its methods are important to\r
256       implement objects in a manner similar to Delphi TObject class. }\r
257    {= Áàçîâûé êëàññ äëÿ âñåõ ïðî÷èõ îáúåêòîâ KOL. }\r
258    protected\r
259      fRefCount: Integer;\r
260      fOnDestroy: TOnEvent;\r
261      procedure DoDestroy;\r
262    protected\r
263      fAutoFree: PList;\r
264      {* Is called from a constructor to initialize created object instance\r
265         filling its fields with 0. Can be overriden in descendant objects\r
266         to add another initialization code there. (Main reason of intending\r
267         is what constructors can not be virtual in poor objects). }\r
268      {= Âûçûâàåòñÿ äëÿ èíèöèàëèçàöèè îáúåêòà. }\r
269      fTag: DWORD;\r
270      {* Custom data. }\r
271    {++}(*public*){--}\r
272      destructor Destroy; {-} virtual; {+}{++}(* override; *){--}\r
273      {* Disposes memory, allocated to an object. Does not release huge strings,\r
274         dynamic arrays and so on. Such memory should be freeing in overriden\r
275         destructor. }\r
276      {= Îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ äëÿ îáúåêòà. Íå îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ\r
277         äëÿ ñòðîê, äèíàìè÷èñêèõ ìàññèâîâ è ò.ï. Òàêàÿ ïàìÿòü äîëæíà áûòü îñâîáîæäåíà\r
278         â ïåðåîïðåäåëåííîì äåñòðóêòîðå îáúåêòà. }\r
279    {++}(*protected*){--}\r
280      {++}(*\r
281      procedure Init; virtual;\r
282      {* Can be overriden in descendant objects\r
283         to add initialization code there. (Main reason of intending\r
284         is what constructors can not be virtual in poor objects). }\r
285      *){--}\r
286      procedure Final;\r
287      {* Is called in destructor to perform OnDestroy event call and to\r
288         released objects, added to fAutoFree list. }\r
289    public\r
290      procedure Free;\r
291      {* Before calling destructor of object, checks if passed pointer is not\r
292         nil - similar what is done in VCL for TObject. It is ALWAYS recommended\r
293         to use Free instead of Destroy - see also comments to RefInc, RefDec. }\r
294      {= Äî âûçîâà äåñòðóêòîðà, ïðîâåðÿåò, íå ïåðåäàí ëè nil â êà÷åñòâå ïàðàìåòðà.\r
295         ÂÑÅÃÄÀ ðåêîìåíäóåòñÿ èñïîëüçîâàòü Free âìåñòî Destroy - ñì. òàê æå RefInc,\r
296         RefDec. }\r
298      {-}\r
299      // By Vyacheslav Gavrik:\r
300      function InstanceSize: Integer;\r
301      {* Returns a size of object instance. }\r
302      {+}\r
304      constructor Create;\r
305      {* Constructor. Do not call it. Instead, use New<objectname> function\r
306         call for certain object, e.g., NewLabel( AParent, 'caption' ); }\r
307      {= Êîíñòðóêòîð. Íå ñëåäóåò âûçûâàòü åãî. Äëÿ êîíñòðóèðîâàíèÿ îáúåêòîâ,\r
308         âûçûâàéòå ñîîòâåòñòâóþùóþ ãëîáàëüíóþ ôóíêöèþ New<èìÿ-îáúåêòà>. Íàïðèìåð,\r
309         NewLabel( MyForm, 'Ìåòêà¹1' ); }\r
310      {-}\r
311      class function AncestorOfObject( Obj: Pointer ): Boolean;\r
312      {* Is intended to replace 'is' operator, which is not applicable to objects. }\r
313      {= }\r
314      function VmtAddr: Pointer;\r
315      {* Returns addres of virtual methods table of object. }\r
316      {= âîçâðàùàåò àëðåñ òàáëèöû âèðòóàëüíûõ ìåòîäîâ (VMT). }\r
317      {+}\r
318      procedure RefInc;\r
319      {* See comments below. }\r
320      {= Ñì. RefDec íèæå. }\r
321      procedure RefDec;\r
322      {* Decrements reference count. If it is becoming <0, and Free\r
323         method was already called, object is (self-) destroyed. Otherwise,\r
324         Free method does not destroy object, but only sets flag\r
325         "Free was called".\r
326      |<br>\r
327         Use RefInc..RefDec to provide a block of code, where\r
328         object can not be destroyed by call of Free method.\r
329         This makes code more safe from intersecting flows of processing,\r
330         where some code want to destroy object, but others suppose that it\r
331         is yet existing.\r
332      |<br>\r
333         If You want to release object at the end of block RefInc..RefDec,\r
334         do it immediately BEFORE call of last RefDec (to avoid situation,\r
335         when object is released in result of RefDec, and attempt to\r
336         destroy it follow leads to AV exception).\r
337      }\r
338      {= Óìåíüøàåò ñ÷åò÷èê èñïîëüçîâàíèÿ. Åñëè â ðåçóëüòàòå ñ÷åò÷èê ñòàíîâèòñÿ\r
339         < 0, è ìåòîä Free óæå áûë âûçâàí, îáúåêò (ñàìî-) ðàçðóøàåòñÿ. Èíà÷å,\r
340         ìåòîä Free íå ðàçðóøàåò îáúåêò, à òîëüêî óñòàíàâëèâàåò ôëàã "Free áûë\r
341         âûçâàí".\r
342         |<br>\r
343         Èñïîëüçóéòå RefInc..RefDec äëÿ ïðåäîòâðàùåíèÿ ðàçðóøåíèÿ îáúåêòà íà\r
344         íåêîòîðîì ó÷àñòêå êîäà (åñëè åñòü òàêàÿ íåîáõîäèìîñòü).\r
345         |<br>\r
346         Åñëè íóæíî óáèòü (âðåìåííûé) îáúåêò âìåñòå ñ ïîñëåäíèì RefDec, ñäåëàéòå\r
347         âûçîâ Free íåìåäëåííî ÏÅÐÅÄ ïîñëåäíèì RefDec. }\r
348      property RefCount: Integer read fRefCount;\r
349      {* }\r
350      property OnDestroy: TOnEvent read fOnDestroy write fOnDestroy;\r
351      {* This event is provided for any KOL object, so You can provide your own\r
352         OnDestroy event for it. }\r
353      {= Äàííîå ñîáûòèå îáåñïå÷èâàåòñÿ äëÿ âñåõ îáúåêòîâ KOL. Ïîçâîëÿåò ñäåëàòü\r
354         ÷òî-íèáóäü â ñâÿçè ñ ðàçðóøåíèåì îáúåêòà. }\r
355     procedure Add2AutoFree( Obj: PObj );\r
356     {* Adds an object to the list of objects, destroyed automatically\r
357        when the object is destroyed. Do not add here child controls of\r
358        the TControl (these are destroyed by another way). Only non-control\r
359        objects, which are not destroyed automatically, should be added here. }\r
360     procedure Add2AutoFreeEx( Proc: TObjectMethod );\r
361     {* Adds an event handler to the list of events, called in destructor.\r
362        This method is mainly for internal use, and allows to auto-destroy\r
363        VCL components, located on KOL form at design time (in MCK project). }\r
364     property Tag: DWORD read fTag write fTag;\r
365     {* Custom data field. }\r
366    end;\r
367 //[END OF TObj DEFINITION]\r
369 { ---------------------------------------------------------------------\r
371         TList - object to implement list of pointers (or dwords)\r
373 ---------------------------------------------------------------------- }\r
374 //[TList DEFINITION]\r
375   TList = object( TObj )\r
376   {* Simple list of pointers. It is used in KOL instead of standard VCL\r
377      TList to store any kind data (or pointers to these ones). Can be created\r
378      calling function NewList. }\r
379   {= Ïðîñòîé ñïèñîê óêàçàòåëåé. }\r
380   protected\r
381     fItems: PPointerList;\r
382     fCount: Integer;\r
383     fCapacity: Integer;\r
384     fAddBy: Integer;\r
385     procedure SetCount(const Value: Integer);\r
386     procedure SetAddBy(Value: Integer);\r
387   {++}(*public*){--}\r
388     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
389     {* Destroys list, freeing memory, allocated for pointers. Programmer\r
390        is resposible for destroying of data, referenced by the pointers. }\r
391     {= }\r
392   {++}(*protected*){--}\r
393     procedure SetCapacity( Value: Integer );\r
394     function Get( Idx: Integer ): Pointer;\r
395     procedure Put( Idx: Integer; Value: Pointer );\r
396     {$IFDEF USE_CONSTRUCTORS}\r
397     procedure Init; virtual;\r
398     {$ENDIF USE_CONSTRUCTORS}\r
399   public\r
400     procedure Clear;\r
401     {* Makes Count equal to 0. Not responsible for freeing (or destroying)\r
402        data, referenced by released pointers. }\r
403     procedure Add( Value: Pointer );\r
404     {* Adds pointer to the end of list, increasing Count by one. }\r
405     procedure Insert( Idx: Integer; Value: Pointer );\r
406     {* Inserts pointer before given item. Returns Idx, i.e. index of\r
407        inserted item in the list. Indeces of items, located after insertion\r
408        point, are increasing. To add item to the end of list, pass Count\r
409        as index parameter. To insert item before first item, pass 0 there. }\r
410     function IndexOf( Value: Pointer ): Integer;\r
411     {* Searches first (from start) item pointer with given value and returns\r
412        its index (zero-based) if found. If not found, returns -1. }\r
413     procedure Delete( Idx: Integer );\r
414     {* Deletes given (by index) pointer item from the list, shifting all\r
415        follow item indeces up by one. }\r
416     procedure DeleteRange( Idx, Len: Integer );\r
417     {* Deletes Len items starting from Idx. }\r
418     procedure Remove( Value: Pointer );\r
419     {* Removes first entry of a Value in the list. }\r
420     property Count: Integer read fCount write SetCount;\r
421     {* Returns count of items in the list. It is possible to delete a number\r
422        of items at the end of the list, keeping only first Count items alive,\r
423        assigning new value to Count property (less then Count it is). }\r
424     property Capacity: Integer read fCapacity write SetCapacity;\r
425     {* Returns number of pointers which could be stored in the list\r
426        without reallocating of memory. It is possible change this value\r
427        for optimize usage of the list (for minimize number of reallocating\r
428        memory operations). }\r
429     property Items[ Idx: Integer ]: Pointer read Get write Put; default;\r
430     {* Provides access (read and write) to items of the list. Please note,\r
431        that TList is not responsible for freeing memory, referenced by stored\r
432        pointers. }\r
433     function Last: Pointer;\r
434     {* Returns the last item (or nil, if the list is empty). }\r
435     procedure Swap( Idx1, Idx2: Integer );\r
436     {* Swaps two items in list directly (fast, but without testing of\r
437        index bounds). }\r
438     procedure MoveItem( OldIdx, NewIdx: Integer );\r
439     {* Moves item to new position. Pass NewIdx >= Count to move item\r
440        after the last one. }\r
441     procedure Release;\r
442     {* Especially for lists of pointers to dynamically allocated memory.\r
443        Releases all pointed memory blocks and destroys object itself. }\r
444     procedure ReleaseObjects;\r
445     {* Especially for a list of objects derived from TObj.\r
446        Calls Free for every of the object in the list, and then calls\r
447        Free for the object itself. }\r
448     property AddBy: Integer read fAddBy write SetAddBy;\r
449     {* Value to increment capacity when new items are added or inserted\r
450        and capacity need to be increased. }\r
451     property DataMemory: PPointerList read fItems;\r
452     {* Raw data memory. Can be used for direct access to items of a list. }\r
453     procedure Assign( SrcList: PList );\r
454     {* Copies all source list items. }\r
455   end;\r
456 //[END OF TList DEFINITION]\r
458 //[NewList DECLARATION]\r
459 function NewList: PList;\r
460 {* Returns pointer to newly created TList object. Use it instead usual\r
461    TList.Create as it is done in VCL or XCL. }\r
463 procedure FastIncNum2Elements( List: TList; FromIdx, Count, Value: Integer );\r
464 {* Very fast adds Value to List elements from List[FromIdx] to List[FromIdx+Count-1].\r
465    Given elements must exist. Count must be > 0. }\r
467 procedure Free_And_Nil( var Obj );\r
468 {* Obj.Free and Obj := nil, where Obj *MUST* be TObj or its descendant\r
469    (TControl, TMenu, etc.) This procedure is not compatible with VCL's\r
470    FreeAndNil, which works with TObject, since this it has another name. }\r
472 type\r
474 //[TListEx DEFINITION]\r
475   {++}(*TListEx = class;*){--}\r
476   PListEx = {-}^{+}TListEx;\r
477   TListEx = object( TObj )\r
478   {* Extended list, with Objects[ ] property. Created calling NewListEx function. }\r
479   protected\r
480     fList: PList;\r
481     fObjects: PList;\r
482     function GetEx(Idx: Integer): Pointer;\r
483     procedure PutEx(Idx: Integer; const Value: Pointer);\r
484     function GetCount: Integer;\r
485     function GetAddBy: Integer;\r
486     procedure Set_AddBy(const Value: Integer);\r
487   public\r
488     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
489     {* }\r
490     property AddBy: Integer read GetAddBy write Set_AddBy;\r
491     {* }\r
492     property Items[ Idx: Integer ]: Pointer read GetEx write PutEx;\r
493     {* }\r
494     property Count: Integer read GetCount;\r
495     {* }\r
496     procedure Clear;\r
497     {* }\r
498     procedure Add( Value: Pointer );\r
499     {* }\r
500     procedure AddObj( Value, Obj: Pointer );\r
501     {* }\r
502     procedure Insert( Idx: Integer; Value: Pointer );\r
503     {* }\r
504     procedure InsertObj( Idx: Integer; Value, Obj: Pointer );\r
505     {* }\r
506     procedure Delete( Idx: Integer );\r
507     {* }\r
508     procedure DeleteRange( Idx, Len: Integer );\r
509     {* }\r
510     function IndexOf( Value: Pointer ): Integer;\r
511     {* }\r
512     function IndexOfObj( Obj: Pointer ): Integer;\r
513     {* }\r
514     procedure Swap( Idx1, Idx2: Integer );\r
515     {* }\r
516     procedure MoveItem( OldIdx, NewIdx: Integer );\r
517     {* }\r
518     property ItemsList: PList read fList;\r
519     {* }\r
520     property ObjList: PList read fObjects;\r
521     {* }\r
522     function Last: Pointer;\r
523     {* }\r
524     function LastObj: Pointer;\r
525     {* }\r
526   end;\r
527 //[END OF TListEx DEFINITION]\r
529 //[NewListEx DECLARATION]\r
530 function NewListEx: PListEx;\r
531 {* Creates extended list. }\r
539 { -- tree (non-visual) -- }\r
541 type\r
542 //[TTree DEFINITION]\r
543   {++}(*TTree = class;*){--}\r
544   PTree = {-}^{+}TTree;\r
545   TTree = object( TObj )\r
546   {* Object to store tree-like data in memory (non-visual). }\r
547   protected\r
548     fParent: PTree;\r
549     fChildren: PList;\r
550     fPrev: PTree;\r
551     fNext: PTree;\r
552     fName: String;\r
553     fData: Pointer;\r
554     function GetCount: Integer;\r
555     function GetItems(Idx: Integer): PTree;\r
556     procedure Unlink;\r
557     function GetRoot: PTree;\r
558     function GetLevel: Integer;\r
559     function GetTotal: Integer;\r
560     function GetIndexAmongSiblings: Integer;\r
561   protected\r
562     {$IFDEF USE_CONSTRUCTORS}\r
563     constructor CreateTree( AParent: PTree; const AName: String );\r
564     {* }\r
565     {$ENDIF}\r
566   {++}(*public*){--}\r
567     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
568     {* }\r
569   {++}(*protected*){--}\r
570     procedure Init; {-}virtual;{+}{++}(*override;*){--}\r
571   public\r
572     procedure Clear;\r
573     {* Destoyes all child nodes. }\r
574     property Name: String read fName write fName;\r
575     {* Optional node name. }\r
576     property Data: Pointer read fData write fData;\r
577     {* Optional user-defined pointer. }\r
578     property Count: Integer read GetCount;\r
579     {* Number of child nodes of given node. }\r
580     property Items[ Idx: Integer ]: PTree read GetItems;\r
581     {* Child nodes list items. }\r
582     procedure Add( Node: PTree );\r
583     {* Adds another node as a child of given tree node. This operation\r
584        as well as Insert can be used to move node together with its children\r
585        to another location of the same tree or even from another tree.\r
586        Anyway, added Node first correctly removed from old place (if it is\r
587        defined for it). But for simplest task, such as filling of tree with\r
588        nodes, code should looking as follows:\r
589        !  Node := NewTree( nil, 'test of creating node without parent' );\r
590        !  RootOfMyTree.Add( Node );\r
591        Though, this code gives the same result as:\r
592        !  Node := NewTree( RootOfMyTree, 'test of creatign node as a child' ); }\r
593     procedure Insert( Before, Node: PTree );\r
594     {* Inserts earlier created 'Node' just before given child node 'Before'\r
595        as a child of given tree node. See also Add method. }\r
596     property Parent: PTree read fParent;\r
597     {* Returns parent node (or nil, if there is no parent). }\r
598     property Index: Integer read GetIndexAmongSiblings;\r
599     {* Returns an index of the node in a list of nodes of the same parent\r
600        (or -1, if Parent is not defined). }\r
601     property PrevSibling: PTree read fPrev;\r
602     {* Returns previous node in a list of children of the Parent. Nil is\r
603        returned, if given node is the first child of the Parent or has\r
604        no Parent. }\r
605     property NextSibling: PTree read fNext;\r
606     {* Returns next node in a list of children of the Parent. Nil is returned,\r
607        if given node is the last child of the Parent or has no Parent at all. }\r
608     property Root: PTree read GetRoot;\r
609     {* Returns root node (i.e. the last Parent, enumerating parents recursively). }\r
610     property Level: Integer read GetLevel;\r
611     {* Returns level of the node, i.e. integer value, equal to 0 for root\r
612        of a tree, 1 for its children, etc. }\r
613     property Total: Integer read GetTotal;\r
614     {* Returns total number of children of the node and all its children\r
615        counting its recursively (but node itself is not considered, i.e.\r
616        Total for node without children is equal to 0). }\r
617     procedure SortByName;\r
618     {* Sorts children of the node in ascending order. Sorting is not\r
619        recursive, i.e. only immediate children are sorted. }\r
620     procedure SwapNodes( i1, i2: Integer );\r
621     {* Swaps two child nodes. }\r
622     function IsParentOfNode( Node: PTree ): Boolean;\r
623     {* Returns true, if Node is the tree itself or is a parent of the given node\r
624        on any level. }\r
625     function IndexOf( Node: PTree ): Integer;\r
626     {* Total index of the child node (on any level under this node). }\r
628   end;\r
629 //[END OF TTree DEFINITION]\r
631 //[NewTree DECLARATION]\r
632 function NewTree( AParent: PTree; const AName: String ): PTree;\r
633 {* Constructs tree node, adding it to the end of children list of\r
634    the AParent. If AParent is nil, new root tree node is created. }\r
642 //[DummyObjProc, DummyObjProcParam DECLARATION]\r
643 procedure DummyObjProc( Sender: PObj );\r
644 procedure DummyObjProcParam( Sender: PObj; Param: Pointer );\r
649 { --- threads --- }\r
650 //[THREADS]\r
652 const\r
653   ABOVE_NORMAL_PRIORITY_CLASS = $8000; // only for Windows 2K\r
654   BELOW_NORMAL_PRIORITY_CLASS = $4000; // and higher !\r
656 type\r
657   {++}(*TThread = class;*){--}\r
658   PThread = {-}^{+}TThread;\r
660   TThreadMethod = procedure of object;\r
661   TThreadMethodEx = procedure( Sender: PThread; Param: Pointer ) of object;\r
663   TOnThreadExecute = function(Sender:PThread): Integer of object;\r
664   {* Event to be called when Execute method is called for TThread }\r
666 { ---------------------------------------------------------------------\r
668                             TThread object\r
670 ---------------------------------------------------------------------- }\r
671 //[TThread DEFINITION]\r
672   TThread = object(TObj)\r
673   {* Thread object. It is possible not to derive Your own thread-based\r
674      object, but instead create thread Suspended and assign event\r
675      OnExecute. To create, use one of NewThread of NewThreadEx functions,\r
676      or derive Your own descendant object and write creation function\r
677      (or constructor) for it.\r
678      |<br><br>\r
679      Aknowledgements. Originally class ZThread was developed for XCL:\r
680      |<br> * By: Tim Slusher : junior@nlcomm.com\r
681      |<br> * Home: http://www.nlcomm.com/~junior\r
682    }\r
683   protected\r
684     FSuspended,\r
685     FTerminated: boolean;\r
686     FHandle: THandle;\r
687     FThreadId: DWORD;\r
688     FOnSuspend: TObjectMethod;\r
689     FOnResume: TOnEvent;\r
690     FData : Pointer;\r
691     FOnExecute : TOnThreadExecute;\r
692     FMethod: TThreadMethod;\r
693     FMethodEx: TThreadMethodEx;\r
694     F_AutoFree: Boolean;\r
695     function GetPriorityCls: Integer;\r
696     function GetThrdPriority: Integer;\r
697     procedure SetPriorityCls(Value: Integer);\r
698     procedure SetThrdPriority(Value: Integer);\r
699   {++}(*public*){--}\r
700     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
701     {* }\r
702   public\r
703     function Execute: integer; virtual;\r
704     {* Executes thread. Do not call this method from another thread! (Even do\r
705        not call this method at all!) Instead, use Resume.\r
706        |<br>\r
707        Note also that in contrast to VCL, it is not necessary to create your\r
708        own descendant object from TThread and override Execute method. In KOL,\r
709        it is sufficient to create an instance of TThread object (see NewThread,\r
710        NewThreadEx, NewThreadAutoFree functions) and assign OnExecute event\r
711        handler for it. }\r
712     procedure Resume;\r
713     {* Continues executing. It is necessary to make call for every\r
714        nested Suspend. }\r
715     procedure Suspend;\r
716     {* Suspends thread until it will be resumed. Can be called from another\r
717        thread or from the thread itself. }\r
718     procedure Terminate;\r
719     {* Terminates thread. }\r
720     function WaitFor: Integer;\r
721     {* Waits (infinitively) until thead will be finished. }\r
723     property Handle: THandle read FHandle;\r
724     {* Thread handle. It is created immediately when object is created\r
725        (using NewThread). }\r
726     property Suspended: boolean read FSuspended;\r
727     {* True, if suspended. }\r
728     property Terminated: boolean read FTerminated;\r
729     {* True, if terminated. }\r
730     property ThreadId: DWORD read FThreadId;\r
731     {* Thread id. }\r
732     property PriorityClass: Integer read GetPriorityCls write SetPriorityCls;\r
733     {* Thread priority class. One of following values: HIGH_PRIORITY_CLASS,\r
734        IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS. }\r
735     property ThreadPriority: Integer read GetThrdPriority write SetThrdPriority;\r
736     {* Thread priority value. One of following values: THREAD_PRIORITY_ABOVE_NORMAL,\r
737        THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_IDLE,\r
738        THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_TIME_CRITICAL. }\r
739     property Data : Pointer read FData write FData;\r
740     {* Custom data pointer. Use it for Youe own purpose. }\r
742     property OnExecute: TOnThreadExecute read FOnExecute write FOnExecute;\r
743     {* Is called, when Execute is starting. }\r
744     property OnSuspend: TObjectMethod read FOnSuspend write FOnSuspend;\r
745     {* Is called, when Suspend is performed. }\r
746     property OnResume: TOnEvent read FOnResume write FOnResume;\r
747     {* Is called, when resumed. }\r
748     procedure Synchronize( Method: TThreadMethod );\r
749     {* Call it to execute given method in main thread context. Applet variable\r
750        must exist for that time. }\r
751     procedure SynchronizeEx( Method: TThreadMethodEx; Param: Pointer );\r
752     {* Call it to execute given method in main thread context, with a given\r
753        parameter. Applet variable must exist for that time. Param must not be nil. }\r
754     {$IFDEF USE_CONSTRUCTORS}\r
755     constructor ThreadCreate;\r
756     constructor ThreadCreateEx( const Proc: TOnThreadExecute );\r
757     {$ENDIF USE_CONSTRUCTORS}\r
759     property AutoFree: Boolean read F_AutoFree write F_AutoFree;\r
760     {* Set this property to true to provide automatic destroying of thread\r
761        object when its executing is finished. }\r
762   end;\r
763 //[END OF TThread DEFINITION]\r
765 //[NewThread, NewThreadEx, NewThreadAutoFree, Global_Synchronized DECLARATIONS]\r
766 function NewThread: PThread;\r
767 {* Creates thread object (always suspended). After creating, set event\r
768    OnExecute and perform Resume operation. }\r
770 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;\r
771 {* Creates thread object, assigns Proc to its OnExecute event and runs\r
772    it. }\r
774 function NewThreadAutoFree( const Proc: TOnThreadExecute ): PThread;\r
775 {* Creates thread object similar to NewThreadEx, but freeing automatically\r
776    when executing of such thread finished. Be sure that a thread is resumed\r
777    at least to provide its object keeper freeing. }\r
779 var Global_Synchronized: procedure( Sender: PObj; Param: Pointer ) = DummyObjProcParam;\r
780 // It is not necessary to declare it as threadvar.\r
795 { -- streams -- }\r
796 //[STREAMS]\r
798 type\r
799   TMoveMethod = ( spBegin, spCurrent, spEnd );\r
801   {++}(*TStream = class;*){--}\r
802   PStream = {-}^{+}TStream;\r
804   PStreamMethods = ^TStreamMethods;\r
805   TStreamMethods = Packed Record\r
806     fSeek: function( Strm: PStream; MoveTo: Integer; MoveMethod: TMoveMethod ): DWORD;\r
807     fGetSiz: function( Strm: PStream ): DWORD;\r
808     fSetSiz: procedure( Strm: PStream; Value: DWORD );\r
809     fRead: function( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
810     fWrite: function( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
811     fClose: procedure( Strm: PStream );\r
812     fCustom: Pointer;\r
813     fWait: procedure( Strm: PStream );\r
814   end;\r
816   TStreamData = Packed Record\r
817     fHandle: THandle;\r
818     fCapacity, fSize, fPosition: DWORD;\r
819     fThread: PThread;\r
820   end;\r
822 { ---------------------------------------------------------------------\r
824                 TStream - streaming objects incapsulation\r
826 ---------------------------------------------------------------------- }\r
827 //[TStream DEFINITION]\r
828   TStream = object(TObj)\r
829   {* Simple stream object. Can be opened for file, or as memory stream (see\r
830      NewReadFileStream, NewWriteFileStream, NewMemoryStream, etc.). And, another\r
831      type of streaming object can be derived (without inheriting new object\r
832      type, just by writing another New...Stream method, which calls\r
833      _NewStream and pass methods record to it). }\r
834   protected\r
835     fPMethods: PStreamMethods;\r
836     fMethods: TStreamMethods;\r
837     fMemory: Pointer;\r
838     fData: TStreamData;\r
839     fParam1, fParam2: DWORD; // parameters to use in thread\r
840     function GetCapacity: DWORD;\r
841     procedure SetCapacity(const Value: DWORD);\r
842     function DoAsyncRead( Sender: PThread ): Integer;\r
843     function DoAsyncWrite( Sender: PThread ): Integer;\r
844     function DoAsyncSeek( Sender: PThread ): Integer;\r
845   protected\r
846     function GetFileStreamHandle: THandle;\r
847     procedure SetPosition(Value: DWord);\r
848     function GetPosition: DWord;\r
849     function GetSize: DWord;\r
850     procedure SetSize(NewSize: DWord);\r
851   {++}(*public*){--}\r
852     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
853   public\r
854     function Read(var Buffer; Count: DWord): DWord;\r
855     {* Reads Count bytes from a stream. Returns number of bytes read. }\r
856     function Seek(MoveTo: Integer; MoveMethod: TMoveMethod): DWord;\r
857     {* Allows to change current position or to obtain it. Property\r
858        Position uses this method both for get and set position. }\r
859     function Write(var Buffer; Count: DWord): DWord;\r
860     {* Writes Count bytes from Buffer, starting from current position\r
861        in a stream. Returns how much bytes are written. }\r
862     function WriteStr( S: String ): DWORD;\r
863     {* Writes string to the stream, not including ending #0. Exactly\r
864        Length( S ) characters are written. }\r
865     function WriteStrZ( S: String ): DWORD;\r
866     {* Writes string, adding #0. Number of bytes written is returned. }\r
867     function ReadStrZ: String;\r
868     {* Reads string, finished by #0. After reading, current position in\r
869        the stream is set to the byte, follows #0. }\r
870     function ReadStr: String;\r
871     {* Reads string, finished by #13, #10 or #13#10 symbols. Terminating symbols\r
872        #13 and/or #10 are not added to the end of returned string though\r
873        stream positioned follow it. }\r
874     function WriteStrEx(S: String): DWord;\r
875     {* Writes string S to stream, also saving its size for future use by\r
876        ReadStrEx* functions. Returns number of actually written characters. }\r
877     function ReadStrExVar(var S: String): DWord;\r
878     {* Reads string from stream and assigns it to S.\r
879        Returns number of actually read characters.\r
880        Note:\r
881          String must be written by using WriteStrEx function.\r
882          Return value is count of characters READ, not the length of string. }\r
883     function ReadStrEx: String;\r
884     {* Reads string from stream and returns it. }\r
885     function WriteStrPas( S: String ): DWORD;\r
886     {* Writes a string in Pascal short string format - 1 byte length, then string\r
887        itself without trailing #0 char. S parameter length should not exceed 255\r
888        chars, rest chars are truncated while writing. Total amount of bytes\r
889        written is returned. }\r
890     function ReadStrPas: String;\r
891     {* Reads 1 byte from a stream, then treat it as a length of following string\r
892        which is read and returned. A purpose of this function is reading strings\r
893        written using WriteStrPas. }\r
894     property Size: DWord read GetSize write SetSize;\r
895     {* Returns stream size. For some custom streams, can be slow\r
896        operation, or even always return undefined value (-1 recommended). }\r
897     property Position: DWord read GetPosition write SetPosition;\r
898     {* Current position. }\r
900     property Memory: Pointer read fMemory;\r
901     {* Only for memory stream. }\r
902     property Handle: THandle read GetFileStreamHandle;\r
903     {* Only for file stream. It is possible to check that Handle <>\r
904        INVALID_HANDLE_VALUE to ensure that file stream is created OK. }\r
906     //---------- for asynchronous operations (using thread - not tested):\r
907     procedure SeekAsync(MoveTo: Integer; MoveMethod: TMoveMethod);\r
908     {* Changes current position asynchronously. To wait for finishing the\r
909        operation, use method Wait. }\r
910     procedure ReadAsync(var Buffer; Count: DWord);\r
911     {* Reads Count bytes from a stream asynchronously. To wait finishing the\r
912        operation, use method Wait. }\r
913     procedure WriteAsync(var Buffer; Count: DWord);\r
914     {* Writes Count bytes from Buffer, starting from current position\r
915        in a stream - asynchronously. To wait finishing the operation,\r
916        use method Wait. }\r
917     function Busy: Boolean;\r
918     {* Returns TRUE until finishing the last asynchronous operation\r
919        started by calling SeekAsync, ReadAsync, WriteAsync methods. }\r
920     procedure Wait;\r
921     {* Waits for finishing the last asynchronous operation. }\r
923     property Methods: PStreamMethods read fPMethods;\r
924     {* Pointer to TStreamMethods record. Useful to implement custom-defined\r
925        streams, which can access its fCustom field, or even to change\r
926        methods when necessary. }\r
927     property Data: TStreamData read fData;\r
928     {* Pointer to TStreamData record. Useful to implement custom-defined\r
929     streams, which can access Data fields directly when implemented. }\r
931     property Capacity: DWORD read GetCapacity write SetCapacity;\r
932     {* Amound of memory allocated for data (MemoryStream). }\r
934   end;\r
935 //[END OF TStream DEFINITION]\r
937 //[_NewStream DECLARATION]\r
938 function _NewStream( const StreamMethods: TStreamMethods ): PStream;\r
939 {* Use this method only to define your own stream type. See also declared\r
940    below (in KOL.pas) methods used to implement standard KOL streams. You can use it in\r
941    your code to create streams, which are partially based on standard\r
942    methods. }\r
944 // Methods below are declared here to simplify creating your\r
945 // own streams with some methods standard and some non-standard\r
946 // together:\r
947 function SeekFileStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;\r
948 function GetSizeFileStream( Strm: PStream ): DWORD;\r
949 function ReadFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
950 function WriteFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
951 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
952 procedure CloseFileStream( Strm: PStream );\r
953 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;\r
954 function GetSizeMemStream( Strm: PStream ): DWORD;\r
955 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );\r
956 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
957 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
958 procedure CloseMemStream( Strm: PStream );\r
959 procedure SetSizeFileStream( Strm: PStream; NewSize: DWORD );\r
961 function DummyReadWrite( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
962 procedure DummySetSize( Strm: PStream; Value: DWORD );\r
963 procedure DummyStreamProc(Strm: PStream);\r
966 //[NewFileStream DECLARATION]\r
967 function NewFileStream( const FileName: String; Options: DWORD ): PStream;\r
968 {* Creates file stream for read and write. Exact set of open attributes\r
969    should be passed through Options parameter (see FileCreate where those\r
970    flags are listed). }\r
972 function NewReadFileStream( const FileName: String ): PStream;\r
973 {* Creates file stream for read only. }\r
975 function NewWriteFileStream( const FileName: String ): PStream;\r
976 {* Creates file stream for write only. Truncating of file (if needed)\r
977    is provided automatically. }\r
979 function NewReadWriteFileStream( const FileName: String ): PStream;\r
980 {* Creates stream for read and write file. To truncate file, if it is\r
981    necessary, change Size property. }\r
983 //[NewMemoryStream DECLARATION]\r
984 function NewMemoryStream: PStream;\r
985 {* Creates memory stream (read and write). }\r
987 function NewExMemoryStream( ExistingMem: Pointer; Size: DWORD ): PStream;\r
988 {* Creates memory stream on base of existing memory. It is not possible\r
989    to write out of top bound given by Size (i.e. memory can not be resized,\r
990    or reallocated. When stream object is destroyed this memory is not freed. }\r
992 //[Stream2Stream DECLARATION]\r
993 function Stream2Stream( Dst, Src: PStream; Count: DWORD ): DWORD;\r
994 {* Copies Count (or less, if the rest of Src is not sufficiently long)\r
995    bytes from Src to Dst, but with optimizing in cases, when Src or/and\r
996    Dst are memory streams (intermediate buffer is not allocated). }\r
997 function Stream2StreamEx( Dst, Src: PStream; Count: DWORD ): DWORD;\r
998 {* Copies Count bytes from Src to Dst, but without any optimization.\r
999    Unlike Stream2Stream function, it can be applied to very large streams.\r
1000    See also Stream2StreamExBufSz. }\r
1001 function Stream2StreamExBufSz( Dst, Src: PStream; Count, BufSz: DWORD ): DWORD;\r
1002 {* Copies Count bytes from Src to Dst using buffer of given size, but without\r
1003    other optimizations.\r
1004    Unlike Stream2Stream function, it can be applied to very large streams }\r
1006 //[Resource2Stream DECLARATION]\r
1007 function Resource2Stream( DestStrm : PStream; Inst : HInst;\r
1008                           ResName : PChar; ResType : PChar ): Integer;\r
1009 {* Loads given resource to DestStrm. Useful for non-standard\r
1010    resources to load it into memory (use memory stream for such\r
1011    purpose). Use one of following resource types to pass as ResType:\r
1012    |<pre>\r
1013 RT_ACCELERATOR  Accelerator table\r
1014 RT_ANICURSOR    Animated cursor\r
1015 RT_ANIICON      Animated icon\r
1016 RT_BITMAP       Bitmap resource\r
1017 RT_CURSOR       Hardware-dependent cursor resource\r
1018 RT_DIALOG       Dialog box\r
1019 RT_FONT         Font resource\r
1020 RT_FONTDIR      Font directory resource\r
1021 RT_GROUP_CURSOR Hardware-independent cursor resource\r
1022 RT_GROUP_ICON   Hardware-independent icon resource\r
1023 RT_ICON         Hardware-dependent icon resource\r
1024 RT_MENU         Menu resource\r
1025 RT_MESSAGETABLE Message-table entry\r
1026 RT_RCDATA       Application-defined resource (raw data)\r
1027 RT_STRING       String-table entry\r
1028 RT_VERSION      Version resource\r
1029    |</pre>\r
1030    |<br>For example:\r
1031    !var MemStrm: PStream;\r
1032    !    JpgObj: PJpeg;\r
1033    !......\r
1034    ! MemStrm := NewMemoryStream;\r
1035    ! JpgObj := NewJpeg;\r
1036    !......\r
1037    ! Resource2Stream( MemStrm, hInstance, 'MYJPEG', RT_RCDATA );\r
1038    ! MemStrm.Position := 0;\r
1039    ! JpgObj.LoadFromStream( MemStrm );\r
1040    ! MemStrm.Free;\r
1041    !......\r
1042    }\r
1067 type\r
1068 //[TBits DEFINITION]\r
1069   {++}(*TBits = class;*){--}\r
1070   PBits = {-}^{+}TBits;\r
1071   TBits = object( TObj )\r
1072   {* Variable-length bits array object. Created using function NewBits. See also\r
1073      |<a href="kol_pas.htm#Small bit arrays (max 32 bits in array)">\r
1074      Small bit arrays (max 32 bits in array)\r
1075      |</a>. }\r
1076   protected\r
1077     fList: PList;\r
1078     fCount: Integer;\r
1079     function GetBit(Idx: Integer): Boolean;\r
1080     function GetCapacity: Integer;\r
1081     function GetSize: Integer;\r
1082     procedure SetBit(Idx: Integer; const Value: Boolean);\r
1083     procedure SetCapacity(const Value: Integer);\r
1084   public\r
1085     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
1086     {* }\r
1087     property Bits[ Idx: Integer ]: Boolean read GetBit write SetBit;\r
1088     {* }\r
1089     property Size: Integer read GetSize;\r
1090     {* Size in bytes of the array. To get know number of bits, use property Count. }\r
1091     property Count: Integer read fCount;\r
1092     {* Number of bits an the array. }\r
1093     property Capacity: Integer read GetCapacity write SetCapacity;\r
1094     {* Number of bytes allocated. Can be set before assigning bit values\r
1095        to improve performance (minimizing amount of memory allocation\r
1096        operations).  }\r
1097     function Copy( From, BitsCount: Integer ): PBits;\r
1098     {* Use this property to get a sub-range of bits starting from given bit\r
1099        and of BitsCount bits count. }\r
1100     function IndexOf( Value: Boolean ): Integer;\r
1101     {* Returns index of first bit with given value (True or False). }\r
1102     function OpenBit: Integer;\r
1103     {* Returns index of the first bit not set to true. }\r
1104     procedure Clear;\r
1105     {* Clears bits array. Count, Size and Capacity become 0. }\r
1106     function LoadFromStream( strm: PStream ): Integer;\r
1107     {* Loads bits from the stream. Data should be stored in the stream\r
1108        earlier using SaveToStream method. While loading, previous bits\r
1109        data are discarded and replaced with new one totally. In part,\r
1110        Count of bits also is changed. Count of bytes read from the stream\r
1111        while loading data is returned. }\r
1112     function SaveToStream( strm: PStream ): Integer;\r
1113     {* Saves entire array of bits to the stream. First, Count of bits\r
1114        in the array is saved, then all bytes containing bits data. }\r
1115     function Range( Idx, N: Integer ): PBits;\r
1116     {* Creates and returns new TBits object instance containing N bits\r
1117        starting from index Idx. If you call this method, you are responsible\r
1118        for destroying returned object when it become not neccessary. }\r
1119     procedure AssignBits( ToIdx: Integer; FromBits: PBits; FromIdx, N: Integer );\r
1120     {* Assigns bits from another bits array object. N bits are assigned\r
1121        starting at index ToIdx. }\r
1122   end;\r
1123 //[END OF TBits DEFINITION]\r
1125 //[NewBits DECLARATION]\r
1126 function NewBits: PBits;\r
1127 {* Creates variable-length bits array object. }\r
1147 { -- string list objects -- }\r
1148 //[TStrList]\r
1150 type\r
1151   {++}(*TStrList = class;*){--}\r
1152   PStrList = {-}^{+}TStrList;\r
1153 { ---------------------------------------------------------------------\r
1155                 TStrList - string list\r
1157 ---------------------------------------------------------------------- }\r
1158 //[TStrList DEFINITION]\r
1159   TStrList = object(TObj)\r
1160   {* Easy string list implementation (non-visual, just to store\r
1161      string data). It is well improved and has very high performance\r
1162      allowing to work fast with huge text files (more then megabyte\r
1163      of text data).\r
1164      |\r
1165      Please note that #0 charaster if stored in string lines, will cut it\r
1166      preventing reading the rest of a line. Be careful, if your data\r
1167      contain such characters. }\r
1168   protected\r
1169     procedure Init; virtual;\r
1170   protected\r
1171     fList: PList;\r
1172     fCount: Integer;\r
1173     fCaseSensitiveSort: Boolean;\r
1174     fTextBuf: PChar;\r
1175     fTextSiz: DWORD;\r
1176     function GetPChars(Idx: Integer): PChar;\r
1177     //procedure AddTextBuf( Src: PChar; Len: DWORD );\r
1178   protected\r
1179     function Get(Idx: integer): string;\r
1180     function GetTextStr: string;\r
1181     procedure Put(Idx: integer; const Value: string);\r
1182     procedure SetTextStr(const Value: string);\r
1183   {++}(*public*){--}\r
1184     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
1185   protected\r
1186     // by Dod:\r
1187     procedure SetValue(const Name, Value: string);\r
1188     function GetValue(const Name: string): string;\r
1189   public\r
1190     // by Dod:\r
1191     function IndexOfName(Name: string): Integer;\r
1192     {* by Dod. Returns index of line starting like Name=... }\r
1193     property Values[const Name: string]: string read GetValue write SetValue;\r
1194     {* by Dod. Returns right side of a line starting like Name=... }\r
1195   public\r
1196     function Add(const S: string): integer;\r
1197     {* Adds a string to list. }\r
1198     procedure AddStrings(Strings: PStrList);\r
1199     {* Merges string list with given one. Very fast - more preferrable to\r
1200        use than any loop with calling Add method. }\r
1201     procedure Assign(Strings: PStrList);\r
1202     {* Fills string list with strings from other one. The same as AddStrings,\r
1203        but Clear is called first. }\r
1204     procedure Clear;\r
1205     {* Makes string list empty. }\r
1206     procedure Delete(Idx: integer);\r
1207     {* Deletes string with given index (it *must* exist). }\r
1208     function IndexOf(const S: string): integer;\r
1209     {* Returns index of first string, equal to given one. }\r
1210     function IndexOf_NoCase(const S: string): integer;\r
1211     {* Returns index of first string, equal to given one (while comparing it\r
1212        without case sensitivity). }\r
1213     function IndexOfStrL_NoCase( Str: PChar; L: Integer ): integer;\r
1214     {* Returns index of first string, equal to given one (while comparing it\r
1215        without case sensitivity). }\r
1216     function Find(const S: String; var Index: Integer): Boolean;\r
1217     {* Returns Index of the first string, equal or greater to given pattern, but\r
1218        works only for sorted TStrList object. Returns TRUE if exact string found,\r
1219        otherwise nearest (greater then a pattern) string index is returned,\r
1220        and the result is FALSE. }\r
1221     procedure Insert(Idx: integer; const S: string);\r
1222     {* Inserts string before one with given index. }\r
1223     function LoadFromFile(const FileName: string): Boolean;\r
1224     {* Loads string list from a file. (If file does not exist, nothing\r
1225        happens). Very fast even for huge text files. }\r
1226     procedure LoadFromStream(Stream: PStream; Append2List: boolean);\r
1227     {* Loads string list from a stream (from current position to the end of\r
1228        a stream). Very fast even for huge text. }\r
1229     procedure MergeFromFile(const FileName: string);\r
1230     {* Merges string list with strings in a file. Fast. }\r
1231     procedure Move(CurIndex, NewIndex: integer);\r
1232     {* Moves string to another location. }\r
1233     procedure SetText(const S: string; Append2List: boolean);\r
1234     {* Allows to set strings of string list from given string (in which\r
1235        strings are separated by $0D,$0A or $0D characters). Text must not\r
1236        contain #0 characters. Works very fast. This method is used in\r
1237        all others, working with text arrays (LoadFromFile, MergeFromFile,\r
1238        Assign, AddStrings). }\r
1239     procedure SetUnixText( const S: String; Append2List: Boolean );\r
1240     {* Allows to assign UNIX-style text (with #10 as string separator). }\r
1241     function SaveToFile(const FileName: string): Boolean;\r
1242     {* Stores string list to a file. }\r
1243     procedure SaveToStream(Stream: PStream);\r
1244     {* Saves string list to a stream (from current position). }\r
1245     function AppendToFile(const FileName: string): Boolean;\r
1246     {* Appends strings of string list to the end of a file. }\r
1247     property Count: integer read fCount;\r
1248     {* Number of strings in a string list. }\r
1249     property Items[Idx: integer]: string read Get write Put; default;\r
1250     {* Strings array items. If item does not exist, empty string is returned.\r
1251        But for assign to property, string with given index *must* exist. }\r
1252     property ItemPtrs[ Idx: Integer ]: PChar read GetPChars;\r
1253     {* Fast access to item strings as PChars. }\r
1254     function Last: String;\r
1255     {* Last item (or '', if string list is empty). }\r
1256     property Text: string read GetTextStr write SetTextStr;\r
1257     {* Content of string list as a single string (where strings are separated\r
1258        by characters $0D,$0A). }\r
1259     procedure Swap( Idx1, Idx2 : Integer );\r
1260     {* Swaps to strings with given indeces. }\r
1261     procedure Sort( CaseSensitive: Boolean );\r
1262     {* Call it to sort string list. }\r
1263     procedure AnsiSort( CaseSensitive: Boolean );\r
1264     {* Call it to sort ANSI string list. }\r
1266     // by Alexander Pravdin:\r
1267   protected\r
1268     fNameDelim: Char;\r
1269     function GetLineName( Idx: Integer ): string;\r
1270     procedure SetLineName( Idx: Integer; const NV: string );\r
1271     function GetLineValue(Idx: Integer): string;\r
1272     procedure SetLineValue(Idx: Integer; const Value: string);\r
1273   public\r
1274     property LineName[ Idx: Integer ]: string read GetLineName write SetLineName;\r
1275     property LineValue[ Idx: Integer ]: string read GetLineValue write SetLineValue;\r
1276     property NameDelimiter: Char read fNameDelim write fNameDelim;\r
1277   end;\r
1278 //[END OF TStrList DEFINITION]\r
1280 //[DefaultNameDelimiter]\r
1281 var DefaultNameDelimiter: Char = '=';\r
1283 //[NewStrList DECLARATION]\r
1284 function NewStrList: PStrList;\r
1285 {* Creates string list object. }\r
1287 function  GetFileList(const dir: string): PStrList;\r
1288 {* By Alexander Shakhaylo. Returns list of file names of the given directory. }\r
1293 //[TStrListEx]\r
1294 type\r
1295   {++}(*TStrListEx = class;*){--}\r
1296   PStrListEx = {-}^{+}TStrListEx;\r
1298 //[TStrListEx DEFINITION]\r
1299   TStrListEx = object( TStrList )\r
1300   {* Extended string list object. Has additional capability to associate\r
1301      numbers or objects with string list items. }\r
1302   protected\r
1303     FObjects: PList;\r
1304     function GetObjects(Idx: Integer): DWORD;\r
1305     procedure SetObjects(Idx: Integer; const Value: DWORD);\r
1306     procedure Init; {-}virtual;{+}{++}(*override;*){--}\r
1307     procedure ProvideObjCapacity( NewCap: Integer );\r
1308   public\r
1309     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
1310     {* }\r
1311     property Objects[ Idx: Integer ]: DWORD read GetObjects write SetObjects;\r
1312     {* Objects are just 32-bit values. You can treat and use it as pointers to\r
1313        any other data in the memory. But it is your task to free allocated\r
1314        memory in such case therefore. }\r
1315     procedure AddStrings(Strings: PStrListEx);\r
1316     {* Merges string list with given one. Very fast - more preferrable to\r
1317        use than any loop with calling Add method. }\r
1318     procedure Assign(Strings: PStrListEx);\r
1319     {* Fills string list with strings from other one. The same as AddStrings,\r
1320        but Clear is called first. }\r
1321     procedure Clear;\r
1322     {* Makes string list empty. }\r
1323     procedure Delete(Idx: integer);\r
1324     {* Deletes string with given index (it *must* exist). }\r
1325     procedure Move(CurIndex, NewIndex: integer);\r
1326     {* Moves string to another location. }\r
1327     procedure Swap( Idx1, Idx2 : Integer );\r
1328     {* Swaps to strings with given indeces. }\r
1329     procedure Sort( CaseSensitive: Boolean );\r
1330     {* Call it to sort string list. }\r
1331     procedure AnsiSort( CaseSensitive: Boolean );\r
1332     {* Call it to sort ANSI string list. }\r
1333     function LastObj: DWORD;\r
1334     {* Object assotiated with the last string. }\r
1335     function AddObject( const S: String; Obj: DWORD ): Integer;\r
1336     {* Adds a string and associates given number with it. Index of the item added\r
1337        is returned. }\r
1338     procedure InsertObject( Before: Integer; const S: String; Obj: DWORD );\r
1339     {* Inserts a string together with object associated. }\r
1340     function IndexOfObj( Obj: Pointer ): Integer;\r
1341     {* Returns an index of a string associated with the object passed as a\r
1342        parameter. If there are no such strings, -1 is returned. }\r
1343   end;\r
1344 //[END OF TStrListEx DEFINITION]\r
1346 //[NewStrListEx DECLARATION]\r
1347 function NewStrListEx: PStrListEx;\r
1348 {* Creates extended string list object. }\r
1354 //[TWStrList]\r
1356 {-}\r
1357 {$IFNDEF _D2} //------------------ WideString is not supported in D2 -----------\r
1359 type\r
1360   PWStrList = ^TWstrList;\r
1361   {* }\r
1362 //[TWstrList DEFINITION]\r
1363   TWStrList = object( TObj )\r
1364   {* String list to store Unicode (null-terminated) strings. }\r
1365   protected\r
1366     function GetCount: Integer;\r
1367     function GetItems(Idx: Integer): WideString;\r
1368     procedure SetItems(Idx: Integer; const Value: WideString);\r
1369     function GetPtrs(Idx: Integer): PWideChar;\r
1370     function GetText: WideString;\r
1371   protected\r
1372     fList: PList;\r
1373     fText: PWideChar;\r
1374     fTextBufSz: Integer;\r
1375     fTmp1, fTmp2: WideString;\r
1376     procedure Init; virtual;\r
1377   public\r
1378     procedure SetText(const Value: WideString);\r
1379     {* See also TStrList.SetText }\r
1380     destructor Destroy; virtual;\r
1381     {* }\r
1382     procedure Clear;\r
1383     {* See also TStrList.Clear }\r
1384     property Items[ Idx: Integer ]: WideString read GetItems write SetItems;\r
1385     {* See also TStrList.Items }\r
1386     property ItemPtrs[ Idx: Integer ]: PWideChar read GetPtrs;\r
1387     {* See also TStrList.ItemPtrs }\r
1388     property Count: Integer read GetCount;\r
1389     {* See also TStrList.Count }\r
1390     function Add( const W: WideString ): Integer;\r
1391     {* See also TStrList.Add }\r
1392     procedure Insert( Idx: Integer; const W: WideString );\r
1393     {* See also TStrList.Insert }\r
1394     procedure Delete( Idx: Integer );\r
1395     {* See also TStrList.Delete }\r
1396     property Text: WideString read GetText write SetText;\r
1397     {* See also TStrList.Text }\r
1398     procedure AddWStrings( WL: PWStrList );\r
1399     {* See also TStrList.AddStrings }\r
1400     procedure Assign( WL: PWStrList );\r
1401     {* See also TStrList.Assign }\r
1402     function LoadFromFile( const Filename: String ): Boolean;\r
1403     {* See also TStrList.LoadFromFile }\r
1404     procedure LoadFromStream( Strm: PStream );\r
1405     {* See also TStrList.LoadFromStream }\r
1406     function MergeFromFile( const Filename: String ): Boolean;\r
1407     {* See also TStrList.MergeFromFile }\r
1408     procedure MergeFromStream( Strm: PStream );\r
1409     {* See also TStrList.MergeFromStream }\r
1410     function SaveToFile( const Filename: String ): Boolean;\r
1411     {* See also TStrList.SaveToFile }\r
1412     procedure SaveToStream( Strm: PStream );\r
1413     {* See also TStrList.SaveToStream }\r
1414     function AppendToFile( const Filename: String ): Boolean;\r
1415     {* See also TStrList.AppendToFile }\r
1416     procedure Swap( Idx1, Idx2: Integer );\r
1417     {* See also TStrList.Swap }\r
1418     procedure Sort( CaseSensitive: Boolean );\r
1419     {* See also TStrList.Sort }\r
1420     procedure Move( IdxOld, IdxNew: Integer );\r
1421     {* See also TStrList.Move }\r
1422   end;\r
1423 //[END OF TWStrList DEFINITION]\r
1425 //[TWStrListEx]\r
1426   PWStrListEx = ^TWStrListEx;\r
1428 //[TWStrListEx DEFINITION]\r
1429   TWStrListEx = object( TWStrList )\r
1430   {* Extended Unicode string list (with Objects). }\r
1431   protected\r
1432     function GetObjects(Idx: Integer): DWORD;\r
1433     procedure SetObjects(Idx: Integer; const Value: DWORD);\r
1434     procedure ProvideObjectsCapacity( NewCap: Integer );\r
1435   protected\r
1436     fObjects: PList;\r
1437     procedure Init; virtual;\r
1438   public\r
1439     destructor Destroy; virtual;\r
1440     {* }\r
1441     property Objects[ Idx: Integer ]: DWORD read GetObjects write SetObjects;\r
1442     {* }\r
1443     procedure AddWStrings( WL: PWStrListEx );\r
1444     {* }\r
1445     procedure Assign( WL: PWStrListEx );\r
1446     {* }\r
1447     procedure Clear;\r
1448     {* }\r
1449     procedure Delete( Idx: Integer );\r
1450     {* }\r
1451     procedure Move( IdxOld, IdxNew: Integer );\r
1452     {* }\r
1453     function AddObject( const S: WideString; Obj: DWORD ): Integer;\r
1454     {* Adds a string and associates given number with it. Index of the item added\r
1455        is returned. }\r
1456     procedure InsertObject( Before: Integer; const S: WideString; Obj: DWORD );\r
1457     {* Inserts a string together with object associated. }\r
1458     function IndexOfObj( Obj: Pointer ): Integer;\r
1459     {* Returns an index of a string associated with the object passed as a\r
1460        parameter. If there are no such strings, -1 is returned. }\r
1461   end;\r
1462 //[END OF TWStrListEx DEFINITION]\r
1464 //[NewWStrList DECLARATION]\r
1465 function NewWStrList: PWStrList;\r
1466 {* Creates new TWStrList object and returns a pointer to it. }\r
1468 //[NewWStrListEx DECLARATION]\r
1469 function NewWStrListEx: PWStrListEx;\r
1470 {* Creates new TWStrListEx objects and returns a pointer to it. }\r
1472 {$ENDIF}\r
1489 {+}\r
1490 ////////////////////////////////////////////////////////////////////////////////\r
1491 //                            GRAPHIC OBJECTS                                 //\r
1492 ////////////////////////////////////////////////////////////////////////////////\r
1493 //[GRAPHIC OBJECTS]\r
1495   It is very important, that the most of code, implementing graphic objets\r
1496   from this section, is included into executable ONLY if really accessed in your\r
1497   project directly (e.g., if Font or Brush properies of a control are accessed\r
1498   or changed).\r
1500 type\r
1501   TColor = Integer;\r
1503 const\r
1504 //[COLOR CONSTANTS]\r
1505   clScrollBar = TColor(COLOR_SCROLLBAR or $80000000);\r
1506   clBackground = TColor(COLOR_BACKGROUND or $80000000);\r
1507   clActiveCaption = TColor(COLOR_ACTIVECAPTION or $80000000);\r
1508   clInactiveCaption = TColor(COLOR_INACTIVECAPTION or $80000000);\r
1509   clMenu = TColor(COLOR_MENU or $80000000);\r
1510   clWindow = TColor(COLOR_WINDOW or $80000000);\r
1511   clWindowFrame = TColor(COLOR_WINDOWFRAME or $80000000);\r
1512   clMenuText = TColor(COLOR_MENUTEXT or $80000000);\r
1513   clWindowText = TColor(COLOR_WINDOWTEXT or $80000000);\r
1514   clCaptionText = TColor(COLOR_CAPTIONTEXT or $80000000);\r
1515   clActiveBorder = TColor(COLOR_ACTIVEBORDER or $80000000);\r
1516   clInactiveBorder = TColor(COLOR_INACTIVEBORDER or $80000000);\r
1517   clAppWorkSpace = TColor(COLOR_APPWORKSPACE or $80000000);\r
1518   clHighlight = TColor(COLOR_HIGHLIGHT or $80000000);\r
1519   clHighlightText = TColor(COLOR_HIGHLIGHTTEXT or $80000000);\r
1520   clBtnFace = TColor(COLOR_BTNFACE or $80000000);\r
1521   clBtnShadow = TColor(COLOR_BTNSHADOW or $80000000);\r
1522   clGrayText = TColor(COLOR_GRAYTEXT or $80000000);\r
1523   clBtnText = TColor(COLOR_BTNTEXT or $80000000);\r
1524   clInactiveCaptionText = TColor(COLOR_INACTIVECAPTIONTEXT or $80000000);\r
1525   clBtnHighlight = TColor(COLOR_BTNHIGHLIGHT or $80000000);\r
1526   cl3DDkShadow = TColor(COLOR_3DDKSHADOW or $80000000);\r
1527   cl3DLight = TColor(COLOR_3DLIGHT or $80000000);\r
1528   clInfoText = TColor(COLOR_INFOTEXT or $80000000);\r
1529   clInfoBk = TColor(COLOR_INFOBK or $80000000);\r
1531   clBlack = TColor($000000);\r
1532   clMaroon = TColor($000080);\r
1533   clGreen = TColor($008000);\r
1534   clOlive = TColor($008080);\r
1535   clNavy = TColor($800000);\r
1536   clPurple = TColor($800080);\r
1537   clTeal = TColor($808000);\r
1538   clGray = TColor($808080);\r
1539   clSilver = TColor($C0C0C0);\r
1540   clRed = TColor($0000FF);\r
1541   clLime = TColor($00FF00);\r
1542   clYellow = TColor($00FFFF);\r
1543   clBlue = TColor($FF0000);\r
1544   clFuchsia = TColor($FF00FF);\r
1545   clAqua = TColor($FFFF00);\r
1546   clLtGray = TColor($C0C0C0);\r
1547   clDkGray = TColor($808080);\r
1548   clWhite = TColor($FFFFFF);\r
1549   clNone = TColor($1FFFFFFF);\r
1550   clDefault = TColor($20000000);\r
1552   clMoneyGreen = TColor($C0DCC0);\r
1553   clSkyBlue = TColor($F0CAA6);\r
1554   clCream = TColor($F0FBFF);\r
1555   clMedGray = TColor($A4A0A0);\r
1556 //[END OF COLOR CONSTANTS]\r
1558 const\r
1559 //[TGraphicTool FIELD OFFSET CONSTANTS]\r
1560   go_Color                 = 0;\r
1561   go_FontHeight            = 4;\r
1562   go_FontWidth             = 8;\r
1563   go_FontEscapement        = 12;\r
1564   go_FontOrientation       = 16;\r
1565   go_FontWeight            = 20;\r
1566   go_FontItalic            = 24;\r
1567   go_FontUnderline         = 25;\r
1568   go_FontStrikeOut         = 26;\r
1569   go_FontCharSet           = 27;\r
1570   go_FontOutPrecision      = 28;\r
1571   go_FontClipPrecision     = 29;\r
1572   go_FontQuality           = 30;\r
1573   go_FontPitch             = 31;\r
1574   go_FontName              = 32;\r
1575   go_BrushBitmap           = 4;\r
1576   go_BrushStyle            = 8;\r
1577   go_BrushLineColor        = 9;\r
1578   go_PenBrushBitmap        = 4;\r
1579   go_PenBrushStyle         = 8;\r
1580   go_PenStyle              = 9;\r
1581   go_PenWidth              = 10;\r
1582   go_PenMode               = 14;\r
1583   go_PenGeometric          = 15;\r
1584   go_PenEndCap             = 16;\r
1585   go_PenJoin               = 17;\r
1586 //[END OF TGraphicTool FIELD OFFSET CONSTANTS]\r
1588 //[TGraphicTool]\r
1589 type\r
1590    TGraphicToolType = ( gttBrush, gttFont, gttPen );\r
1591    {* Graphic object types, mainly for internal use. }\r
1593    {++}(*TGraphicTool = class;*){--}\r
1594    PGraphicTool = {-}^{+}TGraphicTool;\r
1595    {* }\r
1596    TOnGraphicChange = procedure ( Sender: PGraphicTool ) of object;\r
1597    {* An event mainly for internal use. }\r
1599    TBrushStyle = (bsSolid, bsClear, bsHorizontal, bsVertical,\r
1600     bsFDiagonal, bsBDiagonal, bsCross, bsDiagCross);\r
1601    {* Available brush styles. }\r
1603    TFontStyles = (fsBold, fsItalic, fsUnderline, fsStrikeOut);\r
1604    {* Available font styles. }\r
1605    TFontStyle = set of TFontStyles;\r
1606    {* Font style is representing as a set of XFontStyles. }\r
1607    TFontPitch = (fpDefault, fpFixed, fpVariable);\r
1608    {* Availabe font pitch values. }\r
1609    TFontName = type string;\r
1610    {* Font name is represented as a string. }\r
1611    TFontCharset = 0..255;\r
1612    {* Font charset is represented by number from 0 to 255. }\r
1613    TFontQuality = (fqDefault, fqDraft, fqProof, fqNonAntialiased, fqAntialiased);\r
1614    {* Font quality. }\r
1616    TPenStyle = (psSolid, psDash, psDot, psDashDot, psDashDotDot, psClear,\r
1617     psInsideFrame);\r
1618    {* Available pen styles. For more info see Delphi or Win32 help files. }\r
1619    TPenMode = (pmBlack, pmNotMerge, pmMaskNotPen, pmNotCopy, pmMaskPenNot,\r
1620                pmNot, pmXor, pmNotMask, pmMask, pmNotXor, pmNop, pmMergePenNot,\r
1621                pmCopy, pmMergeNotPen, pmMerge, pmWhite);\r
1622    {* Available pen modes. For more info see Delphi or Win32 help files. }\r
1623    TPenEndCap = (pecRound, pecSquare, pecFlat);\r
1624    {* Avalable (for geometric pen) end cap styles. }\r
1625    TPenJoin = (pjRound, pjBevel, pjMiter);\r
1626    {* Available (for geometric pen) join styles. }\r
1628 //[TGdiFont]\r
1629    TGDIFont = packed record\r
1630      Height: Integer;\r
1631      Width: Integer;\r
1632      Escapement: Integer;\r
1633      Orientation: Integer;\r
1634      Weight: Integer;\r
1635      Italic: Boolean;\r
1636      Underline: Boolean;\r
1637      StrikeOut: Boolean;\r
1638      CharSet: TFontCharset;\r
1639      OutPrecision: Byte;\r
1640      ClipPrecision: Byte;\r
1641      Quality: TFontQuality;\r
1642      Pitch: TFontPitch;\r
1643      Name: array[0..LF_FACESIZE - 1] of Char;\r
1644    end;\r
1646 //[TGDIBrush]\r
1647    TGDIBrush = packed record\r
1648      Bitmap: HBitmap;\r
1649      Style: TBrushStyle;\r
1650      LineColor: TColor;\r
1651    end;\r
1653 //[TGDIPen]\r
1654    TGDIPen = packed record\r
1655      BrushBitmap: HBitmap;\r
1656      BrushStyle: TBrushStyle;\r
1657      Style: TPenStyle;\r
1658      Width: Integer;\r
1659      Mode: TPenMode;\r
1660      Geometric: Boolean;\r
1661      EndCap: TPenEndCap;\r
1662      Join: TPenJoin;\r
1663    end;\r
1665 //[TGDIToolData]\r
1666    TGDIToolData = packed record\r
1667      Color: TColor;\r
1668      case Integer of\r
1669      1: (Font: TGDIFont);\r
1670      2: (Pen: TGDIPen);\r
1671      3: (Brush: TGDIBrush);\r
1672    end;\r
1674 //[TNewGraphicTool]\r
1675    TNewGraphicTool = function: PGraphicTool;\r
1677 { ---------------------------------------------------------------------\r
1679      TGraphicTool - object to implement GDI-tools (brush, pen, font)\r
1681 ---------------------------------------------------------------------- }\r
1682 //[TGraphicTool DEFINITION]\r
1683   TGraphicTool = object( TObj )\r
1684   {* Incapsulates all GDI objects: Pen, Brush and Font. }\r
1685   protected\r
1686     fType: TGraphicToolType;\r
1687     fHandle: THandle;\r
1688     fParentGDITool: PGraphicTool;\r
1689     fOnChange: TOnGraphicChange;\r
1690     fColorRGB: TColor;\r
1691     fData: TGDIToolData;\r
1693     fNewProc: TNewGraphicTool;\r
1694     fMakeHandleProc: function( Self_: PGraphicTool ): THandle;\r
1696     procedure SetInt( const Index: Integer; Value: Integer );\r
1697     {$IFDEF F_P}\r
1698     function GetInt( const Index: Integer ): Integer;\r
1699     {$ENDIF}\r
1700     procedure SetColor( Value: TColor );\r
1701     procedure SetBrushBitmap(const Value: HBitmap);\r
1702     procedure SetBrushStyle(const Value: TBrushStyle);\r
1703     procedure SetFontCharset(const Value: TFontCharset);\r
1704     procedure SetFontQuality(const Value: TFontQuality);\r
1705     function GetFontName: String;\r
1706     procedure SetFontName(const Value: String);\r
1707     procedure SetFontOrientation(Value: Integer);\r
1708     procedure SetFontPitch(const Value: TFontPitch);\r
1709     function GetFontStyle: TFontStyle;\r
1710     procedure SetFontStyle(const Value: TFontStyle);\r
1711     procedure SetPenMode(const Value: TPenMode);\r
1712     procedure SetPenStyle(const Value: TPenStyle);\r
1713     procedure SetGeometricPen(const Value: Boolean);\r
1714     procedure SetPenEndCap(const Value: TPenEndCap);\r
1715     procedure SetPenJoin(const Value: TPenJoin);\r
1716     procedure SetFontWeight(const Value: Integer);\r
1717     procedure SetLogFontStruct(const Value: TLogFont);\r
1718     function GetLogFontStruct: TLogFont;\r
1719   protected\r
1720     procedure Changed;\r
1721     {* }\r
1722     function GetHandle: THandle;\r
1723     {* }\r
1724   public\r
1725     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
1726     {* }\r
1727     property Handle: THandle read GetHandle;\r
1728     {* Every time, when accessed, real GDI object is created (if it is\r
1729        not yet created). So, to prevent creating of the handle, use\r
1730        HandleAllocated instead of comparing Handle with value 0. }\r
1731     function HandleAllocated: Boolean;\r
1732     {* Returns True, if handle is allocated (i.e., if real GDI\r
1733        objet is created. }\r
1734     property OnChange: TOnGraphicChange read fOnChange write fOnChange;\r
1735     {* Called, when object is changed. }\r
1736     function ReleaseHandle: Integer;\r
1737     {* Returns Handle value (if allocated), releasing it from the\r
1738        object (so, it is no more knows about this handle and its\r
1739        HandleAllocated function returns False. }\r
1740     property Color: TColor {index go_Color} read fData.Color write SetColor;\r
1741     {* Color is the most common property for all Pen, Brush and\r
1742        Font objects, so it is placed in its common for all of them. }\r
1743     function Assign( Value: PGraphicTool ): PGraphicTool;\r
1744     {* Assigns properties of the same (only) type graphic object,\r
1745        excluding Handle. If assigning is really leading to change\r
1746        object, procedure Changed is called. }\r
1747     procedure AssignHandle( NewHandle: Integer );\r
1748     {* Assigns value to Handle property. }\r
1750     property BrushBitmap: HBitmap read fData.Brush.Bitmap write SetBrushBitmap;\r
1751     {* Brush bitmap. For more info about using brush bitmap,\r
1752        see Delphi or Win32 help files. }\r
1753     property BrushStyle: TBrushStyle read fData.Brush.Style write SetBrushStyle;\r
1754     {* Brush style. }\r
1755     property BrushLineColor: TColor index go_BrushLineColor\r
1756              {$IFDEF F_P}\r
1757              read GetInt\r
1758              {$ELSE DELPHI}\r
1759              read fData.Brush.LineColor\r
1760              {$ENDIF F_P/DELPHI}\r
1761              write SetInt;\r
1762     {* Brush line color, used to represent lines in hatched brush. Default value is clBlack. }\r
1764     property FontHeight: Integer index go_FontHeight\r
1765              {$IFDEF F_P}\r
1766              read GetInt\r
1767              {$ELSE DELPHI}\r
1768              read fData.Font.Height\r
1769              {$ENDIF F_P/DELPHI}\r
1770              write SetInt;\r
1771     {* Font height. Value 0 (default) seys to use system default value,\r
1772        negative values are to represent font height in "points", positive\r
1773        - in pixels. In XCL usually positive values (if not 0) are used to\r
1774        make appearance independent from different local settings. }\r
1775     property FontWidth: Integer index go_FontWidth\r
1776              {$IFDEF F_P}\r
1777              read GetInt\r
1778              {$ELSE DELPHI}\r
1779              read fData.Font.Width\r
1780              {$ENDIF F_P/DELPHI}\r
1781              write SetInt;\r
1782     {* Font width in logical units. If FontWidth = 0, then as it is said\r
1783        in Win32.hlp, "the aspect ratio of the device is matched against the\r
1784        digitization aspect ratio of the available fonts to find the closest match,\r
1785        determined by the absolute value of the difference." }\r
1786     property FontPitch: TFontPitch read fData.Font.Pitch write SetFontPitch;\r
1787     {* Font pitch. Change it very rare. }\r
1788     property FontStyle: TFontStyle read GetFontStyle write SetFontStyle;\r
1789     {* Very useful property to control text appearance. }\r
1790     property FontCharset: TFontCharset read fData.Font.Charset write SetFontCharset;\r
1791     {* Do not change it if You do not know what You do. }\r
1792     property FontQuality: TFontQuality read fData.Font.Quality write SetFontQuality;\r
1793     {* Font quality. }\r
1794     property FontOrientation: Integer read fData.Font.Orientation write SetFontOrientation;\r
1795     {* It is possible to rotate text in XCL just by changing this\r
1796        property of a font (tenths of degree, i.e. value 900 represents\r
1797        90 degree - text written from bottom to top). }\r
1798     property FontWeight: Integer read fData.Font.Weight write SetFontWeight;\r
1799     {* Additional font weight for bold fonts (must be 0..1000). When set to\r
1800        value <> 0, fsBold is added to FontStyle. And otherwise, when set to 0,\r
1801        fsBold is removed from FontStyle. Value 700 corresponds to Bold,\r
1802        400 to Normal. }\r
1803     property FontName: String read GetFontName write SetFontName;\r
1804     {* Font face name. }\r
1805     function IsFontTrueType: Boolean;\r
1806     {* Returns True, if font is True Type. Requires of creating of a Handle,\r
1807        if it is not yet created. }\r
1809     property PenWidth: Integer index go_PenWidth\r
1810              {$IFDEF F_P}\r
1811              read GetInt\r
1812              {$ELSE DELPHI}\r
1813              read fData.Pen.Width\r
1814              {$ENDIF F_P/DELPHI}\r
1815              write SetInt;\r
1816     {* Value 0 means default pen width. }\r
1817     property PenStyle: TPenStyle read fData.Pen.Style write SetPenStyle;\r
1818     {* Pen style. }\r
1819     property PenMode: TPenMode read fData.Pen.Mode write SetPenMode;\r
1820     {* Pen mode. }\r
1822     property GeometricPen: Boolean read fData.Pen.Geometric write SetGeometricPen;\r
1823     {* True if Pen is geometric. Note, that under Win95/98 only pen styles\r
1824        psSolid, psNull, psInsideFrame are supported by OS. }\r
1825     property PenBrushStyle: TBrushStyle read fData.Pen.BrushStyle write SetBrushStyle;\r
1826     {* Brush style for hatched geometric pen. }\r
1827     property PenBrushBitmap: HBitmap read fData.Pen.BrushBitmap write SetBrushBitmap;\r
1828     {* Brush bitmap for geometric pen (if assigned Pen is functioning as\r
1829        its style = BS_PATTERN, regadless of PenBrushStyle value). }\r
1830     property PenEndCap: TPenEndCap read fData.Pen.EndCap write SetPenEndCap;\r
1831     {* Pen end cap mode - for GeometricPen only. }\r
1832     property PenJoin: TPenJoin read fData.Pen.Join write SetPenJoin;\r
1833     {* Pen join mode - for GeometricPen only. }\r
1834     property LogFontStruct: TLogFont read GetLogFontStruct write SetLogFontStruct;\r
1835     {* by Alex Pravdin: a property to change all font structure items at once. }\r
1836   end;\r
1837 //[END OF TGraphicTool DEFINITION]\r
1839 //[Color2XXX FUNCTIONS]\r
1840 function Color2RGB( Color: TColor ): TColor;\r
1841 {* Function to get RGB color from system color. Parameter can be also RGB\r
1842    color, in that case result is just equal to a parameter. }\r
1843 function ColorsMix( Color1, Color2: TColor ): TColor;\r
1844 {* Returns color, which RGB components are build as an (approximate)\r
1845    arithmetic mean of correspondent RGB components of both source\r
1846    colors (these both are first converted from system to RGB, and\r
1847    result is always RGB color). Please note: this function is fast,\r
1848    but can be not too exact. }\r
1849 function Color2RGBQuad( Color: TColor ): TRGBQuad;\r
1850 {* Converts color to RGB, used to represent RGB values in palette entries\r
1851    (actually swaps R and B bytes). }\r
1852 function Color2Color16( Color: TColor ): WORD;\r
1853 {* Converts Color to RGB, packed to word (as it is used in format pf16bit). }\r
1855 //[DefFont VARIABLE]\r
1856 var    // New TFont instances are intialized with the values in this structure:\r
1857   DefFont: TGDIFont = (\r
1858      Height: 0;\r
1859      Width: 0;\r
1860      Escapement: 0;\r
1861      Orientation: 0;\r
1862      Weight: 0;\r
1863      Italic: FALSE;\r
1864      Underline: FALSE;\r
1865      StrikeOut: FALSE;\r
1866      CharSet: 1;\r
1867      OutPrecision: 0;\r
1868      ClipPrecision: 0;\r
1869      Quality: fqDefault;\r
1870      Pitch: fpDefault;\r
1871      Name: 'MS Sans Serif';\r
1872   );\r
1873   DefFontColor: TColor = clWindowText;\r
1874   {* Default font color. }\r
1876 //[GlobalGraphics_UseFontOrient]\r
1877   GlobalGraphics_UseFontOrient: Boolean;\r
1878   {* Global flag. If stays False (default), Orientation property of Font\r
1879      objects is ignored. This flag is set to True automatically in\r
1880      RotateFonts add-on. }\r
1882 { -- Constructors for different GDI tools -- }\r
1884 //[New FUNCTIONS FOR TGraphicTool]\r
1885 function NewFont: PGraphicTool;\r
1886 {* Creates and returns font graphic tool object. }\r
1887 function NewBrush: PGraphicTool;\r
1888 {* Creates and returns new brush object. }\r
1889 function NewPen: PGraphicTool;\r
1890 {* Creates and returns new pen object. }\r
1905 { -- TCanvas object -- }\r
1906 //[TCanvas]\r
1907 const\r
1908   HandleValid = 1;\r
1909   PenValid    = 2;\r
1910   BrushValid  = 4;\r
1911   FontValid   = 8;\r
1912   ChangingCanvas = 16;\r
1914 type\r
1915    TFillStyle = (fsSurface, fsBorder);\r
1916    {* Available filling styles. For more info see Win32 or Delphi help files. }\r
1917    TFillMode = (fmAlternate, fmWinding);\r
1918    {* Available filling modes. For more info see Win32 or Delphi help files. }\r
1919    TCopyMode = Integer;\r
1920    {* Available copying modes are following:\r
1921       |  cmBlackness<br>\r
1922       |  cmDstInvert<br>\r
1923       |  cmMergeCopy<br>\r
1924       |  cmMergePaint<br>\r
1925       |  cmNotSrcCopy<br>\r
1926       |  cmNotSrcErase<br>\r
1927       |  cmPatCopy<br>\r
1928       |  cmPatInvert<br>\r
1929       |  cmPatPaint<br>\r
1930       |  cmSrcAnd<br>\r
1931       |  cmSrcCopy<br>\r
1932       |  cmSrcErase<br>\r
1933       |  cmSrcInvert<br>\r
1934       |  cmSrcPaint<br>\r
1935       |  cmWhiteness<br>&nbsp;&nbsp;&nbsp;\r
1936       Also it is possible to use any other available ROP2 modes. For more info,\r
1937       see Win32 help files. }\r
1939 const\r
1940   cmBlackness = BLACKNESS;\r
1941   cmDstInvert = DSTINVERT;\r
1942   cmMergeCopy = MERGECOPY;\r
1943   cmMergePaint = MERGEPAINT;\r
1944   cmNotSrcCopy = NOTSRCCOPY;\r
1945   cmNotSrcErase = NOTSRCERASE;\r
1946   cmPatCopy = PATCOPY;\r
1947   cmPatInvert = PATINVERT;\r
1948   cmPatPaint = PATPAINT;\r
1949   cmSrcAnd = SRCAND;\r
1950   cmSrcCopy = SRCCOPY;\r
1951   cmSrcErase = SRCERASE;\r
1952   cmSrcInvert = SRCINVERT;\r
1953   cmSrcPaint = SRCPAINT;\r
1954   cmWhiteness = WHITENESS;\r
1956 type\r
1957   {++}(*TCanvas = class;*){--}\r
1958   PCanvas = {-}^{+}TCanvas;\r
1959   {* }\r
1960   TOnGetHandle = function( Canvas: PCanvas ): HDC of object;\r
1961   {* For internal use mainly. }\r
1962   TOnTextArea = procedure( Sender: PCanvas; var Size : TSize; var P0 : TPoint );\r
1963   {* Event to calculate actual area, occupying by a text. It is used\r
1964      to optionally extend calculating of TextArea taking into considaration\r
1965      font Orientation property. }\r
1967 { ---------------------------------------------------------------------\r
1969                 TCanvas - high-level drawing helper object\r
1971 ----------------------------------------------------------------------- }\r
1972 //[TCanvas DEFINITION]\r
1973   TCanvas = object( TObj )\r
1974   {* Very similar to VCL's TCanvas object. But with some changes, specific\r
1975      for KOL: there is no necessary to use canvases in all applications.\r
1976      And graphic tools objects are not created with canvas, but only\r
1977      if really accessed in program. (Actually, even if paint box used,\r
1978      only programmer decides, if to implement painting using Canvas or\r
1979      to call low level API drawing functions working directly with DC).\r
1980      Therefore TCanvas has some powerful extensions: rotated text support,\r
1981      geometric pen support - just by changing correspondent properties\r
1982      of certain graphic tool objects (Font.FontOrientation, Pen.GeometricPen).\r
1983      See also additional Font properties (Font.FontWeight, Font.FontQuality,\r
1984      etc. }\r
1985   protected\r
1986     fOwnerControl: Pointer; //PControl;\r
1987     fHandle : HDC;\r
1988     fPenPos : TPoint;\r
1989     fBrush, fFont, fPen : PGraphicTool; // order is important for ASM version\r
1990     fState : Byte;\r
1991     fCopyMode : TCopyMode;\r
1992     fOnChange: TOnEvent;\r
1993     fOnGetHandle: TOnGetHandle;\r
1994     procedure SetHandle( Value : HDC );\r
1995     procedure SetPenPos( const Value : TPoint );\r
1996     procedure CreatePen;\r
1997     procedure CreateBrush;\r
1998     procedure CreateFont;\r
1999     procedure ObjectChanged( Sender : PGraphicTool );\r
2000     procedure Changing;\r
2001     function GetBrush: PGraphicTool;\r
2002     function GetFont: PGraphicTool;\r
2003     function GetPen: PGraphicTool;\r
2004     function GetHandle: HDC;\r
2005     procedure AssignChangeEvents;\r
2006     function GetPixels(X, Y: Integer): TColor;\r
2007     procedure SetPixels(X, Y: Integer; const Value: TColor);\r
2008   protected\r
2009     fIsPaintDC : Boolean;\r
2010     {* TRUE, if DC obtained during current WM_PAINT (or WM_ERASEBKGND?)\r
2011        processing for a control. This affects a way how Handle is released. }\r
2012   {++}(*public*){--}\r
2013     destructor Destroy;{-}virtual;{+}{++}(*override;*){--}\r
2014     {* }\r
2015   {++}(*protected*){--}\r
2016     property OnGetHandle: TOnGetHandle read fOnGetHandle write fOnGetHandle;\r
2017     {* For internal use only. }\r
2018   public\r
2019     property Handle : HDC read GetHandle write SetHandle;\r
2020     {* GDI device context object handle. Never created by\r
2021        Canvas itself (to use Canvas with memory bitmaps,\r
2022        always create DC by yourself and assign it to the\r
2023        Handle property of Canvas object, or use property\r
2024        Canvas of a bitmap). }\r
2025     property PenPos : TPoint read FPenPos write SetPenPos;\r
2026     {* Position of a pen. }\r
2027     property Pen : PGraphicTool read GetPen;\r
2028     {* Pen of Canvas object. Do not change its Pen.OnChange event value. }\r
2029     property Brush : PGraphicTool read GetBrush;\r
2030     {* Brush of Canvas object. Do not change its Brush.OnChange event value. }\r
2031     property Font : PGraphicTool read GetFont;\r
2032     {* Font of Canvas object. Do not change its Font.OnChange event value. }\r
2033     procedure Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;\r
2034     {* Draws arc. For more info, see Delphi TCanvas help. }\r
2035     procedure Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;\r
2036     {* Draws chord. For more info, see Delphi TCanvas help. }\r
2037     procedure DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);\r
2038     {* Draws rectangle to represent focused visual object.\r
2039        For more info, see Delphi TCanvas help. }\r
2040     procedure Ellipse(X1, Y1, X2, Y2: Integer);\r
2041     {* Draws an ellipse. For more info, see Delphi TCanvas help. }\r
2042     procedure FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);\r
2043     {* Fills rectangle. For more info, see Delphi TCanvas help. }\r
2044     procedure FillRgn( const Rgn : HRgn );\r
2045     {* Fills region. For more info, see Delphi TCanvas help. }\r
2046     procedure FloodFill(X, Y: Integer; Color: TColor; FillStyle: TFillStyle);\r
2047     {* Fills a figure with givien color, floodfilling its surface.\r
2048        For more info, see Delphi TCanvas help. }\r
2049     procedure FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);\r
2050     {* Draws a rectangle. For more info, see Delphi TCanvas help. }\r
2051     procedure MoveTo( X, Y : Integer );\r
2052     {* Moves current PenPos to a new position.\r
2053        For more info, see Delphi TCanvas help. }\r
2054     procedure LineTo( X, Y : Integer );\r
2055     {* Draws a line from current PenPos up to new position.\r
2056        For more info, see Delphi TCanvas help. }\r
2057     procedure Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;\r
2058     {* Draws a pie. For more info, see Delphi TCanvas help. }\r
2059     procedure Polygon(const Points: array of TPoint);\r
2060     {* Draws a polygon. For more info, see Delphi TCanvas help. }\r
2061     procedure Polyline(const Points: array of TPoint);\r
2062     {* Draws a bound for polygon. For more info, see Delphi TCanvas help. }\r
2063     procedure Rectangle(X1, Y1, X2, Y2: Integer);\r
2064     {* Draws a rectangle using current Pen and/or Brush.\r
2065        For more info, see Delphi TCanvas help. }\r
2066     procedure RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);\r
2067     {* Draws a rounded rectangle. For more info, see Delphi TCanvas help. }\r
2068     procedure TextOut(X, Y: Integer; const Text: String); stdcall;\r
2069     {* Draws a text. For more info, see Delphi TCanvas help. }\r
2070     procedure ExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect; const Text: String;\r
2071               const Spacing: array of Integer );\r
2072     {* }\r
2073     procedure DrawText(Text:String; var Rect:TRect; Flags:DWord);\r
2074     {* }\r
2075     procedure TextRect(const Rect: TRect; X, Y: Integer; const Text: string);\r
2076     {* Draws a text, clipping output into given rectangle.\r
2077        For more info, see Delphi TCanvas help. }\r
2078     function TextExtent(const Text: string): TSize;\r
2079     {* Calculates size of a Text, using current Font settings.\r
2080        Does not need in Handle for Canvas object (if it is not\r
2081        yet allocated, temporary device context is created and used. }\r
2082     procedure TextArea( const Text : String; var Sz : TSize; var P0 : TPoint );\r
2083     {* Calculates size and starting point to output Text,\r
2084        taking into considaration all Font attributes, including\r
2085        Orientation (only if GlobalGraphics_UseFontOrient flag\r
2086        is set to True, i.e. if rotated fonts are used).\r
2087        Like for TextExtent, does not need in Handle (and if this\r
2088        last is not yet allocated/assigned, temporary device context\r
2089        is created and used). }\r
2090     function TextWidth(const Text: string): Integer;\r
2091     {* Calculates text width (using TextArea). }\r
2092     function TextHeight(const Text: string): Integer;\r
2093     {* Calculates text height (using TextArea). }\r
2094     function ClipRect: TRect;\r
2095     {* returns ClipBox. by Dmitry Zharov. }\r
2097     {$IFNDEF _FPC}\r
2098     {$IFNDEF _D2} //------- WideString not supported in D2\r
2099     procedure WTextOut(X, Y: Integer; const WText: WideString); stdcall;\r
2100     {* Draws a Unicode text. }\r
2101     procedure WExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect;\r
2102               const WText: WideString; const Spacing: array of Integer );\r
2103     {* }\r
2104     procedure WDrawText(WText: WideString; var Rect:TRect; Flags:DWord);\r
2105     {* }\r
2106     procedure WTextRect(const Rect: TRect; X, Y: Integer;\r
2107               const WText: WideString);\r
2108     {* Draws a Unicode text, clipping output into given rectangle. }\r
2109     function WTextExtent( const WText: WideString ): TSize;\r
2110     {* Calculates Unicode text width and height. }\r
2111     function WTextWidth( const WText: WideString ): Integer;\r
2112     {* Calculates Unicode text width. }\r
2113     function WTextHeight( const WText: WideString ): Integer;\r
2114     {* Calculates Unicode text height. }\r
2115     {$ENDIF _D2}\r
2116     {$ENDIF _FPC}\r
2118     property ModeCopy : TCopyMode read fCopyMode write fCopyMode;\r
2119     {* Current copy mode. Is used in CopyRect method. }\r
2120     procedure CopyRect( const DstRect : TRect; SrcCanvas : PCanvas; const SrcRect : TRect );\r
2121     {* Copyes a rectangle from source to destination, using StretchBlt. }\r
2122     property OnChange: TOnEvent read fOnChange write fOnChange;\r
2123     {* }\r
2124     function Assign( SrcCanvas : PCanvas ) : Boolean;\r
2125     {* }\r
2126     function RequiredState( ReqState : DWORD ): Integer; stdcall;// public now\r
2127     {* It is possible to call this method before using Handle property\r
2128        to pass it into API calls - to provide valid combinations of\r
2129        pen, brush and font, selected into device context. This method\r
2130        can not provide valid Handle - You always must create it by\r
2131        yourself and assign to TCanvas.Handle property manually.\r
2132        To optimize assembler version, returns Handle value. }\r
2133     procedure DeselectHandles;\r
2134     {* Call this method to deselect all graphic tool objects from the canvas. }\r
2135     property Pixels[ X, Y: Integer ]: TColor read GetPixels write SetPixels;\r
2136     {* Obvious. }\r
2137   end;\r
2138 //[END OF TCanvas DEFINITION]\r
2140 //[GlobalCanvas_OnTextArea]\r
2141 var\r
2142     GlobalCanvas_OnTextArea : TOnTextArea;\r
2143     {* Global event to extend Canvas with possible add-ons, applied\r
2144        when rotated fonts are used only (to take into consideration\r
2145        Font.Orientation property in TextArea method). }\r
2147 //[NewCanvas DECLARATION]\r
2148 function NewCanvas( DC: HDC ): PCanvas;\r
2149 {* Use to construct Canvas on base of memory DC. }\r
2151 //[Extended FUNCTIONS TO WORK WITH CANVAS]\r
2152 {++}(*\r
2153 {$IFDEF F_P}\r
2154 function Windows_Polygon(DC: HDC; var Points; Count: Integer): BOOL; stdcall;\r
2155 function Windows_Polyline(DC: HDC; var Points; Count: Integer): BOOL; stdcall;\r
2156 function FillRect(hDC: HDC; const lprc: TRect; hbr: HBRUSH): Integer; stdcall;\r
2157 function OffsetRect(var lprc: TRect; dx, dy: Integer): BOOL; stdcall;\r
2158 function CreateAcceleratorTable(var Accel; Count: Integer): HACCEL; stdcall;\r
2159 function TrackPopupMenu(hMenu: HMENU; uFlags: UINT; x, y, nReserved: Integer;\r
2160   hWnd: HWND; prcRect: PRect): BOOL; stdcall;\r
2161 function AdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BOOL;\r
2162   const NewState: TTokenPrivileges; BufferLength: DWORD;\r
2163   var PreviousState: TTokenPrivileges; var ReturnLength: DWORD): BOOL; stdcall;\r
2164 function InflateRect(var lprc: TRect; dx, dy: Integer): BOOL; stdcall;\r
2165 {$IFDEF F_P105ORBELOW}\r
2166 function InvalidateRect(hWnd: HWND; lpRect: PRect; bErase: BOOL): BOOL; stdcall;\r
2167 function ValidateRect(hWnd: HWND; lpRect: PRect): BOOL; stdcall;\r
2168 {$ENDIF F_P105ORBELOW}\r
2169 {$ENDIF}\r
2170 *){--}\r
2185 { -- Image list object -- }\r
2186 //[IMAGE LIST]\r
2188 type\r
2189   TImageListColors = (ilcColor,ilcColor4,ilcColor8,ilcColor16,\r
2190                       ilcColor24,ilcColor32,ilcColorDDB,ilcDefault);\r
2191   {* ImageList color schemes available. }\r
2193   TDrawingStyles = ( dsBlend25, dsBlend50, dsMask, dsTransparent );\r
2194   {* ImageList drawing styles available. }\r
2195   TDrawingStyle = Set of TDrawingStyles;\r
2196   {* Style of drawing is a combination of all available drawing styles. }\r
2198   TImageType = (itBitmap,itIcon,itCursor);\r
2199   {* ImageList types available. }\r
2201   {++}(*TImageList = class;*){--}\r
2202   PImageList = {-}^{+}TImageList;\r
2203   {* }\r
2205   TImgLOVrlayIdx = 1..15;\r
2207 { ---------------------------------------------------------------------\r
2209                 TImageList - images container\r
2211 ----------------------------------------------------------------------- }\r
2212 //[TImageList DEFINITION]\r
2213   TImageList = object( TObj )\r
2214   {* ImageList incapsulation. }\r
2215   protected\r
2216     FHandle: THandle;\r
2217     FControl: Pointer; // PControl;\r
2218     fPrev, fNext: PImageList;\r
2219     FColors: TImageListColors;\r
2220     FMasked: Boolean;\r
2221     FImgWidth: Integer;\r
2222     FImgHeight: Integer;\r
2223     FDrawingStyle: TDrawingStyle;\r
2224     FBlendColor: TColor;\r
2225     fBkColor: TColor;\r
2226     FAllocBy: Integer;\r
2227     FShareImages: Boolean;\r
2228     FOverlay: array[ TImgLOVrlayIdx ] of Integer;\r
2229     function HandleNeeded : Boolean;\r
2230     procedure SetColors(const Value: TImageListColors);\r
2231     procedure SetMasked(const Value: Boolean);\r
2232     procedure SetImgWidth(const Value: Integer);\r
2233     procedure SetImgHeight(const Value: Integer);\r
2234     function GetCount: Integer;\r
2235     function GetBkColor: TColor;\r
2236     procedure SetBkColor(const Value: TColor);\r
2237     function GetBitmap: HBitmap;\r
2238     function GetMask: HBitmap;\r
2239     function GetDrawStyle : DWord;\r
2240     procedure SetAllocBy(const Value: Integer);\r
2241     function GetHandle: THandle;\r
2242     function GetOverlay(Idx: TImgLOVrlayIdx): Integer;\r
2243     procedure SetOverlay(Idx: TImgLOVrlayIdx; const Value: Integer);\r
2244   protected\r
2245     procedure SetHandle(const Value: THandle);\r
2246     {*}\r
2247   public\r
2248     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
2249     {*}\r
2250     property Handle : THandle read GetHandle write SetHandle;\r
2251     {* Handle of ImageList object. }\r
2252     property ShareImages : Boolean read FShareImages write FShareImages;\r
2253     {* True if images are shared between processes (it is set to True,\r
2254        if its Handle is assigned to given value, which is a handle of\r
2255        already existing ImageList object). }\r
2256     property Colors : TImageListColors read FColors write SetColors;\r
2257     {* Colors used to represent images. }\r
2258     property Masked : Boolean read FMasked write SetMasked;\r
2259     {* True, if mask is used. It is set to True, if first added image\r
2260        is icon, e.g. }\r
2261     property ImgWidth : Integer read FImgWidth write SetImgWidth;\r
2262     {* Width of every image in list. If change, ImageList is cleared. }\r
2263     property ImgHeight : Integer read FImgHeight write SetImgHeight;\r
2264     {* Height of every image in list. If change, ImageList is cleared. }\r
2265     property Count : Integer read GetCount;\r
2266     {* Number of images in list. }\r
2267     property AllocBy : Integer read FAllocBy write SetAllocBy;\r
2268     {* Allocation factor. Default is 1. Set it to size of ImageList if this\r
2269        value is known - to optimize speed of allocation. }\r
2270     property BkColor : TColor read GetBkColor write SetBkColor;\r
2271     {* Background color. }\r
2272     property BlendColor : TColor read FBlendColor write FBlendColor;\r
2273     {* Blend color. }\r
2275     property Bitmap : HBitmap read GetBitmap;\r
2276     {* Bitmap, containing all ImageList images (tiled horizontally). }\r
2277     property Mask : HBitmap read GetMask;\r
2278     {* Monochrome bitmap, containing masks for all images in list (if not\r
2279        Masked, always returns nil). }\r
2280     function ImgRect( Idx : Integer ) : TRect;\r
2281     {* Rectangle occupied of given image in ImageList. }\r
2283     function Add( Bmp, Msk : HBitmap ) : Integer;\r
2284     {* Adds bitmap and given mask to ImageList. }\r
2285     function AddMasked( Bmp : HBitmap; Color : TColor ) : Integer;\r
2286     {* Adds bitmap to ImageList, using given color to create mask. }\r
2287     function AddIcon( Ico : HIcon ) : Integer;\r
2288     {* Adds icon to ImageList (always masked). }\r
2289     procedure Delete( Idx : Integer );\r
2290     {* Deletes given image from ImageList. }\r
2291     procedure Clear;\r
2292     {* Makes ImageList empty. }\r
2293     function Replace( Idx : Integer; Bmp, Msk : HBitmap ) : Boolean;\r
2294     {* Replaces given (by index) image with bitmap and its mask with mask bitmap. }\r
2295     function ReplaceIcon( Idx : Integer; Ico : HIcon ) : Boolean;\r
2296     {* Replaces given (by index) image with an icon. }\r
2297     function Merge( Idx : Integer; ImgList2 : PImageList; Idx2 : Integer; X, Y : Integer )\r
2298              : PImageList;\r
2299     {* Merges two ImageList objects, returns resulting ImageList. }\r
2300     function ExtractIcon( Idx : Integer ) : HIcon;\r
2301     {* Extracts icon by index. }\r
2302     function ExtractIconEx( Idx : Integer ) : HIcon;\r
2303     {* Extracts icon (is created using current drawing style). }\r
2305     property DrawingStyle : TDrawingStyle read FDrawingStyle write FDrawingStyle;\r
2306     {* Drawing style. }\r
2307     procedure Draw( Idx : Integer; DC : HDC; X, Y : Integer );\r
2308     {* Draws given (by index) image from ImageList onto passed Device Context. }\r
2309     procedure StretchDraw( Idx : Integer; DC : HDC; const Rect : TRect );\r
2310     {* Draws given image with stratching. }\r
2312     function LoadBitmap( ResourceName : PChar; TranspColor : TColor ) : Boolean;\r
2313     {* Loads ImageList from resource. }\r
2314     //function LoadIcon( ResourceName : PChar ) : Boolean;\r
2315     //function LoadCursor( ResourceName : PChar ) : Boolean;\r
2316     function LoadFromFile( FileName : PChar; TranspColor : TColor; ImgType : TImageType ) : Boolean;\r
2317     {* Loads ImageList from file. }\r
2318     function LoadSystemIcons( SmallIcons : Boolean ) : Boolean;\r
2319     {* Assigns ImageList to system icons list (big or small). }\r
2321     property Overlay[ Idx: TImgLOVrlayIdx ]: Integer read GetOverlay write SetOverlay;\r
2322     {* Overlay images for image list (images, used as overlay images to draw over\r
2323        other images from the image list). These overalay images can be used in\r
2324        listview and treeview as overlaying images (up to four masks at the same\r
2325        time). }\r
2326     {$IFDEF USE_CONSTRUCTORS}\r
2327     constructor CreateImageList( POwner: Pointer );\r
2328     {$ENDIF USE_CONSTRUCTORS}\r
2329   end;\r
2330 //[END OF TImageList DEFINITION]\r
2332 //[IMAGE LIST API]\r
2334 const\r
2335   CLR_NONE                = $FFFFFFFF;\r
2336   CLR_DEFAULT             = $FF000000;\r
2338 type\r
2339   HImageList = THandle;\r
2341 const\r
2342   ILC_MASK                = $0001;\r
2343   ILC_COLOR               = $00FE;\r
2344   ILC_COLORDDB            = $00FE;\r
2345   ILC_COLOR4              = $0004;\r
2346   ILC_COLOR8              = $0008;\r
2347   ILC_COLOR16             = $0010;\r
2348   ILC_COLOR24             = $0018;\r
2349   ILC_COLOR32             = $0020;\r
2350   ILC_PALETTE             = $0800;\r
2352 const\r
2353   ILD_NORMAL              = $0000;\r
2354   ILD_TRANSPARENT         = $0001;\r
2355   ILD_MASK                = $0010;\r
2356   ILD_IMAGE               = $0020;\r
2357   ILD_BLEND25             = $0002;\r
2358   ILD_BLEND50             = $0004;\r
2359   ILD_OVERLAYMASK         = $0F00;\r
2361 const\r
2362   ILD_SELECTED            = ILD_BLEND50;\r
2363   ILD_FOCUS               = ILD_BLEND25;\r
2364   ILD_BLEND               = ILD_BLEND50;\r
2365   CLR_HILIGHT             = CLR_DEFAULT;\r
2367 function ImageList_Create(CX, CY: Integer; Flags: UINT;\r
2368   Initial, Grow: Integer): HImageList; stdcall;\r
2369 function ImageList_Destroy(ImageList: HImageList): Bool; stdcall;\r
2370 function ImageList_GetImageCount(ImageList: HImageList): Integer; stdcall;\r
2371 function ImageList_SetImageCount(ImageList: HImageList; Count: Integer): Integer; stdcall;\r
2372 function ImageList_Add(ImageList: HImageList; Image, Mask: HBitmap): Integer; stdcall;\r
2373 function ImageList_ReplaceIcon(ImageList: HImageList; Index: Integer;\r
2374   Icon: HIcon): Integer; stdcall;\r
2375 function ImageList_SetBkColor(ImageList: HImageList; ClrBk: TColorRef): TColorRef; stdcall;\r
2376 function ImageList_GetBkColor(ImageList: HImageList): TColorRef; stdcall;\r
2377 function ImageList_SetOverlayImage(ImageList: HImageList; Image: Integer;\r
2378   Overlay: Integer): Bool; stdcall;\r
2380 function ImageList_AddIcon(ImageList: HImageList; Icon: HIcon): Integer;\r
2382 function Index2OverlayMask(Index: Integer): Integer;\r
2384 function ImageList_Draw(ImageList: HImageList; Index: Integer;\r
2385   Dest: HDC; X, Y: Integer; Style: UINT): Bool; stdcall;\r
2387 function ImageList_Replace(ImageList: HImageList; Index: Integer;\r
2388   Image, Mask: HBitmap): Bool; stdcall;\r
2389 function ImageList_AddMasked(ImageList: HImageList; Image: HBitmap;\r
2390   Mask: TColorRef): Integer; stdcall;\r
2391 function ImageList_DrawEx(ImageList: HImageList; Index: Integer;\r
2392   Dest: HDC; X, Y, DX, DY: Integer; Bk, Fg: TColorRef; Style: Cardinal): Bool; stdcall;\r
2393 function ImageList_Remove(ImageList: HImageList; Index: Integer): Bool; stdcall;\r
2394 function ImageList_GetIcon(ImageList: HImageList; Index: Integer;\r
2395   Flags: Cardinal): HIcon; stdcall;\r
2396 function ImageList_LoadImageA(Instance: THandle; Bmp: PAnsiChar; CX, Grow: Integer;\r
2397   Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;\r
2398 function ImageList_LoadImageW(Instance: THandle; Bmp: PWideChar; CX, Grow: Integer;\r
2399   Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;\r
2400 function ImageList_LoadImage(Instance: THandle; Bmp: PChar; CX, Grow: Integer;\r
2401   Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;\r
2402 function ImageList_BeginDrag(ImageList: HImageList; Track: Integer;\r
2403   XHotSpot, YHotSpot: Integer): Bool; stdcall;\r
2404 function ImageList_EndDrag: Bool; stdcall;\r
2405 function ImageList_DragEnter(LockWnd: HWnd; X, Y: Integer): Bool; stdcall;\r
2406 function ImageList_DragLeave(LockWnd: HWnd): Bool; stdcall;\r
2407 function ImageList_DragMove(X, Y: Integer): Bool; stdcall;\r
2408 function ImageList_SetDragCursorImage(ImageList: HImageList; Drag: Integer;\r
2409   XHotSpot, YHotSpot: Integer): Bool; stdcall;\r
2410 function ImageList_DragShowNolock(Show: Bool): Bool; stdcall;\r
2411 function ImageList_GetDragImage(Point, HotSpot: PPoint): HImageList; stdcall;\r
2413 { macros }\r
2414 procedure ImageList_RemoveAll(ImageList: HImageList); stdcall;\r
2415 function ImageList_ExtractIcon(Instance: THandle; ImageList: HImageList;\r
2416   Image: Integer): HIcon; stdcall;\r
2417 function ImageList_LoadBitmap(Instance: THandle; Bmp: PChar;\r
2418   CX, Grow: Integer; MasK: TColorRef): HImageList; stdcall;\r
2420 //function ImageList_Read(Stream: IStream): HImageList; stdcall;\r
2421 //function ImageList_Write(ImageList: HImageList; Stream: IStream): BOOL; stdcall;\r
2423 //[TImageInfo]\r
2424 type\r
2425   PImageInfo = ^TImageInfo;\r
2426   TImageInfo = packed record\r
2427     hbmImage: HBitmap;\r
2428     hbmMask: HBitmap;\r
2429     Unused1: Integer;\r
2430     Unused2: Integer;\r
2431     rcImage: TRect;\r
2432   end;\r
2434 function ImageList_GetIconSize(ImageList: HImageList; var CX, CY: Integer): Bool; stdcall;\r
2435 function ImageList_SetIconSize(ImageList: HImageList; CX, CY: Integer): Bool; stdcall;\r
2436 function ImageList_GetImageInfo(ImageList: HImageList; Index: Integer;\r
2437   var ImageInfo: TImageInfo): Bool; stdcall;\r
2438 function ImageList_Merge(ImageList1: HImageList; Index1: Integer;\r
2439   ImageList2: HImageList; Index2: Integer; DX, DY: Integer)://Bool - ERROR IN VCL\r
2440   HImageList; stdcall;\r
2442 //[LoadBmp]\r
2443 function LoadBmp( Instance: Integer; Rsrc: PChar; MasterObj: PObj ): HBitmap;\r
2458 //[BITMAPS]\r
2459 type\r
2460   tagBitmap = Windows.TBitmap;\r
2462   TPixelFormat = ( pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit,\r
2463                    pf32bit, pfCustom );\r
2464   {* Available pixel formats. }\r
2465   TBitmapHandleType = ( bmDIB, bmDDB );\r
2466   {* Available bitmap handle types. }\r
2468   {++}(*TBitmap = class;*){--}\r
2469   PBitmap = {-}^{+}TBitmap;\r
2470 { ----------------------------------------------------------------------\r
2472                       TBitmap - bitmap image\r
2474 ----------------------------------------------------------------------- }\r
2475 //[TBitmap DEFINITION]\r
2476   TBitmap = object( TObj )\r
2477   {* Bitmap incapsulation object. }\r
2478   protected\r
2479     fHeight: Integer;\r
2480     fWidth: Integer;\r
2481     fHandle: HBitmap;\r
2482     fCanvas: PCanvas;\r
2483     fScanLineSize: Integer;\r
2484     fBkColor: TColor;\r
2485     fApplyBkColor2Canvas: procedure( Sender: PBitmap );\r
2486     fDetachCanvas: procedure( Sender: PBitmap );\r
2487     fCanvasAttached : Integer;\r
2488     fHandleType: TBitmapHandleType;\r
2489     fDIBHeader: PBitmapInfo;\r
2490     fDIBBits: Pointer;\r
2491     fDIBSize: Integer;\r
2492     fNewPixelFormat: TPixelFormat;\r
2493     fFillWithBkColor: procedure( BmpObj: PBitmap; DC: HDC; oldW, oldH: Integer );\r
2494                         //stdcall;\r
2495     fTransMaskBmp: PBitmap;\r
2496     fTransColor: TColor;\r
2497     fGetDIBPixels: function( Bmp: PBitmap; X, Y: Integer ): TColor;\r
2498     fSetDIBPixels: procedure( Bmp: PBitmap; X, Y: Integer; Value: TColor );\r
2499     fScanLine0: PByte;\r
2500     fScanLineDelta: Integer;\r
2501     fPixelMask: DWORD;\r
2502     fPixelsPerByteMask: Integer;\r
2503     fBytesPerPixel: Integer;\r
2504     fDIBAutoFree: Boolean;\r
2505     procedure SetHeight(const Value: Integer);\r
2506     procedure SetWidth(const Value: Integer);\r
2507     function GetEmpty: Boolean;\r
2508     function GetHandle: HBitmap;\r
2509     function GetHandleAllocated: Boolean;\r
2510     procedure SetHandle(const Value: HBitmap);\r
2511     procedure SetPixelFormat(Value: TPixelFormat);\r
2512     procedure FormatChanged;\r
2513     function GetCanvas: PCanvas;\r
2514     procedure CanvasChanged( Sender: PObj );\r
2515     function GetScanLine(Y: Integer): Pointer;\r
2516     function GetScanLineSize: Integer;\r
2517     procedure ClearData;\r
2518     procedure ClearTransImage;\r
2519     procedure SetBkColor(const Value: TColor);\r
2520     function GetDIBPalEntries(Idx: Integer): TColor;\r
2521     function GetDIBPalEntryCount: Integer;\r
2522     procedure SetDIBPalEntries(Idx: Integer; const Value: TColor);\r
2523     procedure SetHandleType(const Value: TBitmapHandleType);\r
2524     function GetPixelFormat: TPixelFormat;\r
2525     function GetPixels(X, Y: Integer): TColor;\r
2526     procedure SetPixels(X, Y: Integer; const Value: TColor);\r
2527     function GetDIBPixels(X, Y: Integer): TColor;\r
2528     procedure SetDIBPixels(X, Y: Integer; const Value: TColor);\r
2529     function GetBoundsRect: TRect;\r
2530   protected\r
2531   {++}(*public*){--}\r
2532     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
2533   public\r
2534     property Width: Integer read fWidth write SetWidth;\r
2535     {* Width of bitmap. To make code smaller, avoid changing Width or Height\r
2536        after bitmap is created (using NewBitmap) or after it is loaded from\r
2537        file, stream of resource. }\r
2538     property Height: Integer read fHeight write SetHeight;\r
2539     {* Height of bitmap. To make code smaller, avoid changing Width or Height\r
2540        after bitmap is created (using NewBitmap) or after it is loaded from\r
2541        file, stream of resource. }\r
2542     property BoundsRect: TRect read GetBoundsRect;\r
2543     {* Returns rectangle (0,0,Width,Height). }\r
2544     property Empty: Boolean read GetEmpty;\r
2545     {* Returns True if Width or Height is 0. }\r
2546     procedure Clear;\r
2547     {* Makes bitmap empty, setting its Width and Height to 0. }\r
2548     procedure LoadFromFile( const Filename: String );\r
2549     {* Loads bitmap from file (LoadFromStream used). }\r
2550     function LoadFromFileEx( const Filename: String ): Boolean;\r
2551     {* Loads bitmap from a file. If necessary, bitmap is RLE-decoded. Code given\r
2552        by Vyacheslav A. Gavrik. }\r
2553     procedure SaveToFile( const Filename: String );\r
2554     {* Stores bitmap to file (SaveToStream used). }\r
2555     procedure LoadFromStream( Strm: PStream );\r
2556     {* Loads bitmap from stream. Follow loading, bitmap has DIB format (without\r
2557        handle allocated). It is possible to draw DIB bitmap without creating\r
2558        handle for it, which can economy GDI resources. }\r
2559     function LoadFromStreamEx( Strm: PStream ): Boolean;\r
2560     {* Loads bitmap from a stream. Difference is that RLE decoding supported.\r
2561        Code given by Vyacheslav A. Gavrik. }\r
2562     procedure SaveToStream( Strm: PStream );\r
2563     {* Saves bitmap to stream. If bitmap is not DIB, it is converted to DIB\r
2564        before saving. }\r
2565     procedure LoadFromResourceID( Inst: DWORD; ResID: Integer );\r
2566     {* Loads bitmap from resource using integer ID of resource. To load by name,\r
2567        use LoadFromResurceName. To load resource of application itself, pass\r
2568        hInstance as first parameter. This method also can be used to load system\r
2569        predefined bitmaps, if 0 is passed as Inst parameter:\r
2570        |<pre>\r
2571        OBM_BTNCORNERS   OBM_REDUCE\r
2572        OBM_BTSIZE       OBM_REDUCED\r
2573        OBM_CHECK        OBM_RESTORE\r
2574        OBM_CHECKBOXES   OBM_RESTORED\r
2575        OBM_CLOSE        OBM_RGARROW\r
2576        OBM_COMBO        OBM_RGARROWD\r
2577        OBM_DNARROW      OBM_RGARROWI\r
2578        OBM_DNARROWD     OBM_SIZE\r
2579        OBM_DNARROWI     OBM_UPARROW\r
2580        OBM_LFARROW      OBM_UPARROWD\r
2581        OBM_LFARROWD     OBM_UPARROWI\r
2582        OBM_LFARROWI     OBM_ZOOM\r
2583        OBM_MNARROW      OBM_ZOOMD\r
2584        |</pre>        }\r
2585     procedure LoadFromResourceName( Inst: DWORD; ResName: PChar );\r
2586     {* Loads bitmap from resurce (using passed name of bitmap resource. }\r
2587     function Assign( SrcBmp: PBitmap ): Boolean;\r
2588     {* Assigns bitmap from another. Returns False if not success.\r
2589        Note: remember, that Canvas is not assigned - only bitmap image\r
2590        is copied. And for DIB, handle is not allocating due this process. }\r
2591     property Handle: HBitmap read GetHandle write SetHandle;\r
2592     {* Handle of bitmap. Created whenever property accessed. To check if handle\r
2593        is allocated (without allocating it), use HandleAllocated property. }\r
2594     property HandleAllocated: Boolean read GetHandleAllocated;\r
2595     {* Returns True, if Handle already allocated. }\r
2596     function ReleaseHandle: HBitmap;\r
2597     {* Returns Handle and releases it, so bitmap no more know about handle.\r
2598        This method does not destroy bitmap image, but converts it into DIB.\r
2599        Returned Handle actually is a handle of copy of original bitmap. If\r
2600        You need not in keping it up, use Dormant method instead. }\r
2601     procedure Dormant;\r
2602     {* Releases handle from bitmap and destroys it. But image is not destroyed\r
2603        and its data are preserved in DIB format. Please note, that in KOL, DIB\r
2604        bitmaps can be drawn onto given device context without allocating of\r
2605        handle. So, it is very useful to call Dormant preparing it using\r
2606        Canvas drawing operations - to economy GDI resources. }\r
2607     property HandleType: TBitmapHandleType read fHandleType write SetHandleType;\r
2608     {* bmDIB, if DIB part of image data is filled and stored internally in\r
2609        TBitmap object. DIB image therefore can have Handle allocated, which\r
2610        require resources. Use HandleAllocated funtion to determine if handle\r
2611        is allocated and Dormant method to remove it, if You want to economy\r
2612        GDI resources. (Actually Handle needed for DIB bitmap only in case\r
2613        when Canvas is used to draw on bitmap surface). Please note also, that\r
2614        before saving bitmap to file or stream, it is converted to DIB. }\r
2615     property PixelFormat: TPixelFormat read GetPixelFormat write SetPixelFormat;\r
2616     {* Current pixel format. If format of bitmap is unknown, or bitmap is DDB,\r
2617        value is pfDevice. Setting PixelFormat to any other format converts\r
2618        bitmap to DIB, back to pfDevice converts bitmap to DDB again. Avoid\r
2619        such conversations for large bitmaps or for numerous bitmaps in your\r
2620        application to keep good performance. }\r
2621     function BitsPerPixel: Integer;\r
2622     {* Returns bits per pixel if possible. }\r
2623     procedure Draw( DC: HDC; X, Y: Integer );\r
2624     {* Draws bitmap to given device context. If bitmap is DIB, it is always\r
2625        drawing using SetDIBitsToDevice API call, which does not require bitmap\r
2626        handle (so, it is very sensible to call Dormant method to free correspondent\r
2627        GDI resources). }\r
2628     procedure StretchDraw( DC: HDC; const Rect: TRect );\r
2629     {* Draws bitmap onto DC, stretching it to fit given rectangle Rect. }\r
2630     procedure DrawTransparent( DC: HDC; X, Y: Integer; TranspColor: TColor );\r
2631     {* Draws bitmap onto DC transparently, using TranspColor as transparent. }\r
2632     procedure StretchDrawTransparent( DC: HDC; const Rect: TRect; TranspColor: TColor );\r
2633     {* Draws bitmap onto given rectangle of destination DC (with stretching it\r
2634        to fit Rect) - transparently, using TranspColor as transparent. }\r
2635     procedure DrawMasked( DC: HDC; X, Y: Integer; Mask: HBitmap );\r
2636     {* Draws bitmap to destination DC transparently by mask. It is possible\r
2637        to pass as a mask handle of another TBitmap, previously converted to\r
2638        monochrome mask using Convert2Mask method. }\r
2639     procedure StretchDrawMasked( DC: HDC; const Rect: TRect; Mask: HBitmap );\r
2640     {* Like DrawMasked, but with stretching image onto given rectangle. }\r
2641     procedure Convert2Mask( TranspColor: TColor );\r
2642     {* Converts bitmap to monochrome (mask) bitmap with TranspColor replaced\r
2643        to clBlack and all other ones to clWhite. Such mask bitmap can be used\r
2644        to draw original bitmap transparently, with given TranspColor as\r
2645        transparent. (To preserve original bitmap, create new instance of\r
2646        TBitmap and assign original bitmap to it). See also DrawTransparent and\r
2647        StretchDrawTransparent methods. }\r
2648     procedure Invert;\r
2649     {* Obvious. }\r
2650     property Canvas: PCanvas read GetCanvas;\r
2651     {* Canvas can be used to draw onto bitmap. Whenever it is accessed, handle\r
2652        is allocated for bitmap, if it is not yet (to make it possible\r
2653        to select bitmap to display compatible device context). }\r
2654     procedure RemoveCanvas;\r
2655     {* Call this method to destroy Canvas and free GDI resources. }\r
2656     property BkColor: TColor read fBkColor write SetBkColor;\r
2657     {* Used to fill background for Bitmap, when its width or height is increased.\r
2658        Although this value always synchronized with Canvas.Brush.Color, use it\r
2659        instead if You do not use Canvas for drawing on bitmap surface. }\r
2660     property Pixels[ X, Y: Integer ]: TColor read GetPixels write SetPixels;\r
2661     {* Allows to obtain or change certain pixels of a bitmap. This method is\r
2662        both for DIB and DDB bitmaps, and leads to allocate handle anyway. For\r
2663        DIB bitmaps, it is possible to use property DIBPixels[ ] instead,\r
2664        which is much faster and does not require in Handle. }\r
2665     property ScanLineSize: Integer read GetScanLineSize;\r
2666     {* Returns size of scan line in bytes. Use it to measure size of a single\r
2667        ScanLine. To calculate increment value from first byte of ScanLine to\r
2668        first byte of next ScanLine, use difference\r
2669        !  Integer(ScanLine[1]-ScanLine[0])\r
2670        (this is because bitmap can be oriented from bottom to top, so\r
2671        step can be negative). }\r
2672     property ScanLine[ Y: Integer ]: Pointer read GetScanLine;\r
2673     {* Use ScanLine to access DIB bitmap pixels in memory to direct access it\r
2674        fast. Take in attention, that for different pixel formats, different\r
2675        bit counts are used to represent bitmap pixels. Also do not forget, that\r
2676        for formats pf4bit and pf8bit, pixels actually are indices to palette\r
2677        entries, and for formats pf16bit, pf24bit and pf32bit are actually\r
2678        RGB values (for pf16bit B:5-G:6-R:5, for pf15bit B:5-G:5-R:5 (high order\r
2679        bit not used), for pf24bit B:8-G:8-R:8, and for pf32bit high order byte\r
2680        of TRGBQuad structure is not used). }\r
2681     property DIBPixels[ X, Y: Integer ]: TColor read GetDIBPixels write SetDIBPixels;\r
2682     {* Allows direct access to pixels of DIB bitmap, faster then Pixels[ ]\r
2683        property. Access to read is slower for pf15bit, pf16bit formats (because\r
2684        some conversation needed to translate packed RGB color to TColor). And\r
2685        for write, operation performed most slower for pf4bit, pf8bit (searching\r
2686        nearest color required) and fastest for pf24bit, pf32bit and pf1bit. }\r
2687     property DIBPalEntryCount: Integer read GetDIBPalEntryCount;\r
2688     {* Returns palette entries count for DIB image. Always returns 2 for pf1bit,\r
2689        16 for pf4bit, 256 for pf8bit and 0 for other pixel formats. }\r
2690     property DIBPalEntries[ Idx: Integer ]: TColor read GetDIBPalEntries write\r
2691              SetDIBPalEntries;\r
2692     {* Provides direct access to DIB palette. }\r
2693     function DIBPalNearestEntry( Color: TColor ): Integer;\r
2694     {* Returns index of entry in DIB palette with color nearest (or matching)\r
2695        to given one. }\r
2696     property DIBBits: Pointer read fDIBBits;\r
2697     {* This property is mainly for internal use. }\r
2698     property DIBSize: Integer read fDIBSize;\r
2699     {* Size of DIBBits array. }\r
2700     property DIBHeader: PBitmapInfo read fDIBHeader;\r
2701     {* This property is mainly for internal use. }\r
2702     procedure DIBDrawRect( DC: HDC; X, Y: Integer; const R: TRect );\r
2703     {* This procedure copies given rectangle to the target device context,\r
2704        but only for DIB bitmap (using SetDIBBitsToDevice API call). }\r
2705     procedure RotateRight;\r
2706     {* Rotates bitmap right (90 degree). Bitmap must be DIB. If You definitevely\r
2707        know format of a bitmap, use instead one of methods RotateRightMono,\r
2708        RotateRight4bit, RotateRight8bit, RotateRight16bit or RotateRightTrueColor\r
2709        - this will economy code. But if for most of formats such methods are\r
2710        called, this can be more economy just to call always universal method\r
2711        RotateRight. }\r
2712     procedure RotateLeft;\r
2713     {* Rotates bitmap left (90 degree). Bitmap must be DIB. If You definitevely\r
2714        know format of a bitmap, use instead one of methods RotateLeftMono,\r
2715        RotateLeft4bit, RotateLeft8bit, RotateLeft16bit or RotateLeftTrueColor\r
2716        - this will economy code. But if for most of formats such methods are\r
2717        called, this can be more economy just to call always universal method\r
2718        RotateLeft. }\r
2719     procedure RotateRightMono;\r
2720     {* Rotates bitmat right, but only if bitmap is monochrome (pf1bit). }\r
2721     procedure RotateLeftMono;\r
2722     {* Rotates bitmap left, but only if bitmap is monochrome (pf1bit). }\r
2723     procedure RotateRight4bit;\r
2724     {* Rotates bitmap right, but only if PixelFormat is pf4bit. }\r
2725     procedure RotateLeft4bit;\r
2726     {* Rotates bitmap left, but only if PixelFormat is pf4bit. }\r
2727     procedure RotateRight8bit;\r
2728     {* Rotates bitmap right, but only if PixelFormat is pf8bit. }\r
2729     procedure RotateLeft8bit;\r
2730     {* Rotates bitmap left, but only if PixelFormat is pf8bit. }\r
2731     procedure RotateRight16bit;\r
2732     {* Rotates bitmap right, but only if PixelFormat is pf16bit. }\r
2733     procedure RotateLeft16bit;\r
2734     {* Rotates bitmap left, but only if PixelFormat is pf16bit. }\r
2735     procedure RotateRightTrueColor;\r
2736     {* Rotates bitmap right, but only if PixelFormat is pf24bit or pf32bit. }\r
2737     procedure RotateLeftTrueColor;\r
2738     {* Rotates bitmap left, but only if PixelFormat is pf24bit or pf32bit. }\r
2739     procedure FlipVertical;\r
2740     {* Flips bitmap vertically }\r
2741     procedure FlipHorizontal;\r
2742     {* Flips bitmap horizontally }\r
2743     procedure CopyRect( const DstRect : TRect; SrcBmp : PBitmap; const SrcRect : TRect );\r
2744     {* It is possible to use Canvas.CopyRect for such purpose, but if You\r
2745        do not want use TCanvas, it is possible to copy rectangle from one\r
2746        bitmap to another using this function. }\r
2747     function CopyToClipboard: Boolean;\r
2748     {* Copies bitmap to clipboard. }\r
2749     function PasteFromClipboard: Boolean;\r
2750     {* Takes CF_DIB format bitmap from clipboard and assigns it to the\r
2751        TBitmap object. }\r
2752   end;\r
2753 //[END OF TBitmap DEFINITION]\r
2755 //[NewBitmap DECLARATION]\r
2756 function NewBitmap( W, H: Integer ): PBitmap;\r
2757 {* Creates bitmap object of given size. If it is possible, do not change its\r
2758    size (Width and Heigth) later - this can economy code a bit. See TBitmap. }\r
2760 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;\r
2761 {* Creates DIB bitmap object of given size and pixel format. If it is possible,\r
2762    do not change its size (Width and Heigth) later - this can economy code a bit.\r
2763    See TBitmap. }\r
2765 //[CalcScanLineSize DECLARATION]\r
2766 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;\r
2767 {* May be will be useful. }\r
2769 //[DefaultPixelFormat VARIABLE]\r
2770 var\r
2771   //DefaultBitsPerPixel: Integer = 16;\r
2772   DefaultPixelFormat: TPixelFormat = pf16bit;\r
2774 //[Mapped bitmaps]\r
2776 { -- Function to load bitmap mapping some its colors. -- }\r
2777 function LoadMappedBitmap( hInst: THandle; BmpResID: Integer; const Map: array of TColor )\r
2778          : HBitmap;\r
2779 {* This function can be used to load bitmap and replace some it colors to\r
2780    desired ones. This function especially useful when loaded by the such way\r
2781    bitmap is used as toolbar bitmap - to replace some original colors to\r
2782    system default colors. To use this function properly, the bitmap shoud\r
2783    be prepared as 16-color bitmap, which uses only system colors. To do so,\r
2784    create a new 16-color bitmap with needed dimensions in Borland Image Editor\r
2785    and paste a bitmap image, copyed in another graphic tool, and then save it.\r
2786    If this is not done, bitmap will not be loaded correctly! }\r
2787 function LoadMappedBitmapEx( MasterObj: PObj; hInst: THandle; BmpResName: PChar; const Map: array of TColor )\r
2788          : HBitmap;\r
2789 {* Like LoadMappedBitmap, but much powerful. It uses CreateMappedBitmapEx\r
2790    by Alex Pravdin, so it understands any bitmap color format, including\r
2791    pf24bit. Also, LoadMappedBitmapEx provides auto-destroying loaded resource\r
2792    when MasterObj is destroyed. }\r
2793 function CreateMappedBitmap(Instance: THandle; Bitmap: Integer;\r
2794   Flags: UINT; ColorMap: PColorMap; NumMaps: Integer): HBitmap; stdcall;\r
2795 {* Creates mapped bitmap replacing colors correspondently to the\r
2796    ColorMap (each pare of colors defines color replaced and a color\r
2797    used for replace it in the bitmap). See also CreateMappedBitmapEx. }\r
2798 function CreateMappedBitmapEx(Instance: THandle; BmpRsrcName: PChar; Flags:\r
2799   Cardinal; ColorMap: PColorMap; NumMaps: Integer): HBitmap;\r
2800 {* By Alex Pravdin.\r
2801 Creates mapped bitmap independently from bitmap color format (works\r
2802 correctly with bitmaps having format deeper than 8bit per pixel). }\r
2815 //[ICONS]\r
2817 type\r
2818   {++}(*TIcon = class;*){--}\r
2819   PIcon = {-}^{+}TIcon;\r
2820 { ----------------------------------------------------------------------\r
2822                           TIcon - icon image\r
2824 ----------------------------------------------------------------------- }\r
2825 //[TIcon DEFINITION]\r
2826   TIcon = object( TObj )\r
2827   {* Object type to incapsulate icon or cursor image. }\r
2828   protected\r
2829     FSize : Integer;\r
2830     FHandle: HIcon;\r
2831     FShareIcon: Boolean;\r
2832     procedure SetSize(const Value: Integer);\r
2833     procedure SetHandle(const Value: HIcon);\r
2834     function GetHotSpot: TPoint;\r
2835     function GetEmpty: Boolean;\r
2836   protected\r
2837   {++}(*public*){--}\r
2838     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
2839   public\r
2840     property Size : Integer read FSize write SetSize;\r
2841     {* Icon dimension (width and/or height, which are equal to each other always). }\r
2842     property Handle : HIcon read FHandle write SetHandle;\r
2843     {* Windows icon object handle. }\r
2844     procedure Clear;\r
2845     {* Clears icon, freeing image and allocated GDI resource (Handle). }\r
2846     property Empty: Boolean read GetEmpty;\r
2847     {* Returns True if icon is Empty. }\r
2848     property ShareIcon : Boolean read FShareIcon write FShareIcon;\r
2849     {* True, if icon object is shared and can not be deleted when TIcon object\r
2850        is destroyed (set this flag is to True, if an icon is obtained from another\r
2851        TIcon object, for example). }\r
2852     property HotSpot : TPoint read GetHotSpot;\r
2853     {* Hot spot point - for cursors. }\r
2854     procedure Draw( DC : HDC; X, Y : Integer );\r
2855     {* Draws icon onto given device context. Icon always is drawn transparently\r
2856        using its transparency mask (stored internally in icon object). }\r
2857     procedure StretchDraw( DC : HDC; Dest : TRect );\r
2858     {* Draws icon onto given device context with stretching it to fit destination\r
2859        rectangle. See also Draw. }\r
2860     procedure LoadFromStream( Strm : PStream );\r
2861     {* Loads icon from stream. If stream contains several icons (of\r
2862        different dimentions), icon with the most appropriate size is loading. }\r
2863     procedure LoadFromFile( const FileName : String );\r
2864     {* Load icon from file. If file contains several icons (of\r
2865        different dimensions), icon with the most appropriate size is loading. }\r
2866     procedure LoadFromResourceID( Inst: Integer; ResID: Integer; DesiredSize: Integer );\r
2867     {* Loads icon from resource. To load system default icon, pass 0 as Inst and\r
2868        one of followin values as ResID:\r
2869        |<pre>\r
2870        IDI_APPLICATION  Default application icon.\r
2871        IDI_ASTERISK     Asterisk (used in informative messages).\r
2872        IDI_EXCLAMATION  Exclamation point (used in warning messages).\r
2873        IDI_HAND         Hand-shaped icon (used in serious warning messages).\r
2874        IDI_QUESTION     Question mark (used in prompting messages).\r
2875        IDI_WINLOGO      Windows logo.\r
2876        |</pre> It is also possible to load icon from resources of another module,\r
2877        if pass instance handle of loaded module as Inst parameter. }\r
2878     procedure LoadFromResourceName( Inst: Integer; ResName: PChar; DesiredSize: Integer );\r
2879     {* Loads icon from resource. To load own application resource, pass\r
2880        hInstance as Inst parameter. It is possible to load resource from\r
2881        another module, if pass its instance handle as Inst. }\r
2882     procedure LoadFromExecutable( const FileName: String; IconIdx: Integer );\r
2883     {* Loads icon from executable (exe or dll file). Always default sized icon\r
2884        is loaded. It is possible also to get know how much icons are contained\r
2885        in executable using gloabl function GetFileIconCount. To obtain icon of\r
2886        another size, try to load given executable and use LoadFromResourceID\r
2887        method. }\r
2888     procedure SaveToStream( Strm : PStream );\r
2889     {* Saves single icon to stream. To save icons with several different\r
2890        dimensions, use global procedure SaveIcons2Stream. }\r
2891     procedure SaveToFile( const FileName : String );\r
2892     {* Saves single icon to file. To save icons with several different\r
2893        dimensions, use global procedure SaveIcons2File. }\r
2894     function Convert2Bitmap( TranColor: TColor ): HBitmap;\r
2895     {* Converts icon to bitmap, returning Windows GDI bitmap resource as\r
2896        a result. It is possible later to assign returned bitmap handle to\r
2897        Handle property of TBitmap object to use features of TBitmap.\r
2898        Pass TranColor to replace transparent area of icon with given color. }\r
2899   end;\r
2900 //[END OF TIcon DEFINITION]\r
2902 //[Icon save functions]\r
2904   procedure SaveIcons2Stream( const Icons : array of PIcon; Strm : PStream );\r
2905   {* Saves several icons (of different dimentions) to stream. }\r
2906   function SaveIcons2StreamEx( const BmpHandles: array of HBitmap; Strm: PStream ): Boolean;\r
2907   {* Saves icons creating it from pairs of bitmaps and their masks.\r
2908      BmpHandles array must contain pairs of bitmap handles, each pair\r
2909      of color bitmap and mask bitmap of the same size. }\r
2910   procedure SaveIcons2File( const Icons : array of PIcon; const FileName : String );\r
2911   {* Saves several icons (of different dimentions) to file. (Single file\r
2912      with extension .ico can contain several different sized icon images\r
2913      to use later one with the most appropriate size). }\r
2915 //[NewIcon DECLARATION]\r
2916   function NewIcon: PIcon;\r
2917   {* Creates new icon object, setting its Size to 32 by default. Created icon\r
2918      is Empty. }\r
2920 //[GetFileIconCount DECLARATION]\r
2921   function GetFileIconCount( const FileName: String ): Integer;\r
2922   {* Returns number of icon resources stored in given (executable) file. }\r
2924 //[ICON STRUCTURES]\r
2925 type\r
2926   TIconHeader = packed record\r
2927     idReserved: Word; (* Always set to 0 *)\r
2928     idType: Word;     (* Always set to 1 *)\r
2929     idCount: Word;    (* Number of icon images *)\r
2930     (* immediately followed by idCount TIconDirEntries *)\r
2931   end;\r
2933   TIconDirEntry = packed record\r
2934     bWidth: Byte;          (* Width *)\r
2935     bHeight: Byte;         (* Height *)\r
2936     bColorCount: Byte;     (* Nr. of colors used, see below *)\r
2937     bReserved: Byte;       (* not used, 0 *)\r
2938     wPlanes: Word;         (* not used, 0 *)\r
2939     wBitCount: Word;       (* not used, 0 *)\r
2940     dwBytesInRes: Longint; (* total number of bytes in images *)\r
2941     dwImageOffset: Longint;(* location of image from the beginning of file *)\r
2942   end;\r
2944 //[LoadImgIcon DECLARATION]\r
2945 function LoadImgIcon( RsrcName: PChar; Size: Integer ): HIcon;\r
2946 {* Loads icon of specified size from the resource. }\r
2955 //[METAFILES]\r
2957 type\r
2958   {++}(*TMetafile = class;*){--}\r
2959   PMetafile = {-}^{+}TMetafile;\r
2960 { ----------------------------------------------------------------------\r
2962       TMetafile - Windows metafile and Enchanced Metafile image\r
2964 ----------------------------------------------------------------------- }\r
2965 //[TMetafile DEFINITION]\r
2966   TMetafile = object( TObj )\r
2967   {* Object type to incapsulate metafile image. }\r
2968   protected\r
2969     function GetHeight: Integer;\r
2970     function GetWidth: Integer;\r
2971     procedure SetHandle(const Value: THandle);\r
2972   protected\r
2973     fHandle: THandle;\r
2974     fHeader: PEnhMetaHeader;\r
2975     procedure RetrieveHeader;\r
2976   public\r
2977     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
2978     {* }\r
2979     procedure Clear;\r
2980     {* }\r
2981     function Empty: Boolean;\r
2982     {* Returns TRUE if empty}\r
2983     property Handle: THandle read fHandle write SetHandle;\r
2984     {* Returns handle of enchanced metafile. }\r
2985     function LoadFromStream( Strm: PStream ): Boolean;\r
2986     {* Loads emf or wmf file format from stream. }\r
2987     function LoadFromFile( const Filename: String ): Boolean;\r
2988     {* Loads emf or wmf from stream. }\r
2989     procedure Draw( DC: HDC; X, Y: Integer );\r
2990     {* Draws enchanced metafile on DC. }\r
2991     procedure StretchDraw( DC: HDC; const R: TRect );\r
2992     {* Draws enchanced metafile stretched. }\r
2993     property Width: Integer read GetWidth;\r
2994     {* Native width of the metafile. }\r
2995     property Height: Integer read GetHeight;\r
2996     {* Native height of the metafile. }\r
2997   end;\r
2998 //[END OF TMetafile DEFINITION]\r
3000 //[NewMetafile DECLARATION]\r
3001 function NewMetafile: PMetafile;\r
3002 {* Creates metafile object. }\r
3004 //[Metafile CONSTANTS, STRUCTURES, ETC.]\r
3005 const\r
3006   WMFKey = Integer($9AC6CDD7);\r
3007   WMFWord = $CDD7;\r
3008 type\r
3009   TMetafileHeader = packed record\r
3010     Key: Longint;\r
3011     Handle: SmallInt;\r
3012     Box: TSmallRect;\r
3013     Inch: Word;\r
3014     Reserved: Longint;\r
3015     CheckSum: Word;\r
3016   end;\r
3018 function ComputeAldusChecksum(var WMF: TMetafileHeader): Word;\r
3020 {++}(*\r
3021 function SetEnhMetaFileBits(p1: UINT; p2: PChar): HENHMETAFILE; stdcall;\r
3022 function PlayEnhMetaFile(DC: HDC; p2: HENHMETAFILE; const p3: TRect): BOOL; stdcall;\r
3023 *){--}\r
3043 ////////////////////////////////////////////////////////////////////////////////\r
3044 //                       UNIVERSAL CONTROL OBJECT                             //\r
3045 ////////////////////////////////////////////////////////////////////////////////\r
3047 //[CM_XXX CONSTANTS]\r
3049 const\r
3050   CM_EXECPROC       = $8FFF;\r
3051   CM_BASE           = $B000;\r
3052   CM_ACTIVATE       = CM_BASE + 0;\r
3053   CM_DEACTIVATE     = CM_BASE + 1;\r
3054   CM_ENTER          = CM_BASE + 2;\r
3055   CM_RELEASE        = CM_BASE + 3;\r
3056   CM_QUIT           = CM_BASE + 4;\r
3057   CM_COMMAND        = CM_BASE + 5;\r
3058   CM_MEASUREITEM    = CM_BASE + 6;\r
3059   CM_DRAWITEM       = CM_BASE + 7;\r
3060   CM_TRAYICON       = CM_BASE + 8;\r
3061   CM_INVALIDATE     = CM_BASE + 9;\r
3062   CM_UPDATE         = CM_BASE + 10;\r
3063   CM_NCUPDATE       = CM_BASE + 11;\r
3064   CM_SIZEPOS        = CM_BASE + 12;\r
3065   CM_SIZE           = CM_BASE + 13;\r
3066   CM_SETFOCUS       = CM_BASE + 14;\r
3067   CM_CBN_SELCHANGE  = 15;\r
3069   CM_UIACTIVATE     = CM_BASE + 16;\r
3070   CM_UIDEACTIVATE   = CM_BASE + 17;\r
3071   CM_PROCESS        = CM_BASE + 18;\r
3072   CM_SHOW           = CM_BASE + 19;\r
3074   //CM_CLOSE           = CM_BASE + 20;\r
3075   CM_MDIClientShowEdge = CM_BASE + 21;\r
3077 //[CN_XXX CONSTANTS]\r
3079   CN_BASE = $BC00;\r
3080   CN_CHARTOITEM        = CN_BASE + WM_CHARTOITEM;\r
3081   CN_COMMAND           = CN_BASE + WM_COMMAND;\r
3082   CN_COMPAREITEM       = CN_BASE + WM_COMPAREITEM;\r
3084   CN_CTLCOLORMSGBOX    = CN_BASE + WM_CTLCOLORMSGBOX;\r
3085   CN_CTLCOLOREDIT      = CN_BASE + WM_CTLCOLOREDIT;\r
3086   CN_CTLCOLORLISTBOX   = CN_BASE + WM_CTLCOLORLISTBOX;\r
3087   CN_CTLCOLORBTN       = CN_BASE + WM_CTLCOLORBTN;\r
3088   CN_CTLCOLORDLG       = CN_BASE + WM_CTLCOLORDLG;\r
3089   CN_CTLCOLORSCROLLBAR = CN_BASE + WM_CTLCOLORSCROLLBAR;\r
3090   CN_CTLCOLORSTATIC    = CN_BASE + WM_CTLCOLORSTATIC;\r
3092   CN_DELETEITEM        = CN_BASE + WM_DELETEITEM;\r
3093   CN_DRAWITEM          = CN_BASE + WM_DRAWITEM;\r
3094   CN_HSCROLL           = CN_BASE + WM_HSCROLL;\r
3095   CN_MEASUREITEM       = CN_BASE + WM_MEASUREITEM;\r
3096   CN_PARENTNOTIFY      = CN_BASE + WM_PARENTNOTIFY;\r
3097   CN_VKEYTOITEM        = CN_BASE + WM_VKEYTOITEM;\r
3098   CN_VSCROLL           = CN_BASE + WM_VSCROLL;\r
3099   CN_KEYDOWN           = CN_BASE + WM_KEYDOWN;\r
3100   CN_KEYUP             = CN_BASE + WM_KEYUP;\r
3101   CN_CHAR              = CN_BASE + WM_CHAR;\r
3102   CN_SYSKEYDOWN        = CN_BASE + WM_SYSKEYDOWN;\r
3103   CN_SYSCHAR           = CN_BASE + WM_SYSCHAR;\r
3104   CN_NOTIFY            = CN_BASE + WM_NOTIFY;\r
3107 //[ID_SELF DEFINED]\r
3108   ID_SELF: array[ 0..5 ] of Char = ( 'S','E','L','F','_',#0 );\r
3109   {* Identifier for window property "Self", stored directly in window, when\r
3110      it is created. This property is used to [fast] find TControl object,\r
3111      correspondent to given window handle (using API call GetProp). }\r
3113 //[ID_PREVPROC DEFINED]\r
3114   ID_PREVPROC: array[ 0..9 ] of Char = ( 'P','R','E','V','_','P','R','O','C',#0 );\r
3115   {* }\r
3117 //[MK_ALT DEFINED]\r
3118   MK_ALT = $20;\r
3120 //[RICHEDIT STRUCTURES]\r
3121 type\r
3122   TCharFormat2A = packed record\r
3123     cbSize: UINT;\r
3124     dwMask: DWORD;\r
3125     dwEffects: DWORD;\r
3126     yHeight: Longint;\r
3127     yOffset: Longint;\r
3128     crTextColor: TColorRef;\r
3129     bCharSet: Byte;\r
3130     bPitchAndFamily: Byte;\r
3131     szFaceName: array[0..LF_FACESIZE - 1] of AnsiChar;\r
3132     R2Bytes: Word;\r
3133     wWeight: Word;                   { Font weight (LOGFONT value)               }\r
3134     sSpacing: Smallint;              { Amount to space between letters   }\r
3135     crBackColor: TColorRef;          { Background color                                  }\r
3136     lid: LCID;                       { Locale ID                                                 }\r
3137     dwReserved: DWORD;               { Reserved. Must be 0                               }\r
3138     sStyle: Smallint;                { Style handle                                              }\r
3139     wKerning: Word;                  { Twip size above which to kern char pair }\r
3140     bUnderlineType: Byte;            { Underline type                                    }\r
3141     bAnimation: Byte;                { Animated text like marching ants  }\r
3142     bRevAuthor: Byte;                { Revision author index                     }\r
3143     bReserved1: Byte;\r
3144   end;\r
3145   TCharFormat2 = TCharFormat2A;\r
3147   TParaFormat2 = packed record\r
3148     cbSize: UINT;\r
3149     dwMask: DWORD;\r
3150     wNumbering: Word;\r
3151     wReserved: Word;\r
3152     dxStartIndent: Longint;\r
3153     dxRightIndent: Longint;\r
3154     dxOffset: Longint;\r
3155     wAlignment: Word;\r
3156     cTabCount: Smallint;\r
3157     rgxTabs: array [0..MAX_TAB_STOPS - 1] of Longint;\r
3158     dySpaceBefore: Longint;     { Vertical spacing before para                   }\r
3159     dySpaceAfter: Longint;      { Vertical spacing after para                    }\r
3160     dyLineSpacing: Longint;     { Line spacing depending on Rule                 }\r
3161     sStyle: Smallint;           { Style handle                                                   }\r
3162     bLineSpacingRule: Byte;     { Rule for line spacing (see tom.doc)    }\r
3163     bCRC: Byte;                 { Reserved for CRC for rapid searching   }\r
3164     wShadingWeight: Word;       { Shading in hundredths of a per cent    }\r
3165     wShadingStyle: Word;        { Nibble 0: style, 1: cfpat, 2: cbpat    }\r
3166     wNumberingStart: Word;      { Starting value for numbering                   }\r
3167     wNumberingStyle: Word;      { Alignment, roman/arabic, (), ), ., etc. }\r
3168     wNumberingTab: Word;        { Space bet 1st indent and 1st-line text }\r
3169     wBorderSpace: Word;         { Space between border and text (twips) }\r
3170     wBorderWidth: Word;         { Border pen width (twips)                               }\r
3171     wBorders: Word;             { Byte 0: bits specify which borders     }\r
3172                                 { Nibble 2: border style, 3: color index }\r
3173   end;\r
3175   TGetTextLengthEx = packed record\r
3176     flags: DWORD;              { flags (see GTL_XXX defines)                             }\r
3177     codepage: UINT;            { code page for translation (CP_ACP for default,\r
3178                                  1200 for Unicode                                        }\r
3179   end;\r
3181 const\r
3182   PFM_SPACEBEFORE                     = $00000040;\r
3183   PFM_SPACEAFTER                      = $00000080;\r
3184   PFM_LINESPACING                     = $00000100;\r
3185   PFM_STYLE                           = $00000400;\r
3186   PFM_BORDER                          = $00000800;      { (*)    }\r
3187   PFM_SHADING                         = $00001000;      { (*)    }\r
3188   PFM_NUMBERINGSTYLE                  = $00002000;      { (*)    }\r
3189   PFM_NUMBERINGTAB                    = $00004000;      { (*)    }\r
3190   PFM_NUMBERINGSTART                  = $00008000;      { (*)    }\r
3192   PFM_RTLPARA                         = $00010000;\r
3193   PFM_KEEP                            = $00020000;      { (*)    }\r
3194   PFM_KEEPNEXT                        = $00040000;      { (*)    }\r
3195   PFM_PAGEBREAKBEFORE                 = $00080000;      { (*)    }\r
3196   PFM_NOLINENUMBER                    = $00100000;      { (*)    }\r
3197   PFM_NOWIDOWCONTROL                  = $00200000;      { (*)    }\r
3198   PFM_DONOTHYPHEN                     = $00400000;      { (*)    }\r
3199   PFM_SIDEBYSIDE                      = $00800000;      { (*)    }\r
3201   PFM_TABLE                           = $c0000000;      { (*)    }\r
3202   EM_REDO                             = WM_USER + 84;\r
3203   EM_AUTOURLDETECT                    = WM_USER + 91;\r
3204   EM_GETAUTOURLDETECT                 = WM_USER + 92;\r
3205   CFM_UNDERLINETYPE           = $00800000;              { (*)    }\r
3206   CFM_HIDDEN                  = $0100;                  { (*)    }\r
3207   CFM_BACKCOLOR               = $04000000;\r
3208   CFE_AUTOBACKCOLOR           = CFM_BACKCOLOR; \r
3209   GTL_USECRLF         = 1;      { compute answer using CRLFs for paragraphs }\r
3210   GTL_PRECISE         = 2;      { compute a precise answer                                       }\r
3211   GTL_CLOSE           = 4;      { fast computation of a "close" answer           }\r
3212   GTL_NUMCHARS        = 8;      { return the number of characters                        }\r
3213   GTL_NUMBYTES        = 16;     { return the number of _bytes_                           }\r
3214   EM_GETTEXTLENGTHEX                  = WM_USER + 95; \r
3215   EM_SETLANGOPTIONS                   = WM_USER + 120; \r
3216   EM_GETLANGOPTIONS                   = WM_USER + 121;\r
3218   EM_SETEDITSTYLE = $400 + 204;\r
3219   EM_GETEDITSTYLE = $400 + 205;\r
3221   SES_EMULATESYSEDIT = 1;\r
3222   SES_BEEPONMAXTEXT = 2;\r
3223   SES_EXTENDBACKCOLOR = 4;\r
3224   SES_MAPCPS = 8;\r
3225   SES_EMULATE10 = 16;\r
3226   SES_USECRLF = 32;\r
3227   SES_USEAIMM = 64;\r
3228   SES_NOIME = 128;\r
3229   SES_ALLOWBEEPS = 256;\r
3230   SES_UPPERCASE = 512;\r
3231   SES_LOWERCASE = 1024;\r
3232   SES_NOINPUTSEQUENCECHK = 2048;\r
3233   SES_BIDI = 4096;\r
3234   SES_SCROLLONKILLFOCUS = 8192;\r
3235   SES_XLTCRCRLFTOCR = 16384;\r
3237 //[CONTROLS]\r
3239 type\r
3240   {++}(*TControl = class;*){--}\r
3241   PControl = {-}^{+}TControl;\r
3242   {* Type of pointer to TControl visual object. All\r
3243      |<a href="kol_pas.htm#visual_objects_constructors">\r
3244      constructing functions\r
3245      |</a>\r
3246      New[ControlName] are returning\r
3247      pointer of this type. Do not forget about some difference\r
3248      of using objects from using classes. Identifier Self for\r
3249      methods of object is not of pointer type, and to pass\r
3250      pointer to Self, it is necessary to pass @Self instead.\r
3251      At the same time, to use pointer to object in 'WITH' operator,\r
3252      it is necessary to apply suffix '^' to pointer to get know\r
3253      to compiler, what do You want. }\r
3255 //[TWindowFunc TYPE]\r
3256   TWindowFunc = function( Sender: PControl; var Msg: TMsg; var Rslt: Integer )\r
3257                           : Boolean;\r
3258   {* Event type to define custom extended message handlers (as pointers to\r
3259      procedure entry points). Such handlers are usually defined like add-ons,\r
3260      extending behaviour of certain controls and attached using AttachProc\r
3261      method of TControl. If the handler detects, that it is necessary to stop\r
3262      further message processing, it should return True. }\r
3265 //[Mouse TYPES]\r
3266   TMouseButton = ( mbNone, mbLeft, mbRight, mbMiddle );\r
3267   {* Available mouse buttons. mbNone is useful to get know, that\r
3268      there were no mouse buttons pressed. }\r
3270   TMouseEventData = packed Record\r
3271   {* Record to pass it to mouse handling routines, assigned to OnMouseXXXX\r
3272      events. }\r
3273     Button: TMouseButton;\r
3274     StopHandling: Boolean; // Set it to True in OnMouseXXXX event handler to\r
3275                            // stop further processing\r
3276     R1, R2: Byte; // Not used\r
3277     Shift : DWORD;    // HiWord( Shift ) = zDelta in WM_MOUSEWHEEL\r
3278     X, Y  : SmallInt;\r
3279   end;\r
3281   TOnMouse = procedure( Sender: PControl; var Mouse: TMouseEventData ) of object;\r
3282   {* Common mouse handling event type. }\r
3284 //[Key TYPES]\r
3285   TOnKey = procedure( Sender: PControl; var Key: Longint; Shift: DWORD ) of object;\r
3286   {* Key events. Shift is a combination of flags MK_SHIFT, MK_CONTROL, MK_ALT.\r
3287      (See GetShiftState funtion). }\r
3289   TOnChar = procedure( Sender: PControl; var Key: Char; Shift: DWORD ) of object;\r
3290   {* Char event. Shift is a combination of flags MK_SHIFT, MK_CONTROL, MK_ALT. }\r
3292   TTabKey = ( tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn );\r
3293   {* Available tabulating key groups. }\r
3294   TTabKeys = Set of TTabKey;\r
3295   {* Set of tabulating key groups, allowed to be used in with a control\r
3296      (are installed by TControl.LookTabKey property). }\r
3298 //[Event TYPES]\r
3299   TOnMessage = function( var Msg: TMsg; var Rslt: Integer ): Boolean of object;\r
3300   {* Event type for events, which allows to extend behaviour of windowed controls\r
3301      descendants using add-ons. }\r
3303   TOnEventAccept = procedure( Sender: PObj; var Accept: Boolean ) of object;\r
3304   {* Event type for OnClose event. }\r
3305   TCloseQueryReason = ( qClose, qShutdown, qLogoff );\r
3306   {* Request reason type to call OnClose and OnQueryEndSession. }\r
3307   TWindowState = ( wsNormal, wsMinimized, wsMaximized );\r
3308   {* Avalable states of TControl's window object. }\r
3310   TOnSplit = function( Sender: PControl; NewSize1, NewSize2: Integer ): Boolean of object;\r
3311   {* Event type for OnSplit event handler, designed specially for splitter\r
3312      control. Event handler must return True to accept new size of previous\r
3313      (to splitter) control and new size of the rest of client area of parent. }\r
3315   TOnTVBeginDrag = procedure( Sender: PControl; Item: THandle ) of object;\r
3316   {* Event type for OnTVBeginDrag event (defined for tree view control). }\r
3317   TOnTVBeginEdit = function( Sender: PControl; Item: THandle ): Boolean of object;\r
3318   {* Event type for OnTVBeginEdit event (for tree view control). }\r
3319   TOnTVEndEdit = function( Sender: PControl; Item: THandle; const NewTxt: String )\r
3320                : Boolean of object;\r
3321   {* Event type for TOnTVEndEdit event. }\r
3322   TOnTVExpanding = function( Sender: PControl; Item: THandle; Expand: Boolean )\r
3323                  : Boolean of object;\r
3324   {* Event type for TOnTVExpanding event. }\r
3325   TOnTVExpanded = procedure( Sender: PControl; Item: THandle; Expand: Boolean )\r
3326                 of object;\r
3327   {* Event type for OnTVExpanded event. }\r
3328   TOnTVDelete = procedure( Sender: PControl; Item: THandle ) of object;\r
3329   {* Event type for OnTVDelete event. }\r
3331   //--------- by Sergey Shisminzev:\r
3332   TOnTVSelChanging = function(Sender: PControl; oldItem, newItem: THandle): Boolean  //~ss\r
3333                   of object;\r
3334   {* When the handler returns False, selection is not changed. }\r
3335   //-------------------------------\r
3336   TOnDrag = function( Sender: PControl; ScrX, ScrY: Integer; var CursorShape: Integer;\r
3337             var Stop: Boolean ): Boolean of object;\r
3338   {* Event, called during dragging operation (it is initiated\r
3339      with method Drag, where callback function of type TOnDrag is\r
3340      passed as a parameter). Callback function receives Stop parameter True,\r
3341      when operation is finishing. Otherwise, it can set it to True to force\r
3342      finishing the operation (in such case, returning False means cancelling\r
3343      drag operation, True - successful drag and in this last case callback is\r
3344      no more called). During the operation, when input Stop value is False,\r
3345      callback function can control Cursor shape, and return True, if the operation\r
3346      can be finished successfully at the given ScrX, ScrY position.\r
3347      ScrX, ScrY are screen coordinates of the mouse cursor. }\r
3349 //[Create Window STRUCTURES]\r
3350   TCreateParams = packed record\r
3351   {* Record to pass it through CreateSubClass method. }\r
3352     Caption: PChar;\r
3353     Style: cardinal;\r
3354     ExStyle: cardinal;\r
3355     X, Y: Integer;\r
3356     Width, Height: Integer;\r
3357     WndParent: HWnd;\r
3358     Param: Pointer;\r
3359     WindowClass: TWndClass;\r
3360     WinClassName: array[0..63] of Char;\r
3361   end;\r
3363   TCreateWndParams = packed Record\r
3364     ExStyle: DWORD;\r
3365     WinClassName: PChar;\r
3366     Caption: PChar;\r
3367     Style: DWORD;\r
3368     X, Y, Width, Height: Integer;\r
3369     WndParent: HWnd;\r
3370     Menu: HMenu;\r
3371     Inst: THandle;\r
3372     Param: Pointer;\r
3373     WinClsNamBuf: array[ 0..63 ] of Char;\r
3374     WindowClass: TWndClass;\r
3375   end;\r
3378 //[COMMAND ACTIONS TYPE FOR DIFFERENT CONTROLS]\r
3379   PCommandActions = ^TCommandActions;\r
3380   TCommandActions = packed Record\r
3381     aClear: procedure( Sender: PControl );\r
3382     aAddText: procedure( Sender: PControl; const S: String );\r
3383     aClick, aEnter, aLeave: WORD; aChange: SmallInt; aSelChange: SmallInt;\r
3384     aGetCount, aSetCount, aGetItemLength, aGetItemText, aSetItemText,\r
3385     aGetItemData, aSetItemData: WORD;\r
3386     aAddItem, aDeleteItem, aInsertItem: WORD;\r
3387     aFindItem, aFindPartial: WORD;\r
3388     aItem2Pos, aPos2Item: BYTE;\r
3389     aGetSelCount, aGetSelected, aGetSelRange, aExGetSelRange, aGetCurrent,\r
3390     aSetSelected, aSetCurrent, aSetSelRange, aExSetSelRange,\r
3391     aGetSelection, aReplaceSel: WORD;\r
3392     aTextAlignLeft, aTextAlignRight, aTextAlignCenter: WORD;\r
3393     aTextAlignMask: Byte;\r
3394     aVertAlignCenter, aVertAlignTop, aVertAlignBottom: Byte;\r
3395     aDir, aSetLimit: Word; aSetImgList: Word;\r
3396     aAutoSzX, aAutoSzY: Word;\r
3397     aSetBkColor: Word;\r
3398     aItem2XY: Word;\r
3399   end;\r
3401 //[Align TYPES]\r
3402   TTextAlign = ( taLeft, taRight, taCenter );\r
3403   {* Text alignments available. }\r
3404   TRichTextAlign = ( raLeft, raRight, raCenter,\r
3405                  // all other are only set but can not be displayed:\r
3406                  raJustify, // displayed like raLeft (though stored normally)\r
3407                  raInterLetter, raScaled, raGlyphs, raSnapGrid );\r
3408   {* Text alignment styles, available for RichEdit control. }\r
3409   TVerticalAlign = ( vaCenter, vaTop, vaBottom );\r
3410   {* Vertical alignments available. }\r
3411   TControlAlign = ( caNone, caLeft, caTop, caRight, caBottom, caClient );\r
3412   {* Control alignments available. }\r
3414 //[BitBtn TYPES]\r
3415   TBitBtnOption = ( bboImageList,\r
3416                     bboNoBorder,\r
3417                     bboNoCaption,\r
3418                     bboFixed );\r
3419   {* Options available for NewBitBtn. }\r
3420   TBitBtnOptions = set of TBitBtnOption;\r
3421   {* Set of options, available for NewBitBtn. }\r
3422   TGlyphLayout = ( glyphLeft, glyphTop, glyphRight, glyphBottom, glyphOver );\r
3423   {* Layout of glyph (for NewBitBtn). Layout glyphOver means that text is\r
3424      drawn over glyph. }\r
3425   TOnBitBtnDraw = function( Sender: PControl; BtnState: Integer ): Boolean of object;\r
3426   {* Event type for TControl.OnBitBtnDraw event (which is called just before\r
3427      drawing the BitBtn). If handler returns True, there are no drawing occure.\r
3428      BtnState, passed to a handler, determines current button state and can\r
3429      be following: 0 - not pressed, 1 - pressed, 2 - disabled, 3 - focused.\r
3430      Value 4 is reserved for highlight state (then mouse is over it), but\r
3431      highlighting is provided only if property Flat is set to True (or one\r
3432      of events OnMouseEnter / OnMouseLeave is assigned to something). }\r
3434 //[ListView TYPES]\r
3435   TListViewStyle = ( lvsIcon, lvsSmallIcon, lvsList, lvsDetail, lvsDetailNoHeader );\r
3436   {* Styles of view for ListView control (see NewListVew). }\r
3438   TListViewItemStates = ( lvisFocus, lvisSelect, lvisBlend, lvisHighlight );\r
3439   TListViewItemState = Set of TListViewItemStates;\r
3440   TListViewOption = (\r
3441     lvoIconLeft,      // in lvsIcon, lvsSmallIcon plce icon left from text (rather then top)\r
3442     lvoAutoArrange,   // keep icons auto arranged in lvsIcon and lvsSmallIcon view\r
3443     lvoButton,        // icons look like buttons in lvsIcon view\r
3444     lvoEditLabel,     // allows edit labels inplace (first column #0 text)\r
3445     lvoNoLabelWrap,   // item text on a single line in lvsIcon view (by default, item text may wrap in lvsIcon view).\r
3446     lvoNoScroll,      // obvious\r
3447     lvoNoSortHeader,  // click on header button does not lead to sort items\r
3448     lvoHideSel,       // hide selection when not in focus\r
3449     lvoMultiselect,   // allow to select multiple items\r
3450     lvoSortAscending,\r
3451     lvoSortDescending,\r
3452       // extended styles (not documented in my Win32.hlp :( , got from VCL source:\r
3453     lvoGridLines,\r
3454     lvoSubItemImages,\r
3455     lvoCheckBoxes,\r
3456     lvoTrackSelect,\r
3457     lvoHeaderDragDrop,\r
3458     lvoRowSelect,\r
3459     lvoOneClickActivate,\r
3460     lvoTwoClickActivate,\r
3461     lvoFlatsb,\r
3462     lvoRegional,\r
3463     lvoInfoTip,\r
3464     lvoUnderlineHot,\r
3465     lvoMultiWorkares,\r
3466       // virtual list view style:\r
3467     lvoOwnerData,\r
3468       // custom draw style:\r
3469     lvoOwnerDrawFixed\r
3470      );\r
3471   TListViewOptions = Set of TListViewOption;\r
3473   TOnEditLVItem = function( Sender: PControl; Idx, Col: Integer; NewText: PChar ): Boolean\r
3474                   of object;\r
3475   {* Event type for OnEndEditLVItem. Return True in handler to accept new text value. }\r
3476   TOnDeleteLVItem = procedure( Sender: PControl; Idx: Integer ) of object;\r
3477   {* Event type for OnDeleteLVItem event. }\r
3478   TOnLVData = procedure( Sender: PControl; Idx, SubItem: Integer;\r
3479               var Txt: String; var ImgIdx: Integer; var State: DWORD;\r
3480               var Store: Boolean ) of object;\r
3481   {* Event type for OnLVData event. Used to provide virtual list view control\r
3482      (i.e. having lvoOwnerData style) with actual data on request. Use parameter\r
3483      Store as a flag if control should store obtained data by itself or not. }\r
3484   {$IFNDEF _D2}\r
3485   {$IFNDEF _FPC}\r
3486   TOnLVDataW = procedure( Sender: PControl; Idx, SubItem: Integer;\r
3487               var Txt: WideString; var ImgIdx: Integer; var State: DWORD;\r
3488               var Store: Boolean ) of object;\r
3489   {* Event type for OnLVDataW event (the same as OnLVData, but for unicode verion\r
3490      of the control OnLVDataW allows to return WideString text in the event\r
3491      handler). Used to provide virtual list view control\r
3492      (i.e. having lvoOwnerData style) with actual data on request. Use parameter\r
3493      Store as a flag if control should store obtained data by itself or not. }\r
3494   {$ENDIF _FPC}\r
3495   {$ENDIF _D2}\r
3496   TOnCompareLVItems = function( Sender: PControl; Idx1, Idx2: Integer ): Integer\r
3497                     of object;\r
3498   {* Event type to compare two items of the list view (while sorting it). }\r
3499   TOnLVColumnClick = procedure( Sender: PControl; Idx: Integer ) of object;\r
3500   {* Event type for OnColumnClick event. }\r
3501   TOnLVStateChange = procedure( Sender: PControl; IdxFrom, IdxTo: Integer; OldState, NewState: DWORD )\r
3502                    of object;\r
3503   {* Event type for OnLVStateChange event, called in responce to select/unselect\r
3504      a single item or items range in list view control). }\r
3505   TOnLVDelete = procedure( Sender: PControl; Idx: Integer ) of object;\r
3506   {* Event type for OnLVDelete event, called when an item is been deleting. }\r
3508   TDrawActions = ( odaEntire, odaFocus, odaSelect );\r
3509   TDrawAction = Set of TDrawActions;\r
3510   TDrawStates = ( odsSelected, odsGrayed, odsDisabled, odsChecked, odsFocused,\r
3511                   odsDefault, odsHotlist, odsInactive,\r
3512                   odsNoAccel, odsNoFocusRect,\r
3513                   ods400reserved, ods800reserved,\r
3514                   odsComboboxEdit,\r
3515                   // specific for common controls:\r
3516                   odsMarked, odsIndeterminate );\r
3517   {* Possible draw states.\r
3518      |<br>odsSelected - The menu item's status is selected.\r
3519      |<br>odsGrayed - The item is to be grayed. This bit is used only in a menu.\r
3520      |<br>odsDisabled - The item is to be drawn as disabled.\r
3521      |<br>odsChecked - The menu item is to be checked. This bit is used only in\r
3522                      a menu.\r
3523      |<br>odsFocused - The item has the keyboard focus.\r
3524      |<br>odsDefault - The item is the default item.\r
3525      |<br>odsHotList - <b>Windows 98, Windows 2000:</b> The item is being\r
3526                      hot-tracked, that is, the item will be highlighted when\r
3527                      the mouse is on the item.\r
3528      |<br>odsInactive - <b>Windows 98, Windows 2000:</b> The item is inactive\r
3529                       and the window associated with the menu is inactive.\r
3530      |<br>odsNoAccel - <b>Windows 2000:</b> The control is drawn without the\r
3531                      keyboard accelerator cues.\r
3532      |<br>odsNoFocusRect - <b>Windows 2000:</b> The control is drawn without\r
3533                          focus indicator cues.\r
3534      |<br>odsComboboxEdit - The drawing takes place in the selection field\r
3535                           (edit control) of an owner-drawn combo box.\r
3536      |<br>odsMarked - for Common controls only. The item is marked. The meaning\r
3537                     of this is up to the implementation.\r
3538      |<br>odsIndeterminate - for Common Controls only. The item is in an\r
3539                            indeterminate state. }\r
3540   TDrawState = Set of TDrawStates;\r
3541   {* Set of possible draw states. }\r
3542   TOnDrawItem = function( Sender: PObj; DC: HDC; const Rect: TRect; ItemIdx: Integer;\r
3543                            DrawAction: TDrawAction; ItemState: TDrawState ): Boolean of object;\r
3544   {* Event type for OnDrawItem event (applied to list box, combo box, list view). }\r
3545   TOnMeasureItem = function( Sender: PObj; Idx: Integer ): Integer of object;\r
3546   {* Event type for OnMeasureItem event. The event handler must return height of list box\r
3547      item as a result. }\r
3548   TGetLVItemPart = ( lvipBounds, lvipIcon, lvipLabel, lvupIconAndLabel );\r
3549   {* }\r
3550   TWherePosLVItem = ( lvwpOnIcon, lvwpOnLabel, lvwpOnStateIcon, lvwpOnColumn,\r
3551                   lvwpOnItem );\r
3552   {* }\r
3554   TOnLVCustomDraw = function( Sender: PControl; DC: HDC; Stage: DWORD;\r
3555                   ItemIdx, SubItemIdx: Integer; const Rect: TRect;\r
3556                   ItemState: TDrawState; var TextColor, BackColor: TColor )\r
3557                   : DWORD of object;\r
3558   {* Event type for OnLVCustomDraw event. }\r
3560 //[Paint TYPES]\r
3561   TOnPaint = procedure( Sender: PControl; DC: HDC ) of object;\r
3563   TGradientStyle = ( gsVertical, gsHorizontal, gsRectangle, gsElliptic, gsRombic );\r
3564   {* Gradient fill styles. See also TGradientLayout. }\r
3565   TGradientLayout = ( glTopLeft, glTop, glTopRight,\r
3566                       glLeft, glCenter, glRight,\r
3567                       glBottomLeft, glBottom, glBottomRight );\r
3568   {* Position of starting line / point for gradient filling. Depending on\r
3569      TGradientStyle, means either position of first line of first rectangle\r
3570      (ellipse) to be expanded in a loop to fit entire gradient panel area. }\r
3572 //[Edit TYPES]\r
3573   TEditOption = ( eoNoHScroll, eoNoVScroll, eoLowercase, eoMultiline,\r
3574                   eoNoHideSel, eoOemConvert, eoPassword, eoReadonly,\r
3575                   eoUpperCase, eoWantReturn, eoWantTab, eoNumber );\r
3576   {* Available edit options.\r
3577   |<br> Please note, that eoWantTab option just removes TAB key from a list\r
3578   of keys available to tabulate from the edit control. To provide insertion\r
3579   of tabulating key, do so in TControl.OnChar event handler. Sorry for\r
3580   inconvenience, but this is because such behaviour is not must in all cases.\r
3581   See also TControl.EditTabChar property.  }\r
3582   TEditOptions = Set of TEditOption;\r
3583   {* Set of available edit options. }\r
3585   TRichFmtArea = ( raSelection, raWord, raAll );\r
3586   {* Characters formatting area for RichEdit. }\r
3587   TRETextFormat = ( reRTF, reText, rePlainRTF, reRTFNoObjs, rePlainRTFNoObjs,\r
3588                     reTextized );\r
3589   {* Available formats for transfer RichEdit text using property\r
3590      TControl.RE_Text.\r
3591      |<pre>\r
3592      reRTF - normal rich text (no transformations)\r
3593      reText - plain text only (without OLE objects)\r
3594      reTextized - plain text with text representation of OLE objects\r
3595      rePlainRTF - reRTF without language-specific keywords\r
3596      reRTFNoObjs - reRTF without OLE objects\r
3597      rePlainRTFNoObjs - rePlainRTF without OLE objects\r
3598      |</pre> }\r
3599   TRichUnderline = ( ruSingle, ruWord, ruDouble, ruDotted,\r
3600                  //all other - only for RichEditv3.0:\r
3601                  ruDash, ruDashDot, ruDashDotDot, ruWave, ruThick, ruHairLine );\r
3602   {* Rich text exteded underline styles (available only for RichEdit v2.0,\r
3603      and even for RichEdit v2.0 additional styles can not displayed - but\r
3604      ruDotted under Windows2000 is working). }\r
3605   TRichTextSizes = ( rtsNoUseCRLF, rtsNoPrecise, rtsClose, rtsBytes );\r
3606   {* Options to calculate size of rich text. Available only for RichEdit2.0\r
3607      or higher. }\r
3608   TRichTextSize = set of TRichTextSizes;\r
3609   {* Set of all available optioins to calculate rich text size using\r
3610      property TControl.RE_TextSize[ options ]. }\r
3611   TRichNumbering = ( rnNone, rnBullets, rnArabic, rnLLetter, rnULetter,\r
3612                 rnLRoman, rnURoman );\r
3613   {* Advanced numbering styles for paragraph (RichEdit).\r
3614      |<pre>\r
3615      rnNone     - no numbering\r
3616      rnBullets  - bullets only\r
3617      rnArabic   - 1, 2, 3, 4, ...\r
3618      rnLLetter  - a, b, c, d, ...\r
3619      rnULetter  - A, B, C, D, ...\r
3620      rnLRoman   - i, ii, iii, iv, ...\r
3621      rnURoman   - I, II, III, IV, ...\r
3622      rnNoNumber - do not show any numbers (but numbering is taking place).\r
3623      |</pre> }\r
3624   TRichNumBrackets = ( rnbRight, rnbBoth, rnbPeriod, rnbPlain, rnbNoNumber );\r
3625   {* Brackets around number:\r
3626      |<pre>\r
3627      rnbRight   - 1) 2) 3)     - this is default !\r
3628      rnbBoth    - (1) (2) (3)\r
3629      rnbPeriod  - 1. 2. 3.\r
3630      rnbPlain   - 1 2 3\r
3631      |</pre> }\r
3632   TBorderEdge = (beLeft, beTop, beRight, beBottom);\r
3633   {* Borders of rectangle. }\r
3635   TCharFormat = TCharFormat2;\r
3636   TParaFormat = TParaFormat2;\r
3638   TOnTestMouseOver = function( Sender: PControl ): Boolean of object;\r
3639   {* Event type for TControl.OnTestMouseOver event. The handler should\r
3640      return True, if it dectects, that mouse is over control. }\r
3642   TEdgeStyle = ( esRaised, esLowered, esNone );\r
3643   {* Edge styles (for panel - see NewPanel). }\r
3645 //[List TYPES]\r
3646   TListOption = ( loNoHideScroll, loNoExtendSel, loMultiColumn, loMultiSelect,\r
3647                   loNoIntegralHeight, loNoSel, loSort, loTabstops,\r
3648                   loNoStrings, loNoData, loOwnerDrawFixed, loOwnerDrawVariable );\r
3649   {* Options for ListBox (see NewListbox). }\r
3650   TListOptions = Set of TListOption;\r
3651   {* Set of available options for Listbox. }\r
3653   TComboOption = ( coReadOnly, coNoHScroll, coAlwaysVScroll, coLowerCase,\r
3654                    coNoIntegralHeight, coOemConvert, coSort, coUpperCase,\r
3655                    coOwnerDrawFixed, coOwnerDrawVariable, coSimple );\r
3656   {* Options for combobox. }\r
3657   TComboOptions = Set of TComboOption;\r
3658   {* Set of options available for combobox. }\r
3660 //[Progress TYPES]\r
3661   TProgressbarOption = ( pboVertical, pboSmooth );\r
3662   {* Options for progress bar. }\r
3663   TProgressbarOptions = set of TProgressbarOption;\r
3664   {* Set of options available for progress bar. }\r
3666 //[TreeView TYPES]\r
3667   TTreeViewOption = ( tvoNoLines, tvoLinesRoot, tvoNoButtons, tvoEditLabels, tvoHideSel,\r
3668                   tvoDragDrop, tvoNoTooltips, tvoCheckBoxes, tvoTrackSelect,\r
3669                   tvoSingleExpand, tvoInfoTip, tvoFullRowSelect, tvoNoScroll,\r
3670                   tvoNonEvenHeight );\r
3671   {* Tree view options. }\r
3672   TTreeViewOptions = set of TTreeViewOption;\r
3673   {* Set of tree view options. }\r
3675 //[TabControl TYPES]\r
3676   TTabControlOption = ( tcoButtons, tcoFixedWidth, tcoFocusTabs,\r
3677                         tcoIconLeft, tcoLabelLeft,\r
3678                         tcoMultiline, tcoMultiselect, tcoFitRows, tcoScrollOpposite,\r
3679                         tcoBottom, tcoVertical, tcoFlat, tcoHotTrack, tcoBorder,\r
3680                         tcoOwnerDrawFixed );\r
3681   {* Options, available for TabControl. }\r
3682   TTabControlOptions = set of TTabControlOption;\r
3683   {* Set of options, available for TAbControl during its creation (by\r
3684      NewTabControl function). }\r
3686 //[Toolbar TYPES]\r
3687   TToolbarOption = ( tboTextRight, tboTextBottom, tboFlat, tboTransparent,\r
3688                  tboWrapable, tboNoDivider, tbo3DBorder );\r
3689   {* Toolbar options. When tboFlat is set and toolbar is placed onto panel,\r
3690      set its property Transparent to TRUE to provide its correct view. }\r
3691   TToolbarOptions = Set of TToolbarOption;\r
3692   {* Set of toolbar options. }\r
3693   TOnToolbarButtonClick = procedure( Sender: PControl; BtnID: Integer ) of object;\r
3694   {* Special event type to handle separate toolbar buttons click events. }\r
3696   TDateTimePickerOption = ( dtpoTime, dtpoDateLong, dtpoUpDown, dtpoRightAlign,\r
3697     dtpoShowNone, dtpoParseInput );\r
3698   {* }\r
3699   TDateTimePickerOptions = set of TDateTimePickerOption;\r
3700   {* }\r
3701   TDTParseInputEvent = procedure(Sender: PControl; const UserString: string;\r
3702     var DateAndTime: TDateTime; var AllowChange: Boolean) of object;\r
3703   {* }\r
3704   TDateTimeRange = array[ 0..1 ] of TDateTime;\r
3705   {* }\r
3706   TDateTimePickerColor = ( dtpcBackground, dtpcMonthBk, dtpcText, dtpcTitleBk,\r
3707     dtpcTitleText, dtpcTrailingText );\r
3709 //[TOnDropFiles TYPE]\r
3710   TOnDropFiles = procedure( Sender: PControl; const FileList: String; const Pt: TPoint ) of object;\r
3711   {* An event type for OnDropFiles event. When the event is occur, FileList\r
3712      parameter contains a list of files dropped. File names in a list are\r
3713      separated with #13 character. This allows You to assign it to TStrList\r
3714      object using its property Text (for example):\r
3715      ! procedure TSomeObject.DropFiles( Sender: PControl; const FileList: String;\r
3716      !           const Pt: TPoint ); )\r
3717      ! var FList: PStrList;\r
3718      !     I: Integer;\r
3719      ! begin\r
3720      !   FList := NewStrList;\r
3721      !   FList.Text := FileList;\r
3722      !   for I := 0 to FList.Count-1 do\r
3723      !   begin\r
3724      !     // do something with FList.Items[ I ]\r
3725      !   end;\r
3726      !   FList.Free;\r
3727      ! end; }\r
3729 //[Scroll TYPES]\r
3730   TScrollerBar = ( sbHorizontal, sbVertical );\r
3731   TScrollerBars = set of TScrollerBar;\r
3733   TOnScroll = procedure( Sender: PControl; Bar: TScrollerBar; ScrollCmd: DWORD;\r
3734             ThumbPos: DWORD ) of object;\r
3736 //[TOnHelp EVENT TYPE]\r
3737   TOnHelp = procedure( var Sender: PControl; var Context: Integer; var Popup: Boolean )\r
3738             of object;\r
3740 //[ScrollBar TYPES]\r
3741   TOnSBBeforeScroll =\r
3742     procedure(\r
3743       Sender: PControl; OldPos, NewPos: Integer; Cmd: Word;\r
3744       var AllowChange: Boolean) of object;\r
3745   TOnSBScroll = procedure(Sender: PControl; Cmd: Word) of object;\r
3748   {$IFDEF USE_MHTOOLTIP}\r
3749   {$DEFINE pre_interface}\r
3750   {$I KOLMHToolTip}\r
3751   {$UNDEF pre_interface}\r
3752   {$ENDIF}\r
3754 { ----------------------------------------------------------------------\r
3756              TControl - object to implement any visual control\r
3758 ----------------------------------------------------------------------- }\r
3759 //[TControl DEFINITION]\r
3760   TControl = object( TObj )\r
3761   protected\r
3762     fSBMinMax: TPoint;\r
3763     fSBPageSize: Integer;\r
3764     fSBPosition: Integer;\r
3765     procedure SetSBMax(Value: Longint);\r
3766     procedure SetSBMin(Value: Longint);\r
3767     procedure SetSBPageSize(Value: Integer);\r
3768     procedure SetSBPosition(Value: Integer);\r
3769     procedure SetSBMinMax(const Value: TPoint);\r
3771     function GetDate: TDateTime;\r
3772     function GetTime: TDateTime;\r
3773     procedure SetDate(const Value: TDateTime);\r
3774     procedure SetTime(const Value: TDateTime);\r
3775   {*! TControl is the basic visual object of KOL. And now, all visual\r
3776      objects have the same type PControl, differing only in "constructor",\r
3777      which during creating of object adjusts it so it can play role of\r
3778      desired control. Idea of incapsulating of all visual objects having\r
3779      the most common set of properties, is belonging to Vladimir Kladov,\r
3780      (C) 2000.\r
3781      |<br>&nbsp;&nbsp;&nbsp;<b> Since all visual objects are represented\r
3782      in KOL by this single object type, not all methods, properties and\r
3783      events defined in TControl, are applicable to different visual objects.\r
3784      See also notes about certain control kinds, located together with its\r
3785      |<a href="kol_pas.htm#visual_objects_constructors">\r
3786      |constructing functions definitions</a></b>. }\r
3787   protected\r
3788     function GetHelpPath: String;\r
3789     procedure SetHelpPath(const Value: String);\r
3790     procedure SetOnQueryEndSession(const Value: TOnEventAccept);\r
3791     procedure SetOnMinMaxRestore(const Index: Integer; const Value: TOnEvent);\r
3792     procedure SetConstraint(const Index, Value: Integer);\r
3793     {$IFDEF F_P}\r
3794     function GetOnMinMaxRestore(const Index: Integer): TOnEvent;\r
3795     function GetConstraint(const Index: Integer): Integer;\r
3796     {$ENDIF F_P}\r
3797     procedure SetOnScroll(const Value: TOnScroll);\r
3798     function GetLVColalign(Idx: Integer): TTextAlign;\r
3799     procedure SetLVColalign(Idx: Integer; const Value: TTextAlign);\r
3801     procedure SetParent( Value: PControl );\r
3802     function GetLeft: Integer;\r
3803     procedure SetLeft( Value: Integer );\r
3804     function GetTop: Integer;\r
3805     procedure SetTop( Value: Integer );\r
3806     function GetWidth: Integer;\r
3807     procedure SetWidth( Value: Integer );\r
3808     function GetHeight: Integer;\r
3809     procedure SetHeight( Value: Integer );\r
3811     function GetPosition: TPoint;\r
3812     procedure Set_Position( Value: TPoint );\r
3814     function GetMembers(Idx: Integer): PControl;\r
3815     function GetFont: PGraphicTool;\r
3816     procedure FontChanged( Sender: PGraphicTool );\r
3817     function GetBrush: PGraphicTool;\r
3818     procedure BrushChanged( Sender: PGraphicTool );\r
3819     function GetClientHeight: Integer;\r
3820     function GetClientWidth: Integer;\r
3821     procedure SetClientHeight(const Value: Integer);\r
3822     procedure SetClientWidth(const Value: Integer);\r
3823     function GetHasBorder: Boolean;\r
3824     procedure SetHasBorder(const Value: Boolean);\r
3826     function GetHasCaption: Boolean;\r
3827     procedure SetHasCaption(const Value: Boolean);\r
3829     function GetCanResize: Boolean;\r
3830     procedure SetCanResize( const Value: Boolean );\r
3832     function GetStayOnTop: Boolean;\r
3833     procedure SetStayOnTop(const Value: Boolean);\r
3834     function GetChecked: Boolean;\r
3835     procedure Set_Checked(const Value: Boolean);\r
3837     function GetSelStart: Integer;\r
3838     procedure SetSelStart(const Value: Integer);\r
3839     function GetSelLength: Integer;\r
3840     procedure SetSelLength(const Value: Integer);\r
3842     function GetItems(Idx: Integer): String;\r
3843     procedure SetItems(Idx: Integer; const Value: String);\r
3845     function GetItemsCount: Integer;\r
3846     function GetItemSelected(ItemIdx: Integer): Boolean;\r
3847     procedure SetItemSelected(ItemIdx: Integer; const Value: Boolean);\r
3849     procedure SetCtl3D(const Value: Boolean);\r
3850     function GetCurIndex: Integer;\r
3851     procedure SetCurIndex(const Value: Integer);\r
3852     function GetTextAlign: TTextAlign;\r
3853     function GetVerticalAlign: TVerticalAlign;\r
3854     procedure SetTextAlign(const Value: TTextAlign);\r
3855     procedure SetVerticalAlign(const Value: TVerticalAlign);\r
3857     function GetCanvas: PCanvas;\r
3858     function Dc2Canvas( Sender: PCanvas ): HDC;\r
3859     procedure SetShadowDeep(const Value: Integer);\r
3860     procedure SetDoubleBuffered(const Value: Boolean);\r
3862     procedure SetStatusText(Index: Integer; Value: PChar);\r
3863     function GetStatusText( Index: Integer ): PChar;\r
3864     function GetStatusPanelX(Idx: Integer): Integer;\r
3865     procedure SetStatusPanelX(Idx: Integer; const Value: Integer);\r
3867     procedure SetTransparent(const Value: Boolean);\r
3868     function GetImgListIdx(const Index: Integer): PImageList;\r
3870     procedure SetImgListIdx(const Index: Integer; const Value: PImageList);\r
3871     function GetLVColText(Idx: Integer): String;\r
3872     procedure SetLVColText(Idx: Integer; const Value: String);\r
3873     {$IFNDEF _FPC}\r
3874     {$IFNDEF _D2}\r
3875     function GetLVColTextW(Idx: Integer): WideString;\r
3876     procedure SetLVColTextW(Idx: Integer; const Value: WideString);\r
3877     {$ENDIF _D2}\r
3878     {$ENDIF _FPC}\r
3879     function LVGetItemText(Idx, Col: Integer): String;\r
3880     procedure LVSetItemText(Idx, Col: Integer; const Value: String);\r
3881     {$IFNDEF _FPC}\r
3882     {$IFNDEF _D2}\r
3883     function LVGetItemTextW(Idx, Col: Integer): WideString;\r
3884     procedure LVSetItemTextW(Idx, Col: Integer; const Value: WideString);\r
3885     {$ENDIF _D2}\r
3886     {$ENDIF _FPC}\r
3887     procedure SetLVOptions(const Value: TListViewOptions);\r
3888     procedure SetLVStyle(const Value: TListViewStyle);\r
3889     function GetLVColEx(Idx: Integer; const Index: Integer): Integer;\r
3890     procedure SetLVColEx(Idx: Integer; const Index: Integer;\r
3891       const Value: Integer);\r
3893     function GetChildCount: Integer;\r
3895     function LVGetItemPos(Idx: Integer): TPoint;\r
3896     procedure LVSetItemPos(Idx: Integer; const Value: TPoint);\r
3897     procedure LVSetColorByIdx(const Index: Integer; const Value: TColor);\r
3898     {$IFDEF F_P}\r
3899     function LVGetColorByIdx(const Index: Integer): TColor;\r
3900     {$ENDIF F_P}\r
3901     function GetIntVal(const Index: Integer): Integer;\r
3902     procedure SetIntVal(const Index, Value: Integer);\r
3903     function GetItemVal(Item: Integer; const Index: Integer): Integer;\r
3904     procedure SetItemVal(Item: Integer; const Index, Value: Integer);\r
3905     function TBGetButtonVisible(BtnID: Integer): Boolean;\r
3906     procedure TBSetButtonVisible(BtnID: Integer; const Value: Boolean);\r
3908     function TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;\r
3909     procedure TBSetBtnStt(BtnID: Integer; const Index: Integer; const Value: Boolean);\r
3910     function TBGetButtonText(BtnID: Integer): String;\r
3911     function TBGetButtonRect(BtnID: Integer): TRect;\r
3913     function TBGetRows: Integer;\r
3914     procedure TBSetRows(const Value: Integer);\r
3915     procedure SetProgressColor(const Value: TColor);\r
3916     function TBGetBtnImgIdx(BtnID: Integer): Integer;\r
3917     procedure TBSetBtnImgIdx(BtnID: Integer; const Value: Integer);\r
3919     procedure TBSetButtonText(BtnID: Integer; const Value: String);\r
3921     function TBGetBtnWidth(BtnID: Integer): Integer;\r
3922     procedure TBSetBtnWidth(BtnID: Integer; const Value: Integer);\r
3923     procedure TBSetBtMinMaxWidth(const Idx: Integer; const Value: Integer);\r
3924     {$IFDEF F_P}\r
3925     function TBGetBtMinMaxWidth(const Idx: Integer): Integer;\r
3926     {$ENDIF F_P}\r
3927     procedure TBFreeTBevents;\r
3928     procedure Set_Align(const Value: TControlAlign);\r
3929     function GetSelection: String;\r
3930     procedure SetSelection(const Value: String);\r
3931     procedure SetTabOrder(const Value: Integer);\r
3932     function GetFocused: Boolean;\r
3933     procedure SetFocused(const Value: Boolean);\r
3934     function REGetFont: PGraphicTool;\r
3935     procedure RESetFont(Value: PGraphicTool);\r
3936     procedure RESetFontEx(const Index: Integer);\r
3937     function REGetFontEffects(const Index: Integer): Boolean;\r
3938     function REGetFontMask(const Index: Integer): Boolean;\r
3939     procedure RESetFontEffect(const Index: Integer; const Value: Boolean);\r
3940     function REGetFontAttr(const Index: Integer): Integer;\r
3941     procedure RESetFontAttr(const Index, Value: Integer);\r
3942     procedure RESetFontAttr1(const Index, Value: Integer);\r
3943     function REGetFontSizeValid: Boolean;\r
3944     function REGetCharformat: TCharFormat;\r
3945     procedure RESetCharFormat(const Value: TCharFormat);\r
3946     function REReadText(Format: TRETextFormat;\r
3947       SelectionOnly: Boolean): String;\r
3948     procedure REWriteText(Format: TRETextFormat; SelectionOnly: Boolean;\r
3949       const Value: String);\r
3950     function REGetFontName: String;\r
3951     procedure RESetFontName(const Value: String);\r
3952     function REGetParaFmt: TParaFormat;\r
3953     procedure RESetParaFmt(const Value: TParaFormat);\r
3954     function REGetNumbering: Boolean;\r
3955     function REGetParaAttr( const Index: Integer ): Integer;\r
3956     function REGetParaAttrValid( const Index: Integer ): Boolean;\r
3957     function REGetTabCount: Integer;\r
3958     function REGetTabs(Idx: Integer): Integer;\r
3959     function REGetTextAlign: TRichTextAlign;\r
3960     procedure RESetNumbering(const Value: Boolean);\r
3961     procedure RESetParaAttr(const Index, Value: Integer);\r
3962     procedure RESetTabCount(const Value: Integer);\r
3963     procedure RESetTabs(Idx: Integer; const Value: Integer);\r
3964     procedure RESetTextAlign(const Value: TRichTextAlign);\r
3965     function REGetStartIndentValid: Boolean;\r
3966     function REGetAutoURLDetect: Boolean;\r
3967     procedure RESetAutoURLDetect(const Value: Boolean);\r
3969     function GetMaxTextSize: DWORD;\r
3970     procedure SetMaxTextSize(const Value: DWORD);\r
3971     procedure SetOnResize(const Value: TOnEvent);\r
3973     procedure DoSelChange;\r
3975     function REGetUnderlineEx: TRichUnderline;\r
3976     procedure RESetUnderlineEx(const Value: TRichUnderline);\r
3978     function GetTextSize: Integer;\r
3979     function REGetTextSize(Units: TRichTextSize): Integer;\r
3981     function REGetNumStyle: TRichNumbering;\r
3982     procedure RESetNumStyle(const Value: TRichNumbering);\r
3983     function REGetNumBrackets: TRichNumBrackets;\r
3984     procedure RESetNumBrackets(const Value: TRichNumBrackets);\r
3985     function REGetNumTab: Integer;\r
3986     procedure RESetNumTab(const Value: Integer);\r
3987     function REGetNumStart: Integer;\r
3988     procedure RESetNumStart(const Value: Integer);\r
3989     function REGetSpacing(const Index: Integer): Integer;\r
3990     procedure RESetSpacing(const Index, Value: Integer);\r
3991     function REGetSpacingRule: Integer;\r
3992     procedure RESetSpacingRule(const Value: Integer);\r
3993     function REGetLevel: Integer;\r
3994     function REGetBorder(Side: TBorderEdge; const Index: Integer): Integer;\r
3995     procedure RESetBorder(Side: TBorderEdge; const Index: Integer;\r
3996       const Value: Integer);\r
3997     function REGetParaEffect(const Index: Integer): Boolean;\r
3998     procedure RESetParaEffect(const Index: Integer; const Value: Boolean);\r
3999     function REGetOverwite: Boolean;\r
4000     procedure RESetOverwrite(const Value: Boolean);\r
4001     procedure RESetOvrDisable(const Value: Boolean);\r
4002     function REGetTransparent: Boolean;\r
4003     procedure RESetTransparent(const Value: Boolean);\r
4004     procedure RESetOnURL(const Index: Integer; const Value: TOnEvent);\r
4005     {$IFDEF F_P}\r
4006     function REGetOnURL(const Index: Integer): TOnEvent;\r
4007     {$ENDIF F_P}\r
4008     function REGetLangOptions(const Index: Integer): Boolean;\r
4009     procedure RESetLangOptions(const Index: Integer; const Value: Boolean);\r
4010     function LVGetItemImgIdx(Idx: Integer): Integer;\r
4011     procedure LVSetItemImgIdx(Idx: Integer; const Value: Integer);\r
4012     procedure SetFlat(const Value: Boolean);\r
4013     procedure SetOnMouseEnter(const Value: TOnEvent);\r
4014     procedure SetOnMouseLeave(const Value: TOnEvent);\r
4015     procedure EdSetTransparent(const Value: Boolean);\r
4016     procedure SetOnTestMouseOver(const Value: TOnTestMouseOver);\r
4017     function GetPages(Idx: Integer): PControl;\r
4018     function TCGetItemText(Idx: Integer): String;\r
4019     procedure TCSetItemText(Idx: Integer; const Value: String);\r
4020     function TCGetItemImgIDx(Idx: Integer): Integer;\r
4021     procedure TCSetItemImgIdx(Idx: Integer; const Value: Integer);\r
4022     function TCGetItemRect(Idx: Integer): TRect;\r
4023     function TVGetItemIdx(const Index: Integer): THandle;\r
4024     procedure TVSetItemIdx(const Index: Integer; const Value: THandle);\r
4025     function TVGetItemNext(Item: THandle; const Index: Integer): THandle;\r
4026     function TVGetItemRect(Item: THandle; TextOnly: Boolean): TRect;\r
4027     function TVGetItemVisible(Item: THandle): Boolean;\r
4028     procedure TVSetITemVisible(Item: THandle; const Value: Boolean);\r
4029     function TVGetItemStateFlg(Item: THandle; const Index: Integer): Boolean;\r
4030     procedure TVSetItemStateFlg(Item: THandle; const Index: Integer;\r
4031       const Value: Boolean);\r
4032     function TVGetItemImage(Item: THandle; const Index: Integer): Integer;\r
4033     procedure TVSetItemImage(Item: THandle; const Index: Integer;\r
4034       const Value: Integer);\r
4035     function TVGetItemText(Item: THandle): String;\r
4036     procedure TVSetItemText(Item: THandle; const Value: String);\r
4037     {$IFNDEF _FPC}\r
4038     {$IFNDEF _D2}\r
4039     function TVGetItemTextW(Item: THandle): WideString;\r
4040     procedure TVSetItemTextW(Item: THandle; const Value: WideString);\r
4041     {$ENDIF _D2}\r
4042     {$ENDIF _FPC}\r
4043     function TV_GetItemHasChildren(Item: THandle): Boolean;\r
4044     procedure TV_SetItemHasChildren(Item: THandle; const Value: Boolean);\r
4045     function TV_GetItemChildCount(Item: THandle): Integer;\r
4046     function TVGetItemData(Item: THandle): Pointer;\r
4047     procedure TVSetItemData(Item: THandle; const Value: Pointer);\r
4049     function GetToBeVisible: Boolean;\r
4051     procedure SetAlphaBlend(const Value: Integer);\r
4052     procedure SetMaxProgress(const Index, Value: Integer);\r
4053     procedure SetDroppedWidth(const Value: Integer);\r
4054     function LVGetItemState(Idx: Integer): TListViewItemState;\r
4055     procedure LVSetItemState(Idx: Integer; const Value: TListViewItemState);\r
4056     function LVGetSttImgIdx(Idx: Integer): Integer;\r
4057     procedure LVSetSttImgIdx(Idx: Integer; const Value: Integer);\r
4058     function LVGetOvlImgIdx(Idx: Integer): Integer;\r
4059     procedure LVSetOvlImgIdx(Idx: Integer; const Value: Integer);\r
4060     function LVGetItemData(Idx: Integer): DWORD;\r
4061     procedure LVSetItemData(Idx: Integer; const Value: DWORD);\r
4062     function LVGetItemIndent(Idx: Integer): Integer;\r
4063     procedure LVSetItemIndent(Idx: Integer; const Value: Integer);\r
4064     procedure SetOnDeleteAllLVItems(const Value: TOnEvent);\r
4065     procedure SetOnDeleteLVItem(const Value: TOnDeleteLVItem);\r
4066     procedure SetOnEditLVItem(const Value: TOnEditLVItem);\r
4067     procedure SetOnLVData(const Value: TOnLVData);\r
4068     {$IFNDEF _FPC}\r
4069     {$IFNDEF _D2}\r
4070     procedure SetOnLVDataW(const Value: TOnLVDataW);\r
4071     {$ENDIF _D2}\r
4072     {$ENDIF _FPC}\r
4073     procedure SetOnColumnClick(const Value: TOnLVColumnClick);\r
4074     procedure SetOnDrawItem(const Value: TOnDrawItem);\r
4075     procedure SetOnMeasureItem(const Value: TOnMeasureItem);\r
4077     procedure SetItemsCount(const Value: Integer);\r
4079     function GetItemData(Idx: Integer): DWORD;\r
4080     procedure SetItemData(Idx: Integer; const Value: DWORD);\r
4081     function GetLVCurItem: Integer;\r
4082     procedure SetLVCurItem(const Value: Integer);\r
4083     procedure SetOnDropFiles(const Value: TOnDropFiles);\r
4084     procedure SetOnHide(const Value: TOnEvent);\r
4085     procedure SetOnShow(const Value: TOnEvent);\r
4086     procedure SetClientMargin(const Index, Value: Integer);\r
4087     {$IFDEF F_P}\r
4088     function GetClientMargin(const Index: Integer): Integer;\r
4089     {$ENDIF F_P}\r
4090     procedure SetOnPaint(const Value: TOnPaint);\r
4091     procedure SetOnEraseBkgnd(const Value: TOnPaint);\r
4092     procedure SetTVRightClickSelect(const Value: Boolean);\r
4093     procedure SetOnLVStateChange(const Value: TOnLVStateChange);\r
4094     procedure SetOnLVDelete(const Value: TOnLVDelete);\r
4095     procedure SetOnMove(const Value: TOnEvent);\r
4096     procedure SetColor1(const Value: TColor);\r
4097     procedure SetColor2(const Value: TColor);\r
4098     procedure SetGradientLayout(const Value: TGradientLayout);\r
4099     procedure SetGradientStyle(const Value: TGradientStyle);\r
4100     procedure SetDroppedDown(const Value: Boolean);\r
4101     function get_ClassName: String;\r
4102     procedure set_ClassName(const Value: String);\r
4103     procedure SetClsStyle( Value: DWord );\r
4105     procedure SetStyle( Value: DWord );\r
4106     procedure SetExStyle( Value: DWord );\r
4108     procedure SetCursor( Value: HCursor );\r
4110     procedure SetIcon( Value: HIcon );\r
4111     procedure SetMenu( Value: HMenu );\r
4112     function GetCaption: String;\r
4113     procedure SetCaption( const Value: String );\r
4115     procedure SetWindowState( Value: TWindowState );\r
4116     function GetWindowState: TWindowState;\r
4118     procedure ApplyFont2Wnd;\r
4119     procedure DoClick;\r
4121     function TBAddInsButtons( Idx: Integer; const Buttons: array of PChar; const BtnImgIdxArray: array\r
4122               of Integer ): Integer; stdcall;\r
4123     procedure SetBitBtnDrawMnemonic(const Value: Boolean);\r
4124     function GetBitBtnImgIdx: Integer;\r
4125     procedure SetBitBtnImgIdx(const Value: Integer);\r
4126     function GetBitBtnImageList: THandle;\r
4127     procedure SetBitBtnImageList(const Value: THandle);\r
4129     function GetModal: Boolean;\r
4130     {$IFDEF USE_SETMODALRESULT}\r
4131     procedure SetModalResult( const Value: Integer );\r
4132     {$ENDIF}\r
4134   protected\r
4135     fHandle: HWnd;\r
4136     fFocusHandle: HWnd;\r
4137     fClsStyle: DWord;\r
4138     fStyle: DWord;\r
4139     fExStyle: DWord;\r
4140     fCursor: HCursor;\r
4141     fCursorShared: Boolean;\r
4142     fIcon: HIcon;\r
4143     fIconShared: Boolean;\r
4144     fCaption: PChar; // it is now preferred to store Caption as PChar (null-\r
4145                      // terminated string), dynamically allocated in memory.\r
4146     fIgnoreWndCaption: Boolean;\r
4148     fWindowState: TWindowState;\r
4149     fShowAction: Integer;\r
4150     fCanvas: PCanvas;\r
4151     fDefWndProc: Pointer;\r
4152     fNCDestroyed: Boolean;\r
4154     FParent: PControl;\r
4155     //FTag: Integer;\r
4156     fEnabled: Boolean; // Caution!!! fVisible must follow fEnabled! ___\r
4157     fVisible: Boolean; //____________________________________________//\r
4158     fTabstop: Boolean;\r
4159     fTabOrder: Integer;\r
4160     fTextAlign: TTextAlign;\r
4161     fVerticalAlign: TVerticalAlign;\r
4162     fWordWrap: Boolean;\r
4163     fPreventResize: Boolean;\r
4164     fAlphaBlend: Integer;\r
4165     FDroppedWidth: Integer;\r
4167     fChildren: PList;\r
4168     {* List of children. }\r
4169     fMDIClient: PControl;\r
4170     {* MDI client window control }\r
4171     fPass2DefProc: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
4172     {* MDI children list }\r
4173     fMDIChildren: PList;\r
4174     {* List of MDI children. It is filled for MDI client window. }\r
4175     fWndFunc: Pointer;\r
4176     {* Initially pointer to WndFunc. For MDI child window, points to DefMDIChildProc. }\r
4177     fExMsgProc: function( Applet: PControl; var Msg: TMsg ): Boolean;\r
4178     {* Additional message handler called directly from Applet.ProcessMessage.\r
4179        Used to call TranslateMDISysAccel API function for MDI application. }\r
4180     fMDIDestroying: Boolean;\r
4181     {* }\r
4183     fTmpBrush: HBrush;\r
4184     {* Brush handle to return in response to some color set messages.\r
4185        Intended for internal use instead of Brush.Color if possible\r
4186        to avoid using it. }\r
4187     fTmpBrushColorRGB: TColor;\r
4188     { }\r
4189     fMembersCount: Integer;\r
4190     {* Memebers count is first used in XCustomControl to separate\r
4191        some internal child controls from common XControl.Children\r
4192        and make it invisible among Children[]. }\r
4193     fDrawCtrl1st: PControl;\r
4194     {* Child control to draw it first, i.e. foreground of others. }\r
4195     FCreating: Boolean;\r
4196     {* True, when creating of object is in progress. }\r
4197     fDestroying: Boolean;\r
4198     {* True, when destroying of the window is started. Made protected to\r
4199        be accessible in descending classes. }\r
4200     fMenu: HMenu;\r
4201     {* Usually used to store handle of attached main menu, but sometimes\r
4202        is used to store control ID (for standard GUI controls only). }\r
4203     fMenuObj: PObj;\r
4204     {* PMenu pointer to TMenu object. Freed automatically with entire\r
4205        chain of menu objects attached to a control (or form). }\r
4206 {$IFNDEF NEW_MENU_ACCELL}\r
4207     fAccelTable: HAccel;\r
4208 {$ENDIF}\r
4209     {* Handle of accelerator table created by menu(s). }\r
4210     fImageList: PImageList;\r
4211     {* Pointer to first private image list. Control can own several image,\r
4212        lists, linked to a chain of image list objects. All these image lists\r
4213        are released automatically, when control is destroyed. }\r
4214     fCtlImageListSml: PImageList;\r
4215     {* ImageList object (with small icons 16x16) to use with a control (e.g.,\r
4216        with ListView control).\r
4217        If not set, but control has a list of image list objects, last added\r
4218        image list with small icons is used automatically. }\r
4219     fCtlImageListNormal: PImageList;\r
4220     {* ImageList object (with big icons 32x32) to use with a control.\r
4221        If not set, last added image list with big icons is used. }\r
4222     fCtlImgListState: PImageList;\r
4223     {* ImageList object to use as a state image list (for ListView control). }\r
4224     fIsApplet: Boolean;\r
4225     {* True, if the object represent application taskbar button. }\r
4226     fIsForm: Boolean;\r
4227     {* True, if the object is form. }\r
4228     fIsMDIChild: Boolean;\r
4229     {* TRUE, if the object is MDI child form. }\r
4230     fIsControl: Boolean;\r
4231     {* True, if it is a control on form. }\r
4232     fIsStaticControl: Boolean;\r
4233     {* True, if it is static control with a caption. (To prevent flickering\r
4234        it in DoubleBuffered mode. }\r
4235     fIsCommonControl: Boolean;\r
4236     {* True, if it is common control. }\r
4237     fChangedPosSz: Byte;\r
4238     {* Flags of changing left (1), top (2), width (4) or height (8) }\r
4239     fCannotDoubleBuf: Boolean;\r
4240     {* True, if cannot set DoubleBuffered to True (RichEdit). }\r
4241     fUpdRgn: HRgn;\r
4242     fCollectUpdRgn: HRGN;\r
4243     fEraseUpdRgn: Boolean;\r
4244     fPaintDC: HDC;\r
4245     fDblBufBmp: HBitmap;\r
4246     {* Memory bitmap, used for DoubleBuffered painting. }\r
4247     fDblBufW, fDblBufH: Integer;\r
4248     {* Dimensions of fDblBufBmp. }\r
4249     fDblBufPainting: Boolean;\r
4250     fLookTabKeys: TTabKeys;\r
4251     fNotUpdate: Boolean;\r
4252     fDynHandlers: PList;\r
4253     fColumn: Integer;\r
4254     FSupressTab: Boolean;\r
4255     fUpdateCount: Integer;\r
4256     fPaintLater: Boolean;\r
4257     fOnLeave: TOnEvent;\r
4258     fEditing: Boolean;\r
4259     fAutoPopupMenu: PObj;\r
4260     fHelpContext: Integer;\r
4262     // Order of following fields is important:\r
4263     //_______________________________________________________________________________________________\r
4264     fOnDynHandlers: TWindowFunc;                                                                   //\r
4265     fWndProcKeybd: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;         //\r
4266     fControlClick: procedure( Sender : PObj );                                                     //\r
4267     fControlClassName: PChar;                                                                      //\r
4268     fWindowed: Boolean;                                                                            //\r
4269     {* True, if control is windowed (or is a form). Now always True,                               //\r
4270        because KOL does not yet contain Graphic controls. }                                        //\r
4271     //                                                                                             //\r
4272     fCtlClsNameChg: Boolean;                                                                       //\r
4273     {* True, if control class name changed and memory is allocated to store it. }                  //\r
4274     fWndProcResizeFlicks: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;  //\r
4275     fGotoControl: function( Self_: PControl; Key: DWORD; CheckOnly: Boolean ): Boolean;            //\r
4276     fCtl3Dchild: Boolean;                                                                          //\r
4277     fCtl3D: Boolean;                                                                               //\r
4278     fTextColor: TColor;                                                                            //\r
4279     {* Color of text. Used instead of fFont.Color internally to                                    //\r
4280        avoid usage of Font object if user is not accessing and changing it. }                      //\r
4281     fFont: PGraphicTool;                                                                           //\r
4282     fColor: TColor;                                                                                //\r
4283     {* Color of control background. }                                                              //\r
4284     fBrush: PGraphicTool;                                                                          //\r
4285     fMargin: Integer;                                                                              //\r
4286     fBoundsRect: TRect;                                                                            //\r
4287     fClientTop, fClientBottom, fClientLeft, fClientRight: Integer;                                 //\r
4288     {* Store adjustment factor of ClientRect for some 'idiosincrasies' windows,                    //\r
4289        such as Groupbox or Tabcontrol. }                                                           //\r
4290     //_____________________________________________________________________________________________//\r
4291     // this is the end of fiels set, which order is important\r
4293     fDoubleBuffered: Boolean;                                                                      //\r
4294     fTransparent: Boolean;                                                                         //\r
4296     fOnMessage: TOnMessage;\r
4297     fOldOnMessage: TOnMessage;\r
4299     fOnClick: TOnEvent;\r
4300     fRightClick: Boolean;\r
4301     fCurrentControl: PControl;\r
4302     fCreateVisible, fCreateHidden: Boolean;\r
4303     fRadio1st, fRadioLast : THandle;\r
4304     fDropDownProc: procedure( Sender : PObj );\r
4305     fDropped: Boolean;\r
4306     fCurIdxAtDrop: Integer;\r
4307     fPrevWndProc: Pointer;\r
4308     fClickDisabled: Byte;\r
4309     fCurItem, fCurIndex: Integer;\r
4310     FOnScroll: TOnScroll;\r
4311     FScrollLineDist: array[ 0..1 ] of Integer;\r
4313     fDefaultBtn: Boolean;\r
4314     fCancelBtn: Boolean;\r
4315     fDefaultBtnCtl: PControl;\r
4316     fCancelBtnCtl: PControl;\r
4317     fAllBtnReturnClick: Boolean;\r
4318     fIgnoreDefault: Boolean;\r
4320     fOnMouseDown: TOnMouse; // CAUTION!!! Order of mouse event handlers is important. ____\r
4321     fOnMouseUp: TOnMouse;                                                               //\r
4322     fOnMouseMove: TOnMouse;                                                             //\r
4323     fOnMouseDblClk: TOnMouse;                                                           //\r
4324     fOnMouseWheel: TOnMouse;     //_____________________________________________________//\r
4326     fOldDefWndProc: Pointer;\r
4328     fOnChange: TOnEvent;\r
4329     fOnEnter: TOnEvent;\r
4331     FOnLVCustomDraw: TOnLVCustomDraw;\r
4332     FOnSBBeforeScroll: TOnSBBeforeScroll;\r
4333     FOnSBScroll: TOnSBScroll;\r
4334   protected\r
4335     procedure SetOnLVCustomDraw(const Value: TOnLVCustomDraw);\r
4336   public\r
4337     fCommandActions: TCommandActions;\r
4338   protected\r
4339     fOnChar: TOnChar;\r
4340     fOnKeyUp: TOnKey;\r
4341     fOnKeyDown: TOnKey;\r
4343     fOnPaint: TOnPaint;\r
4345     FMaxWidth: Integer;\r
4346     FMinWidth: Integer;\r
4347     FMaxHeight: Integer;\r
4348     FMinHeight: Integer;\r
4349     fShadowDeep: Integer;\r
4350     fStatusCtl: PControl;\r
4351     fStatusWnd: HWnd;\r
4352     fStatusTxt: PChar;\r
4353     fColor1: TColor;\r
4354     fColor2: TColor;\r
4355     fLVColCount: Integer;\r
4356     fLVOptions: TListViewOptions;\r
4357     fLVStyle: TListViewStyle;\r
4358     fOnEditLVITem: TOnEditLVItem;\r
4359     fLVTextBkColor: TColor;\r
4360     fLVItemHeight: Integer;\r
4362     fOnDropDown: TOnEvent;\r
4363     fOnCloseUp: TOnEvent;\r
4365     fModalResult: Integer;\r
4366     \r
4367     fModal: Integer;\r
4368     fModalForm: PControl;\r
4370     FAlign: TControlAlign;\r
4371     fNotUseAlign: Boolean;\r
4372     fDragCallback: TOnDrag;\r
4373     fDragging: Boolean;\r
4374     fDragStartPos: TPoint;\r
4375     fMouseStartPos: TPoint;\r
4376     fSplitStartPos: TPoint;\r
4377     fSplitStartPos2: TPoint;\r
4378     fSplitStartSize: Integer;\r
4379     fSplitMinSize1, fSplitMinSize2: Integer;\r
4380     fOnSplit: TOnSplit;\r
4381     fSecondControl: PControl;\r
4382     fOnSelChange: TOnEvent;\r
4383     fTmpFont: PGraphicTool;\r
4385     fRECharFormatRec: TCharFormat2;\r
4386     fREError: Integer;\r
4387     fREStream: PStream;\r
4388     fREStrLoadLen: DWORD;\r
4389     fREParaFmtRec: TParaFormat2;\r
4390     FOnResize: TOnEvent;\r
4391     fOnProgress: TOnEvent;\r
4392     fCharFmtDeltaSz: Integer;\r
4393     fParaFmtDeltaSz: Integer;\r
4394     fREOvr: Boolean;\r
4395     fReOvrDisable: Boolean;\r
4396     fOnREInsModeChg: TOnEvent;\r
4397     fREScrolling: Boolean;\r
4398     fUpdCount: Integer;\r
4399     fOnREOverURL: TOnEvent;\r
4400     fOnREURLClick: TOnEvent;\r
4401     fRECharArea: TRichFmtArea;\r
4402     fBitBtnOptions : TBitBtnOptions;\r
4403     fGlyphLayout : TGlyphLayout;\r
4404     fGlyphBitmap : HBitmap;\r
4405     fGlyphCount : Integer;\r
4406     fGlyphWidth, fGlyphHeight: Integer;\r
4407     fOnBitBtnDraw: TOnBitBtnDraw;\r
4408     fFlat: Boolean;\r
4409     fSizeRedraw: Boolean; {YS}\r
4411     fOnMouseLeave: TOnEvent;\r
4412     fOnMouseEnter: TOnEvent;\r
4413     fOnTestMouseOver: TOnTestMouseOver;\r
4415     fMouseInControl: Boolean;\r
4416     fRepeatInterval: Integer;\r
4417     fChecked: Boolean;\r
4418     fPrevFocusWnd: HWnd;\r
4420     fOnTVBeginDrag: TOnTVBeginDrag;\r
4421     fOnTVBeginEdit: TOnTVBeginEdit;\r
4422     fOnTVEndEdit: TOnTVEndEdit;\r
4423     fOnTVExpanded: TOnTVExpanded;\r
4424     fOnTVExpanding: TOnTVExpanding;\r
4425     fOnTVDelete: TOnTVDelete;\r
4427     fOnDeleteLVItem: TOnDeleteLVItem;\r
4428     fOnDeleteAllLVItems: TOnEvent;\r
4429     fOnLVData: TOnLVData;\r
4430     {$IFNDEF _FPC}\r
4431     {$IFNDEF _D2}\r
4432     fOnLVDataW: TOnLVDataW;\r
4433     {$ENDIF _D2}\r
4434     {$ENDIF _FPC}\r
4435     fOnCompareLVItems: TOnCompareLVItems;\r
4436     fOnColumnClick: TOnLVColumnClick;\r
4437     fOnDrawItem: TOnDrawItem;\r
4438     fOnMeasureItem: TOnMeasureItem;\r
4439     fREUrl: String;\r
4440     FMinimizeWnd: PControl;\r
4441     FFixWidth: Integer;\r
4442     FFixHeight: Integer;\r
4443     FOnDropFiles: TOnDropFiles;\r
4444     FOnHide: TOnEvent;\r
4445     FOnShow: TOnEvent;\r
4446     fOnEraseBkgnd: TOnPaint;\r
4447     fCustomData: Pointer;\r
4448     fCustomObj: PObj;\r
4449     fOnTVSelChanging: TOnTVSelChanging;\r
4451     fOnClose: TOnEventAccept;\r
4452     fOnQueryEndSession: TOnEventAccept;\r
4453     fCloseQueryReason: TCloseQueryReason;\r
4455     //----- order of following 3 events important: //\r
4456     fOnMinimize: TOnEvent;                         //\r
4457     fOnMaximize: TOnEvent;                         //\r
4458     fOnRestore: TOnEvent;                          //\r
4459     //---------------------------------------------//\r
4461     //fCreateParamsExt: procedure( Self_: PControl; var Params: TCreateParams );\r
4462     fCreateWndExt: procedure( Sender: PControl );\r
4464     fTBttCmd: PList;\r
4465     fTBttTxt: PStrList;\r
4466     fTBevents: PList; // events for TBAssignEvents\r
4467     fTBBtnImgWidth: Integer; // custom toolbar bitmap width\r
4468     FTBBtMinWidth: Integer;\r
4469     FTBBtMaxWidth: Integer;\r
4470     fGradientStyle: TGradientStyle;\r
4471     fGradientLayout: TGradientLayout;\r
4472     fVisibleWoParent: Boolean;\r
4475     fTVRightClickSelect: Boolean;\r
4476     FOnMove: TOnEvent;\r
4477     FOnLVStateChange: TOnLVStateChange;\r
4478     FOnLVDelete: TOnLVDelete;\r
4479     fAutoSize: procedure( Self_: PControl );\r
4480     fIsButton: Boolean;\r
4481     fSizeGrip: Boolean;\r
4482     fNotAvailable: Boolean;\r
4483     FPressedMnemonic: DWORD;\r
4484     FBitBtnDrawMnemonic: Boolean;\r
4485     FBitBtnGetCaption: function( Self_: PControl; const S: String ): String;\r
4486     FBitBtnExtDraw: procedure( Self_: PControl; DC: HDC; X, Y: Integer; const R: TRect;\r
4487                     const CapText, CapTxtOrig: String; Color: TColor );\r
4488     FTextShiftX, FTextShiftY: Integer;\r
4489     fNotifyChild: procedure( Self_, Child: PControl );\r
4490     fScrollChildren: procedure( Self_: PControl );\r
4491     fOnHelp: TOnHelp;\r
4493     FOnDTPUserString: TDTParseInputEvent;\r
4495     {$IFDEF USE_MHTOOLTIP}\r
4496     {$DEFINE var}\r
4497     {$I KOLMHToolTip}\r
4498     {$UNDEF var}\r
4500     {$DEFINE function}\r
4501     {$I KOLMHToolTip}\r
4502     {$UNDEF function}\r
4503     {$ENDIF}\r
4505     procedure Init; {-}virtual;{+}{++}(*override;*){--}\r
4506     {* }\r
4507     procedure InitParented( AParent: PControl ); virtual;\r
4508     {* Initialization of visual object. }\r
4509     procedure DestroyChildren;\r
4510     {* Destroys children. Is called in destructor, and can be\r
4511        called in descending classes as earlier as needed to\r
4512        prevent problems of too late destroying of visuals. }\r
4514     function GetParentWnd( NeedHandle: Boolean ): HWnd;\r
4515     {* Returns handle of parent window. }\r
4516     function GetParentWindow: HWnd;\r
4517     {* }\r
4518     procedure SetEnabled( Value: Boolean );\r
4519     {* Changes Enabled property value. Overriden here to change enabling\r
4520        status of a window. }\r
4521     function GetEnabled: Boolean;\r
4522     {* Returns True, if Enabled. Overriden here to obtain real window\r
4523        state. }\r
4524     procedure SetVisible( Value: Boolean );\r
4525     {* Sets Visible property value. Overriden here to change visibility\r
4526        of correspondent window. }\r
4527     procedure Set_Visible( Value: Boolean );\r
4528     {* }\r
4529     function GetVisible: Boolean;\r
4530     {* Returns True, if correspondent window is Visible. Overriden\r
4531        to get visibility of real window, not just value stored in object. }\r
4532     function Get_Visible: Boolean;\r
4533     {* Returns True, if correspondent window is Visible, for forms and applet,\r
4534        or if fVisible flag is set, for controls. }\r
4535     procedure SetCtlColor( Value: TColor );\r
4536     {* Sets TControl's Color property value. }\r
4537     procedure SetBoundsRect( const Value: TRect );\r
4538     {* Sets BoudsRect property value. }\r
4539     function GetBoundsRect: TRect;\r
4540     {* Returns bounding rectangle. }\r
4541     function GetIcon: HIcon;\r
4542     {* Returns Icon property. By default, if it is not set,\r
4543        returns Icon property of an Applet. }\r
4545     procedure CreateSubclass( var Params: TCreateParams; ControlClassName: PChar );\r
4546     {* Can be used in descending classes to subclass window with given\r
4547        standard Windows ControlClassName - must be called after\r
4548        creating Params but before CreateWindow. Usually it is called\r
4549        in overriden method CreateParams after calling of the inherited one. }\r
4551     function UpdateWndStyles: PControl;\r
4552     {* Updates fStyle, fExStyle, fClsStyle from window handle }\r
4553     procedure SetOnChar(const Value: TOnChar);\r
4554     {* }\r
4555     procedure SetOnKeyDown(const Value: TOnKey);\r
4557     {* }\r
4558     procedure SetOnKeyUp(const Value: TOnKey);\r
4559     {* }\r
4560     procedure SetMouseDown(const Value: TOnMouse);\r
4561     {* }\r
4562     procedure SetMouseMove(const Value: TOnMouse);\r
4563     {* }\r
4564     procedure SetMouseUp(const Value: TOnMouse);\r
4565     {* }\r
4566     procedure SetMouseWheel(const Value: TOnMouse);\r
4567     {* }\r
4568     procedure SetMouseDblClk(const Value: TOnMouse);\r
4569     {* }\r
4570     procedure SetHelpContext( Value: Integer );\r
4571     {* }\r
4572     procedure SetOnTVDelete( const Value: TOnTVDelete );\r
4573     {* }\r
4574     procedure SetDefaultBtn(const Index: Integer; const Value: Boolean);\r
4575     {$IFDEF F_P}\r
4576     function GetDefaultBtn(const Index: Integer): Boolean;\r
4577     {$ENDIF F_P}\r
4578     function DefaultBtnProc( var Msg: TMsg; var Rslt: Integer ): Boolean;\r
4579     {* }\r
4581     procedure SetDateTime( Value: TDateTime );\r
4582     function GetDateTime: TDateTime;\r
4583     procedure SetDateTimeRange( Value: TDateTimeRange );\r
4584     function GetDateTimeRange: TDateTimeRange;\r
4585     procedure SetDateTimePickerColor( Index: TDateTimePickerColor; Value: TColor );\r
4586     function GetDateTimePickerColor( Index: TDateTimePickerColor ): TColor;\r
4587     procedure SetDateTimeFormat( const Value: String );\r
4589   public\r
4590     constructor CreateParented( AParent: PControl );\r
4591     {* Creates new instance of TControl object, calling InitParented }\r
4592     //FormPointer_DoNotUseItPlease_ItIsUsedByMCK: Pointer;\r
4593     { ^ no more needed }\r
4594     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
4595     {* Destroyes object. First of all, destructors for all children\r
4596        are called. }\r
4598     function GetWindowHandle: HWnd;\r
4599     {* Returns window handle. If window is not yet created,\r
4600        method CreateWindow is called. }\r
4601     procedure CreateChildWindows;\r
4602     {* Enumerates all children recursively and calls CreateWindow for all\r
4603        of these. }\r
4604     property Parent: PControl read fParent write SetParent;\r
4605     {* Parent of TParent object. Also must be of TParent type or derived from TParent. }\r
4606     //property Tag: Integer read FTag write FTag; //--------- moved to TObj --------\r
4607     {* User-defined pointer, which can contain any data or reference to\r
4608        anywhere in memory (when used as a pointer).\r
4609     }\r
4610     function ChildIndex( Child: PControl ): Integer;\r
4611     {* Returns index of given child. }\r
4612     procedure MoveChild( Child: PControl; NewIdx: Integer );\r
4613     {* Moves given Child into new position. }\r
4615     property Enabled: Boolean read GetEnabled write SetEnabled;\r
4616     {* Enabled usually used to decide if control can get keyboard focus\r
4617        or been clicked by mouse. }\r
4618     procedure EnableChildren( Enable, Recursive: Boolean );\r
4619     {* Enables (Enable = TRUE) or disables (Enable = FALSE) all the children\r
4620        of the control. If Recursive = TRUE then all the children of all the\r
4621        children are enabled or disabled recursively. }\r
4622     property Visible: Boolean read Get_Visible write SetVisible;\r
4623     {* Obvious. }\r
4624     property ToBeVisible: Boolean read GetToBeVisible;\r
4625     {* Returns True, if a control is supposed to be visible when its\r
4626        form is showing. Thus is, True is returned if either control\r
4627        is Visible or hidden, but marked with flag fCreateHidden. }\r
4628     property CreateVisible: Boolean read fCreateVisible write fCreateVisible;\r
4629     {* False by default. If You want your form to be created visible and\r
4630        flick due creation, set it to True. This does not affect size of\r
4631        executable anyway. }\r
4632     property Align: TControlAlign read FAlign write Set_Align;\r
4633     {* Align style of a control. If this property is not used in your\r
4634        application, there are no additional code added. Aligning of\r
4635        controls is made in KOL like in VCL. To align controls when\r
4636        initially create ones, use "transparent" function SetAlign\r
4637        ("transparent" means that it returns @Self as a result).\r
4638        |<br>\r
4639        Note, that it is better not to align combobox caClient, caLeft or\r
4640        caRight (better way is to place a panel with Border = 0 and\r
4641        EdgeStyle = esNone, align it as desired and to place a combobox on it\r
4642        aligning caTop or caBottom). Otherwise, big problems could be under\r
4643        Win9x/Me, and some delay could occur under any other systems.\r
4644        |<br> Do not attempt to align some kinds of controls (like combobox or\r
4645        toolbar) caLeft or caRight, this can cause infinite recursion in the\r
4646        application. }\r
4647     property BoundsRect: TRect read GetBoundsRect write SetBoundsRect;\r
4648     {* Bounding rectangle of the visual. Coordinates are relative\r
4649        to top left corner of parent's ClientRect, or to top left corner\r
4650        of screen (for TForm). }\r
4651     property Left: Integer read GetLeft write SetLeft;\r
4652     {* Left horizontal position. }\r
4653     property Top: Integer read GetTop write SetTop;\r
4654     {* Top vertical position. }\r
4655     property Width: Integer read GetWidth write SetWidth;\r
4656     {* Width of TVisual object. }\r
4657     property Height: Integer read GetHeight write SetHeight;\r
4658     {* Height of TVisual object. }\r
4660     property Position: TPoint read GetPosition write Set_Position;\r
4661     {* Represents top left position of the object. See also BoundsRect. }\r
4662     property MinWidth: Integer index 0\r
4663              {$IFDEF F_P}   read GetConstraint\r
4664              {$ELSE DELPHI} read FMinWidth\r
4665              {$ENDIF F_P/DELPHI} write SetConstraint;\r
4666     {* Minimal width constraint. }\r
4667     property MinHeight: Integer index 1\r
4668              {$IFDEF F_P}   read GetConstraint\r
4669              {$ELSE DELPHI} read FMinHeight\r
4670              {$ENDIF F_P/DELPHI} write SetConstraint;\r
4671     {* Minimal height constraint. }\r
4672     property MaxWidth: Integer index 2\r
4673              {$IFDEF F_P}   read GetConstraint\r
4674              {$ELSE DELPHI} read FMaxWidth\r
4675              {$ENDIF F_P/DELPHI} write SetConstraint;\r
4676     {* Maximal width constraint. }\r
4677     property MaxHeight: Integer index 3\r
4678              {$IFDEF F_P}   read GetConstraint\r
4679              {$ELSE DELPHI} read FMaxHeight\r
4680              {$ENDIF F_P/DELPHI} write SetConstraint;\r
4681     {* Maximal height constraint. }\r
4683     function ClientRect: TRect;\r
4684     {* Client rectangle of TVisual. Contrary to VCL, for some\r
4685        classes (e.g., derived from XCustomControl, can be relative\r
4686        not to itself, but to top left corner of the BoundsRect\r
4687        rectangle. }\r
4688     property ClientWidth: Integer read GetClientWidth write SetClientWidth;\r
4689     {* Obvious. Accessing this property, program forces window latent creation. }\r
4690     property ClientHeight: Integer read GetClientHeight write SetClientHeight;\r
4691     {* Obvious. Accessing this property, program forces window latent creation. }\r
4693     function ControlRect: TRect;\r
4694     {* Absolute bounding rectangle relatively to nearest\r
4695        Windowed parent client rectangle (at least to a form, but usually to\r
4696        a Parent).\r
4697        Useful while drawing on device context, provided by such\r
4698        Windowed parent. For form itself is the same as BoundsRect. }\r
4699     function ControlAtPos( X, Y: Integer; IgnoreDisabled: Boolean ): PControl;\r
4700     {* Searches TVisual at the given position (relatively to top left\r
4701        corner of the ClientRect). }\r
4703     procedure Invalidate;\r
4704     {* Invalidates rectangle, occupied by the visual (but only if Showing =\r
4705        True). }\r
4707     procedure InvalidateEx;\r
4708     {* Invalidates the window and all its children. }\r
4709     procedure InvalidateNC( Recursive: Boolean );\r
4710     {* Invalidates the window and all its children including non-client area. }\r
4711     procedure Update;\r
4712     {* Updates control's window and calls Update for all child controls. }\r
4713     procedure BeginUpdate;\r
4714     {* |<#treeview>\r
4715        |<#listview>\r
4716        |<#richedit>\r
4717        |<#memo>\r
4718        |<#listbox>\r
4719        Call this method to stop visual updates of the control until correspondent\r
4720        EndUpdate called (pairs BeginUpdate - EndUpdate can be nested). }\r
4721     procedure EndUpdate;\r
4722     {* See BeginUpdate. }\r
4724     property Windowed: Boolean read fWindowed;\r
4725     {* Constantly returns True, if object is windowed (i.e. owns\r
4726         correspondent window handle). Otherwise, returns False.\r
4727         |<br>\r
4728         By now, all the controls are windowed (there are no controls in KOL, which are\r
4729         emulating window, acually belonging to Parent - like TGraphicControl\r
4730         in VCL). }\r
4732     function HandleAllocated: Boolean;\r
4733     {* Returns True, if window handle is allocated. Has no sense for\r
4734        non-Windowed objects (but now, the KOL has no non-Windowed controls). }\r
4735     property MDIClient: PControl read fMDIClient;\r
4736     {* For MDI forms only: returns MDI client window control, containng all MDI\r
4737        children. Use this window to send specific messages to rule MDI children. }\r
4739     property ChildCount: Integer read GetChildCount;//GetChildCountWOMembers;\r
4740     {* Returns number of commonly accessed child objects (without\r
4741        MembersCount). }\r
4742     property Children[ Idx: Integer ]: PControl read GetMembers;\r
4743     {* Child items of TVisual object. Property is reintroduced here\r
4744        to separate access to always visible Children[] from restricted\r
4745        a bit Members[]. }\r
4746     property MembersCount: Integer read FMembersCount;\r
4747     {* Returns number of "internal" child objects, which are\r
4748        not accessible through common Children[] property. }\r
4749     property Members[ Idx: Integer ]: PControl read GetMembers;\r
4750     {* Members and children array of the object (first from 0 to\r
4751        MembersCount-1 are Members[], and Children[] are followed by\r
4752        them. Usually You do not need to use this list. Use instead\r
4753        Children[0..ChildCount] property, Members[] is intended for\r
4754        internal needs of XCL (and in KOL by now Members and Children\r
4755        actually are the same properties). }\r
4757     procedure PaintBackground( DC: HDC; Rect: PRect );\r
4758     {* Is called to paint background in given rectangle. This\r
4759        method is filling clipped area of the Rect rectangle with\r
4760        Color, but only if global event Global_OnPaintBkgnd is\r
4761        not assigned. If assigned, this one is called instead here.\r
4762        |<br>&nbsp;&nbsp;&nbsp;\r
4763        This method made public, so it can be called directly to\r
4764        fill some device context's rectangle. But remember, that\r
4765        independantly of Rect, top left corner of background piece\r
4766        will be located so, if drawing is occure into ControlRect\r
4767        rectangle. }\r
4768     property WindowedParent: PControl read fParent;\r
4769     {* Returns nearest windowed parent, the same as Parent. }\r
4771     function ParentForm: PControl;\r
4772     {* |<#form>\r
4773        Returns parent form for a control (of @Self for form itself. }\r
4774     property ActiveControl: PControl read fCurrentControl write fCurrentControl;\r
4775     {* }\r
4776     function Client2Screen( const P: TPoint ): TPoint;\r
4777     {* Converts the client coordinates of a specified point to screen coordinates. }\r
4778     function Screen2Client( const P: TPoint ): TPoint;\r
4779     {* Converts screen coordinates of a specified point to client coordinates. }\r
4780     function CreateWindow: Boolean; virtual;\r
4781     {* |<#form>\r
4782        Creates correspondent window object. Returns True if success (if\r
4783        window is already created, False is returned). If applied to a form,\r
4784        all child controls also allocates handles that time.\r
4785        |<br>&nbsp;&nbsp;&nbsp;\r
4786        Call this method to ensure, that a hanle is allocated for a form,\r
4787        an application button or a control. (It is not necessary to do so in\r
4788        the most cases, even if You plan to work with control's handle directly.\r
4789        But immediately after creating the object, if You want to pass its\r
4790        handle to API function, this can be helpful). }\r
4791     procedure Close;\r
4792     {* |<#appbutton>\r
4793        |<#form>\r
4794        Closes window. If a window is the main form, this closes application,\r
4795        terminating it. Also it is possible to call Close method for Applet\r
4796        window to stop application. }\r
4798     {$IFDEF USE_MHTOOLTIP}\r
4799     {$DEFINE public}\r
4800     {$I KOLMHToolTip}\r
4801     {$UNDEF public}\r
4802     {$ENDIF}\r
4804     property Handle: HWnd read fHandle; //GetHandle;\r
4805     {* Returns descriptor of system window object. If window is not yet\r
4806        created, 0 is returned. To allocate handle, call CreateWindow method. }\r
4808     property ParentWindow: HWnd read GetParentWindow;\r
4809     {* Returns handle of parent window (not TControl object, but system\r
4810        window object handle). }\r
4811     property ClsStyle: DWord read fClsStyle write SetClsStyle;\r
4812     {* Window class style. Available styles are:\r
4813        |<table border=0>\r
4814        |&L=<tr><td valign=top><font face=Fixedsys>%1</font></td><td>\r
4815        |&E=</td></tr>\r
4816        |&N=<br>&nbsp;&nbsp;&nbsp;\r
4817        <L CS_BYTEALIGNCLIENT> - Aligns the window's client area on the byte boundary\r
4818           (in the x direction) to enhance performance during\r
4819        drawing operations. <E>\r
4820        <L CS_BYTEALIGNWINDOW> - Aligns a window on a byte boundary (in the x\r
4821           direction). <E>\r
4822        <L CS_CLASSDC> - Allocates one device context to be shared by all\r
4823           windows in the class. <E>\r
4824        <L CS_DBLCLKS> - Sends double-click messages to the window\r
4825           procedure when the user double-clicks the mouse while the\r
4826           cursor is within a window belonging to the class. <E>\r
4827        <L CS_GLOBALCLASS> - Allows an application to create a window of\r
4828           the class regardless of the value of the hInstance parameter.\r
4829        <N> You can create a global class by creating\r
4830           the window class in a dynamic-link library (DLL) and listing the\r
4831           name of the DLL in the registry under specific keys. <E>\r
4832        <L CS_HREDRAW> - Redraws the entire window if a movement or\r
4833           size adjustment changes the width of the client area. <E>\r
4834        <L CS_NOCLOSE>  - Disables the Close command on the System menu. <E>\r
4835        <L CS_OWNDC> - Allocates a unique device context for each window\r
4836           in the class. <E>\r
4837        <L CS_PARENTDC> - Sets the clipping region of the child window to\r
4838           that of the parent window so that the child can draw on the parent. <E>\r
4839        <L CS_SAVEBITS> - Saves, as a bitmap, the portion of the screen\r
4840           image obscured by a window. Windows uses the saved bitmap to re-create\r
4841           the screen image when the window is removed. <E>\r
4842        <L CS_VREDRAW> - Redraws the entire window if a movement or size\r
4843           adjustment changes the height of the client area. <E>\r
4844        |</table> For more info, see Win32.hlp (keyword 'WndClass');\r
4845     }\r
4847     property Style: DWord read fStyle write SetStyle;\r
4848     {* Window styles. Available styles are:\r
4849        |<table border=0>\r
4850        <L WS_BORDER>    Creates a window that has a thin-line border. <E>\r
4851        <L WS_CAPTION>   Creates a window that has a title bar (includes the\r
4852           WS_BORDER style). <E>\r
4853        <L WS_CHILD>     Creates a child window. This style cannot be used with\r
4854           the WS_POPUP style. <E>\r
4855        <L WS_CHILDWINDOW>       Same as the WS_CHILD style. <E>\r
4856        <L WS_CLIPCHILDREN>      Excludes the area occupied by child windows\r
4857           when drawing occurs within the parent window. This style is used\r
4858           when creating the parent window. <E>\r
4859        <L WS_CLIPSIBLINGS>      Clips child windows relative to each other;\r
4860           that is, when a particular child window receives a WM_PAINT message,\r
4861           the WS_CLIPSIBLINGS style clips all other overlapping child windows\r
4862           out of the region of the child window to be updated. If\r
4863           WS_CLIPSIBLINGS is not specified and child windows overlap, it is\r
4864           possible, when drawing within the client area of a child window,\r
4865           to draw within the client area of a neighboring child window. <E>\r
4866        <L WS_DISABLED>  Creates a window that is initially disabled. A\r
4867           disabled window cannot receive input from the user. <E>\r
4868        <L WS_DLGFRAME>  Creates a window that has a border of a style\r
4869           typically used with dialog boxes. A window with this style cannot\r
4870           have a title bar. <E>\r
4871        <L WS_GROUP>     Specifies the first control of a group of controls.\r
4872           The group consists of this first control and all  controls defined\r
4873           after it, up to the next control with the WS_GROUP style.\r
4874           The first control in each group usually has the WS_TABSTOP\r
4875           style so that the user can move from group to group. The user\r
4876           can subsequently change the keyboard focus from one control in\r
4877           the group to the next control in the group by using the direction\r
4878           keys. <E>\r
4879        <L WS_HSCROLL>   Creates a window that has a horizontal scroll bar. <E>\r
4880        <L WS_ICONIC>    Creates a window that is initially minimized. Same as\r
4881           the WS_MINIMIZE style. <E>\r
4882        <L WS_MAXIMIZE>  Creates a window that is initially maximized. <E>\r
4883        <L WS_MAXIMIZEBOX>       Creates a window that has a Maximize button.\r
4884           Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU\r
4885           style must also be specified. <E>\r
4886        <L WS_MINIMIZE>  Creates a window that is initially minimized.\r
4887           Same as the WS_ICONIC style. <E>\r
4888        <L WS_MINIMIZEBOX>       Creates a window that has a Minimize button.\r
4889           Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU\r
4890           style must also be specified. <E>\r
4891        <L WS_OVERLAPPED>        Creates an overlapped window. An overlapped\r
4892           window has a title bar and a border. Same as the WS_TILED style. <E>\r
4893        <L WS_OVERLAPPEDWINDOW>  Creates an overlapped window with the\r
4894           WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX,\r
4895           and WS_MAXIMIZEBOX styles. Same as the WS_TILEDWINDOW style. <E>\r
4896        <L WS_POPUP>     Creates a pop-up window. This style cannot be used with\r
4897           the WS_CHILD style. <E>\r
4898        <L WS_POPUPWINDOW>       Creates a pop-up window with WS_BORDER,\r
4899           WS_POPUP, and WS_SYSMENU styles. The WS_CAPTION and WS_POPUPWINDOW\r
4900           styles must be combined to make the window menu visible. <E>\r
4901        <L WS_SIZEBOX>   Creates a window that has a sizing border. Same as the\r
4902           WS_THICKFRAME style. <E>\r
4903        <L WS_SYSMENU>   Creates a window that has a window-menu on its title\r
4904           bar. The WS_CAPTION style must also be specified. <E>\r
4905        <L WS_TABSTOP>   Specifies a control that can receive the keyboard focus\r
4906           when the user presses the TAB key. Pressing the TAB key changes\r
4907           the keyboard focus to the next control with the WS_TABSTOP style. <E>\r
4908        <L WS_THICKFRAME>        Creates a window that has a sizing border.\r
4909           Same as the WS_SIZEBOX style. <E>\r
4910        <L WS_TILED>     Creates an overlapped window. An overlapped window has\r
4911           a title bar and a border. Same as the WS_OVERLAPPED style. <E>\r
4912        <L WS_TILEDWINDOW>       Creates an overlapped window with the\r
4913           WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME,\r
4914           WS_MINIMIZEBOX, and WS_MAXIMIZEBOX styles. Same as the\r
4915           WS_OVERLAPPEDWINDOW style. <E>\r
4916        <L WS_VISIBLE>   Creates a window that is initially visible. <E>\r
4917        <L WS_VSCROLL>   Creates a window that has a vertical scroll bar. <E>\r
4918        |</table>\r
4919        See also Win32.hlp (topic CreateWindow).\r
4920     }\r
4921     property ExStyle: DWord read fExStyle write SetExStyle;\r
4922     {* Extra window styles. Available flags are following:\r
4923        |<table border=0>\r
4924        <L WS_EX_ACCEPTFILES>    Specifies that a window created with this style\r
4925           accepts drag-drop files. <E>\r
4926        <L WS_EX_APPWINDOW>      Forces a top-level window onto the taskbar\r
4927           when the window is minimized. <E>\r
4928        <L WS_EX_CLIENTEDGE>     Specifies that a window has a border with a\r
4929           sunken edge. <E>\r
4930        <L WS_EX_CONTEXTHELP>    Includes a question mark in the title bar of\r
4931           the window. When the user clicks the question mark, the cursor\r
4932           changes to a question mark with a pointer. If the user then clicks\r
4933           a child window, the child receives a WM_HELP message. The child\r
4934           window should pass the message to the parent window procedure,\r
4935           which should call the WinHelp function using the HELP_WM_HELP\r
4936           command. The Help application displays a pop-up window that\r
4937           typically contains help for the child window.WS_EX_CONTEXTHELP\r
4938           cannot be used with the WS_MAXIMIZEBOX or WS_MINIMIZEBOX styles. <E>\r
4939        <L WS_EX_CONTROLPARENT> Allows the user to navigate among the child\r
4940           windows of the window by using the TAB key. <E>\r
4941        <L WS_EX_DLGMODALFRAME> Creates a window that has a double border;\r
4942           the window can, optionally, be created with a title bar by\r
4943           specifying the WS_CAPTION style in the dwStyle parameter. <E>\r
4944        <L WS_EX_LEFT>   Window has generic "left-aligned" properties. This\r
4945           is the default. <E>\r
4946        <L WS_EX_LEFTSCROLLBAR> If the shell language is Hebrew, Arabic, or\r
4947           another language that supports reading order alignment, the\r
4948           vertical scroll bar (if present) is to the left of the client\r
4949           area. For other languages, the style is ignored and not treated\r
4950           as an error. <E>\r
4951        <L WS_EX_LTRREADING>     The window text is displayed using Left to\r
4952           Right reading-order properties. This is the default. <E>\r
4953        <L WS_EX_MDICHILD>       Creates an MDI child window. <E>\r
4954        <L WS_EX_NOPARENTNOTIFY> Specifies that a child window created\r
4955           with this style does not send the WM_PARENTNOTIFY message to its\r
4956           parent window when it is created or destroyed. <E>\r
4957        <L WS_EX_OVERLAPPEDWINDOW>       Combines the WS_EX_CLIENTEDGE and\r
4958           WS_EX_WINDOWEDGE styles. <E>\r
4959        <L WS_EX_PALETTEWINDOW> Combines the WS_EX_WINDOWEDGE,\r
4960           WS_EX_TOOLWINDOW, and WS_EX_TOPMOST styles. <E>\r
4961        <L WS_EX_RIGHT> Window has generic "right-aligned" properties.\r
4962           This depends on the window class. This style has an effect only\r
4963           if the shell language is Hebrew, Arabic, or another language that\r
4964           supports reading order alignment; otherwise, the style is\r
4965           ignored and not treated as an error. <E>\r
4966        <L WS_EX_RIGHTSCROLLBAR> Vertical scroll bar (if present) is to the\r
4967           right of the client area. This is the default. <E>\r
4968        <L WS_EX_RTLREADING>     If the shell language is Hebrew, Arabic, or\r
4969           another language that supports reading order alignment, the\r
4970           window text is displayed using Right to Left reading-order\r
4971           properties. For other languages, the style is ignored and not\r
4972           treated as an error. <E>\r
4973        <L WS_EX_STATICEDGE>     Creates a window with a three-dimensional\r
4974           border style intended to be used for items that do not accept\r
4975           user input. <E>\r
4976        <L WS_EX_TOOLWINDOW>     Creates a tool window; that is, a window\r
4977           intended to be used as a floating toolbar. A tool window has\r
4978           a title bar that is shorter than a normal title bar, and the\r
4979           window title is drawn using a smaller font. A tool window does\r
4980           not appear in the taskbar or in the dialog that appears when\r
4981           the user presses ALT+TAB. <E>\r
4982        <L WS_EX_TOPMOST> Specifies that a window created with this style\r
4983           should be placed above all non-topmost windows and should stay\r
4984           above them, even when the window is deactivated. To add or remove\r
4985           this style, use the SetWindowPos function. <E>\r
4986        <L WS_EX_TRANSPARENT>    Specifies that a window created with this\r
4987           style is to be transparent. That is, any windows that are\r
4988           beneath the window are not obscured by the window. A window\r
4989           created with this style receives WM_PAINT messages only after\r
4990           all sibling windows beneath it have been updated. <E>\r
4991        <L WS_EX_WINDOWEDGE>     Specifies that a window has a border with\r
4992           a raised edge. <E>\r
4993        |</table>\r
4994        See also Win32.hlp (topic CreateWindowEx).\r
4995     }\r
4997     property Cursor: HCursor read fCursor write SetCursor;\r
4998     {* Current cursor. For most of controls, sets initially to IDC_ARROW. See\r
4999        also ScreenCursor. }\r
5000     procedure CursorLoad( Inst: Integer; ResName: PChar );\r
5001     {* Loads Cursor from the resource. See also comments for Icon property. }\r
5003     property Icon: HIcon read GetIcon write SetIcon;\r
5004     {* |<#appbutton>\r
5005        |<#form>\r
5006        Icon. By default, icon of the Applet is used. To load icon from the\r
5007        resource, use IconLoad or IconLoadCursor method - this is more correct, because\r
5008        in such case a special flag is set to prevent attempts to destroy\r
5009        shared icon object in the destructor of the control. }\r
5011     procedure IconLoad( Inst: Integer; ResName: PChar );\r
5012     {* |<#appbutton>\r
5013        |<#form>\r
5014        See Icon property. }\r
5015     procedure IconLoadCursor( Inst: Integer; ResName: PChar );\r
5016     {* |<#appbutton>\r
5017        |<#form>\r
5018        Loads Icon from the cursor resource. See also Icon property. }\r
5021     property Menu: HMenu read fMenu write SetMenu;\r
5023     {* Menu (or ID of control - for standard GUI controls). }\r
5024     property HelpContext: Integer read fHelpContext write SetHelpContext;\r
5025     {* Help context. }\r
5026     function AssignHelpContext( Context: Integer ): PControl;\r
5027     {* Assigns HelpContext and returns @ Self (can be used in initialization\r
5028        of a control in a chain of "transparent" calls). }\r
5030     procedure CallHelp( Context: Integer; CtxCtl: PControl {; CtlID: Integer} );\r
5031     {* Method of a form or Applet. Call it to show help with the given context\r
5032        ID. If the Context = 0, help contents is displayed. By default,\r
5033        WinHelp is used. To allow using HtmlHelp, call AssignHtmlHelp global\r
5034        function. When WinHelp used, HelpPath variable can be assigned directly.\r
5035        If HelpPath variable is not assigned, application name\r
5036        (and path) is used, with extension replaced to '.hlp'. }\r
5038     property HelpPath: String read GetHelpPath write SetHelpPath;\r
5039     {* Property of a form or an Applet. Change it to provide custom path to\r
5040        WinHelp format help file. If HtmlHelp used, call global procedure\r
5041        AssignHtmlHelp instead. }\r
5043     property OnHelp: TOnHelp read fOnHelp write fOnHelp;\r
5044     {* An event of a form, it is called when F1 pressed or help topic requested\r
5045        by any other way. To prevent showing help, nullify Sender. Set Popup to\r
5046        TRUE to provide showing help in a pop-up window. It is also possible to\r
5047        change Context dynamically. }\r
5049     property Caption: String read GetCaption write SetCaption;\r
5050     {* |<#appbutton>\r
5051        |<#form>\r
5052        |<#button>\r
5053        |<#bitbtn>\r
5054        |<#label>\r
5055        |<#wwlabel>\r
5056        |<#3dlabel>\r
5057        Caption of a window. For standard Windows buttons, labels and so on\r
5058        not a caption of a window, but text of the window. }\r
5059     property Text: String read GetCaption write SetCaption;\r
5060     {* |<#edit>\r
5061        |<#memo>\r
5062        The same as Caption. To make more convenient with Edit controls. For\r
5063        Rich Edit control, use property RE_Text. }\r
5064     property SelStart: Integer read GetSelStart write SetSelStart;\r
5065     {* |<#edit>\r
5066        |<#memo>\r
5067        |<#richedit>\r
5068        |<#listbox>\r
5069        |<#combo>\r
5070        Start of selection (editbox - character position, listbox and combobox -\r
5071        index of [the first] selected item). }\r
5072     property SelLength: Integer read GetSelLength write SetSelLength;\r
5073     {* |<#edit>\r
5074        |<#memo>\r
5075        |<#richedit>\r
5076        |<#listbox>\r
5077        |<#listview>\r
5078        Length of selection (editbox - number of characters selected, multiline\r
5079        listbox - number of items selected). }\r
5081     property Selection: String read GetSelection write SetSelection;\r
5082     {* |<#edit>\r
5083        |<#memo>\r
5084        |<#richedit>\r
5085        Selected text (editbox, richedit) as string. Can be useful to replace\r
5086        selection. For rich edit, use RE_Text[ reText, TRUE ], if you want to\r
5087        read correctly characters from another locale then ANSI only. }\r
5088     procedure SelectAll;\r
5089     {* |<#edit>\r
5090        |<#memo>\r
5091        |<#richedit>\r
5092        Makes all the text in editbox or RichEdit, or all items in listbox\r
5093        selected. }\r
5095     procedure ReplaceSelection( const Value: String; aCanUndo: Boolean );\r
5096     {* |<#edit>\r
5097        |<#memo>\r
5098        |<#richedit>\r
5099        Replaces selection (in edit, RichEdit). Unlike assigning new value\r
5100        to Selection property, it is possible to specify, if operation can\r
5101        be undone. }\r
5103     procedure DeleteLines( FromLine, ToLine: Integer );\r
5104     {* |<#edit>\r
5105        |<#memo>\r
5106        |<#richedit>\r
5107        Deletes lines from FromLine to ToLine (inclusively, i.e. 0 to 0 deletes\r
5108        one line with index 0). Current selection is restored as possible. }\r
5109     property CurIndex: Integer read GetCurIndex write SetCurIndex;\r
5110     {* |<#listbox>\r
5111        |<#combo>\r
5112        |<#toolbar>\r
5113        Index of current item (for listbox, combobox) or button index pressed\r
5114        or dropped down (for toolbar button, and only in appropriate event\r
5115        handler call).\r
5116        |<br>\r
5117        You cannot use it to set or remove a selection in a multiple-selection\r
5118        list box, so you should set option loNoExtendSel to true.\r
5119        |<br>\r
5120        In OnClick event handler, CurIndex has not yet changed. Use OnSelChange\r
5121        to respond to selection changes. }\r
5123     property Count: Integer read GetItemsCount write SetItemsCount;\r
5124     {* |<#listbox>\r
5125        |<#combo>\r
5126        |<#listview>\r
5127        |<#treeview>\r
5128        |<#edit>\r
5129        |<#memo>\r
5130        |<#richedit>\r
5131        |<#toolbar>\r
5132        Number of items (listbox, combobox, listview) or lines (multiline\r
5133        editbox, richedit control) or buttons (toolbar). It is possible to\r
5134        assign a value to this property only for listbox control with loNoData\r
5135        style and for list view control with lvoOwnerData style (virtual list\r
5136        box and list view). }\r
5138     property Items[ Idx: Integer ]: String read GetItems write SetItems;\r
5139     {* |<#edit>\r
5140        |<#listbox>\r
5141        |<#combo>\r
5142        |<#memo>\r
5143        |<#richedit>\r
5144        Obvious. Used with editboxes, listbox, combobox. With list view, use\r
5145        property LVItems instead. }\r
5147     function Item2Pos( ItemIdx: Integer ): Integer;\r
5148     {* |<#edit>\r
5149        |<#memo>\r
5150        Only for edit controls: converts line index to character position. }\r
5151     function Pos2Item( Pos: Integer ): Integer;\r
5152     {* |<#edit>\r
5153        |<#memo>\r
5154        Only for edit controls: converts character position to line index. }\r
5156     function EditTabChar: PControl;\r
5157     {* |<#edit>\r
5158        |<#memo>\r
5159        Call this method (once) to provide insertion of tab character (code #9)\r
5160        when tab key is pressed on keyboard. }\r
5162     function IndexOf( const S: String ): Integer;\r
5163     {* |<#listbox>\r
5164        |<#combobox>\r
5165        |<#tabcontrol>\r
5166        Works for the most of control types, though some of those\r
5167        have its own methods to search given item. If a control is not\r
5168        list box or combobox, item is finding by enumerating all\r
5169        the Items one by one. See also SearchFor method. }\r
5170     function SearchFor( const S: String; StartAfter: Integer; Partial: Boolean ): Integer;\r
5171     {* |<#listbox>\r
5172        |<#combobox>\r
5173        |<#tabcontrol>\r
5174        Works for the most of control types, though some of those\r
5175        have its own methods to search given item. If a control is not\r
5176        list box or combobox, item is finding by enumerating all\r
5177        the Items one by one. See also IndexOf method. }\r
5180     property ItemSelected[ ItemIdx: Integer ]: Boolean read GetItemSelected write SetItemSelected;\r
5181     {* |<#edit>\r
5182        |<#memo>\r
5183        |<#listbox>\r
5184        |<#combo>\r
5185        Returns True, if a line (in editbox) or an item (in listbox, combobox) is\r
5186        selected.\r
5187        Can be set only for listboxes. For listboxes, which are not multiselect, and\r
5188        for combo lists, it is possible only to set to True, to change selection. }\r
5190     property ItemData[ Idx: Integer ]: DWORD read GetItemData write SetItemData;\r
5191     {* |<#listbox>\r
5192        |<#combo>\r
5193        Access to user-defined data, associated with the item of a list box and\r
5194        combo box. }\r
5195     property OnDropDown: TOnEvent read fOnDropDown write fOnDropDown;\r
5196     {* |<#combo>\r
5197        |<#toolbar>\r
5198        Is called when combobox is dropped down (or drop-down button of\r
5199        toolbar is pressed - see also OnTBDropDown). }\r
5200     property OnCloseUp: TOnEvent read fOnCloseUp write fOnCloseUp;\r
5201     {* |<#combo>\r
5202        Is called when combobox is closed up. When drop down list is closed\r
5203        because user pressed "Escape" key, previous selection is restored.\r
5204        To test if it is so, call GetKeyState( VK_ESCAPE ) and check, if\r
5205        negative value is returned (i.e. Escape key is pressed when event\r
5206        handler is calling). }\r
5207     property DroppedWidth: Integer read FDroppedWidth write SetDroppedWidth;\r
5208     {* |<#combo>\r
5209        Allows to change width of dropped down items list for combobox (only!)\r
5210        control. }\r
5211     property DroppedDown: Boolean read fDropped write SetDroppedDown;\r
5212     {* |<#combo>\r
5213        Dropped down state for combo box. Set it to TRUE or FALSE to change\r
5214        dropped down state. }\r
5215     procedure AddDirList( const Filemask: String; Attrs: DWORD );\r
5216     {* |<#listbox>\r
5217        |<#combo>\r
5218        Can be used only with listbox and combobox - to add directory list items,\r
5219        filtered by given Filemask (can contain wildcards) and Attrs. Following\r
5220        flags can be combined in Attrs:\r
5221        |<table border=0>\r
5222        |&L=<tr><td>%1</td><td>\r
5223        <L DDL_ARCHIVE> Include archived files. <E>\r
5224        <L DDL_DIRECTORY> Includes subdirectories. Subdirectory names are\r
5225           enclosed in square brackets ([ ]). <E>\r
5226        <L DDL_DRIVES> Includes drives. Drives are listed in the form [-x-],\r
5227           where x is the drive letter. <E>\r
5228        <L DDL_EXCLUSIVE> Includes only files with the specified attributes.\r
5229           By default, read-write files are listed even if DDL_READWRITE is\r
5230           not specified. Also, this flag needed to list directories only,\r
5231           etc. <E>\r
5232        <L DDL_HIDDEN> Includes hidden files. <E>\r
5233        <L DDL_READONLY> Includes read-only files. <E>\r
5234        <L DDL_READWRITE> Includes read-write files with no additional\r
5235           attributes. <E>\r
5236        <L DDL_SYSTEM> Includes system files. <E>\r
5237        </table>\r
5238        If the listbox is sorted, directory items will be sorted (alpabetically). }\r
5239     property OnBitBtnDraw: TOnBitBtnDraw read fOnBitBtnDraw write fOnBitBtnDraw;\r
5240     {* |<#bitbtn>\r
5241        Special event for BitBtn. Using it, it is possible to provide\r
5242        additional effects, such as highlighting button text (by changing\r
5243        its Font and other properties). If the handler returns True, it is\r
5244        supposed that it made all drawing and there are no further drawing\r
5245        occure. }\r
5246     property BitBtnDrawMnemonic: Boolean read FBitBtnDrawMnemonic write SetBitBtnDrawMnemonic;\r
5247     {* |<#bitbtn>\r
5248        Set this property to TRUE to provide correct drawing of bit btn control\r
5249        caption with '&' characters (to remove such characters, and underline\r
5250        follow ones). }\r
5251     property TextShiftX: Integer read fTextShiftX write fTextShiftX;\r
5252     {* |<#bitbtn>\r
5253        Horizontal shift for bitbtn text when the bitbtn is pressed. }\r
5254     property TextShiftY: Integer read fTextShiftY write fTextShiftY;\r
5255     {* |<#bitbtn>\r
5256        Vertical shift for bitbtn text when the bitbtn is pressed. }\r
5257     property BitBtnImgIdx: Integer read GetBitBtnImgIdx write SetBitBtnImgIdx;\r
5258     {* |<#bitbtn>\r
5259        BitBtn image index for the first image in list view, used as bitbtn\r
5260        image. It is used only in case when BitBtn is created with bboImageList\r
5261        option. }\r
5262     property BitBtnImgList: THandle read GetBitBtnImageList write SetBitBtnImageList;\r
5263     {* |<#bitbtn>\r
5264        BitBtn Image list. Assign image list handle to change it. }\r
5266     function SetButtonIcon( aIcon: HIcon ): PControl;\r
5267     {* |<#button>\r
5268        Sets up button icon image and changes its styles. Returns button itself. }\r
5269     function SetButtonBitmap( aBmp: HBitmap ): PControl;\r
5270     {* |<#button>\r
5271        Sets up button icon image and changes its styles. Returns button itself. }\r
5273     property OnMeasureItem: TOnMeasureItem read fOnMeasureItem write SetOnMeasureItem;\r
5274     {* |<#combo>\r
5275        |<#listbox>\r
5276        |<#listview>\r
5277        This event is called for owner-drawn controls, such as list box, combo box,\r
5278        list view with appropriate owner-drawn style. For fixed item height controls\r
5279        (list box with loOwnerDrawFixed style, combobox with coOwnerDrawFixed and\r
5280        list view with lvoOwnerDrawFixed option) this event is called once. For\r
5281        list box with loOwnerDrawVariable style and for combobox with coOwnerDrawVariable\r
5282        style this event is called for every item. }\r
5284     property DefaultBtn: Boolean index 13\r
5285              {$IFDEF F_P}   read GetDefaultBtn\r
5286              {$ELSE DELPHI} read fDefaultBtn\r
5287              {$ENDIF F_P/DELPHI} write SetDefaultBtn;\r
5288     {* |<#button>\r
5289        |<#bitbtn>\r
5290        Set this property to true to make control clicked when ENTER key is pressed.\r
5291        This property uses OnMessage event of the parent form, storing it into\r
5292        fOldOnMessage field and calling in chain. So, assign default button\r
5293        after setting OnMessage event for the form. }\r
5294     property CancelBtn: Boolean index 27\r
5295              {$IFDEF F_P}   read GetDefaultBtn\r
5296              {$ELSE DELPHI} read fCancelBtn\r
5297              {$ENDIF F_P/DELPHI} write SetDefaultBtn;\r
5298     {* |<#button>\r
5299        |<#bitbtn>\r
5300        Set this property to true to make control clicked when escape key is pressed.\r
5301        This property uses OnMessage event of the parent form, storing it into\r
5302        fOldOnMessage field and calling in chain. So, assign cancel button\r
5303        after setting OnMessage event for the form. }\r
5304     function AllBtnReturnClick: PControl;\r
5305     {* Call this method for a form or any its control to provide clicking\r
5306        a focused button when ENTER pressed. By default, a button can be clicked\r
5307        only by SPACE key from the keyboard, or by mouse. }\r
5308     property IgnoreDefault: Boolean read fIgnoreDefault write fIgnoreDefault;\r
5309     {* Change this property to TRUE to ignore default button reaction on\r
5310        press ENTER key when a focus is grabbed of the control. Default\r
5311        value is different for different controls. By default, DefaultBtn\r
5312        ignored in memo, richedit (even if read-only). }\r
5315     property Color: TColor read fColor write SetCtlColor;\r
5316     {* Property Color is one of the most common for all visual\r
5317        elements (like form, control etc.) Please note, that standard GUI button\r
5318        can not change its color and the most characteristics of the Font. Also,\r
5319        standard button can not become Transparent. Use bitbtn for such purposes.\r
5320        Also, changing Color property for some kinds of control has no effect (rich edit,\r
5321        list view, tree view, etc.). To solve this, use native (for such controls)\r
5322        color property, or call Perform method with appropriate message to set the\r
5323        background color. }\r
5324     property Font: PGraphicTool read GetFont;\r
5325     {* If the Font property is not accessed, correspondent TGraphicTool object\r
5326        is not created and its methods are not included into executable. Leaving\r
5327        properties Font and Brush untouched can economy executable size a lot. }\r
5328     property Brush: PGraphicTool read GetBrush;\r
5329     {* If not accessed, correspondent TGraphicTool object is not created\r
5330        and its methods are not referenced. See also note on Font property. }\r
5332     property Ctl3D: Boolean read fCtl3D write SetCtl3D;\r
5333     {* Inheritable from parent controls to child ones. }\r
5335     procedure Show;\r
5336     {* |<#appbutton>\r
5337        |<#form>\r
5338        Makes control visible and activates it. }\r
5339     function ShowModal: Integer;\r
5340     {* |<#form>\r
5341        Can be used only with a forms to show it modal. See also global function\r
5342        ShowMsgModal.\r
5343        |<br>\r
5344        To use a form as a modal, it is possible to make it either auto-created\r
5345        or dynamically created. For a first case, You (may be prefer to hide a\r
5346        form after showing it as a modal:\r
5347        !\r
5348        !  procedure TForm1.Button1Click( Sender: PObj );\r
5349        !  begin\r
5350        !    Form2.Form.ShowModal;\r
5351        !    Form2.Form.Hide;\r
5352        !  end;\r
5353        !\r
5354        Another way is to create modal form just before showing it (this economies\r
5355        system resources):\r
5356        !\r
5357        !  procedure TForm1.Button1Click( Sender: PObj );\r
5358        !  begin\r
5359        !    NewForm2( Form2, Applet );\r
5360        !    Form2.Form.ShowModal;\r
5361        !    Form2.Form.Free; // Never call Form2.Free or Form2.Form.Close\r
5362        !  end;               // but always Form2.Form.Free; (!)\r
5363        !\r
5364        In samples above, You certainly can place any wished code before and after\r
5365        calling ShowModal method.\r
5366        |<br>\r
5367        Do not forget that if You have more than a single form in your project,\r
5368        separate Applet object should be used.\r
5369        |<br>\r
5370        See also ShowModalEx.\r
5371        }\r
5372     function ShowModalParented( const AParent: PControl ): Integer;\r
5373     {* by Alexander Pravdin. The same as ShowModal, but with a certain\r
5374        form as a parent. }\r
5375     function ShowModalEx: Integer;\r
5376     {* The same as ShowModal, but all the windows of current thread are\r
5377        disabled while showing form modal. This is useful if KOL form from\r
5378        a DLL is used modally in non-KOL application. }\r
5379     property ModalResult: Integer read fModalResult write\r
5380     {$IFDEF USE_SETMODALRESULT}\r
5381     SetModalResult;\r
5382     {$ELSE}\r
5383     fModalResult;\r
5384     {$ENDIF}\r
5385     {* |<#form>\r
5386        Modal result. Set it to value<>0 to stop modal dialog. By agreement,\r
5387        value 1 corresponds 'OK', 2 - 'Cancel'. But it is totally by decision\r
5388        of yours how to interpret this value. }\r
5389     property Modal: Boolean read GetModal;\r
5390     {* |<#form>\r
5391        TRUE, if the form is shown modal. }\r
5392     property ModalForm: PControl read fModalForm write fModalForm;\r
5393     {* |<#form>\r
5394        |<#appbutton>\r
5395        Form currently shown modal from this form or from Applet. }\r
5397     procedure Hide;\r
5398     {* |<#appbutton>\r
5399        |<#form>\r
5400        Makes control hidden. }\r
5401     property OnShow: TOnEvent read FOnShow write SetOnShow;\r
5402     {* Is called when a control or form is to be shown. This event is not fired\r
5403        for a form, if its WindowState initially is set to wsMaximized or\r
5404        wsMinimized. This behaviour is by design (the window does not receive\r
5405        WM_SHOW message in such case). }\r
5406     property OnHide: TOnEvent read FOnHide write SetOnHide;\r
5407     {* Is called when a control or form becomes hidden. }\r
5408     property WindowState: TWindowState read GetWindowState write SetWindowState;\r
5409     {* |<#form>\r
5410        Window state. }\r
5412     property Canvas: PCanvas read GetCanvas;\r
5413     {* |<#paintbox>\r
5414        Placeholder for Canvas: PCanvas. But in KOL, it is possible to\r
5415        create applets without canvases at all. To do so, avoid using\r
5416        Canvas and use DC directly (which is passed in OnPaint event). }\r
5417     function CallDefWndProc( var Msg: TMsg ): Integer;\r
5418     {* Function to be called in WndProc method to redirect message handling\r
5419        to default window procedure. }\r
5420     function DoSetFocus: Boolean;\r
5421     {* Sets focus for Enabled window. Returns True, if success. }\r
5423     procedure MinimizeNormalAnimated;\r
5424     {* |<#form>\r
5425        Apply this method to a main form (not to another form or Applet,\r
5426        even when separate Applet control is not used and main form matches it!).\r
5427        This provides normal animated visual minimization for the application.\r
5428        It therefore has no effect, if animation during minimize/resore is\r
5429        turned off by user. }\r
5431     property OnMessage: TOnMessage read fOnMessage write fOnMessage;\r
5432     {* |<#appbutton>\r
5433        |<#form>\r
5434        Is called for every message processed by TControl object. And for\r
5435        Applet window, this event is called also for all messages, handled by\r
5436        all its child windows (forms). }\r
5438     function IsMainWindow: Boolean;\r
5439     {* |<#appbutton>\r
5440        |<#form>\r
5441        Returns True, if a window is the main in application (created first\r
5442        after the Applet, or matches the Applet). }\r
5443     property IsApplet: Boolean read FIsApplet;\r
5444     {* Returns true, if the control is created using NewApplet (or CreateApplet).\r
5445     }\r
5446     property IsForm: Boolean read fIsForm;\r
5447     {* Returns True, if the object is form window. }\r
5448     property IsMDIChild: Boolean read fIsMDIChild;\r
5449     {* Returns TRUE, if the object is MDI child form. In such case, IsForm also\r
5450        returns TRUE. }\r
5451     property IsControl: Boolean read fIsControl;\r
5452     {* Returns True, is the control is control (not form or applet). }\r
5453     property IsButton: Boolean read fIsButton;\r
5454     {* Returns True, if the control is button-like or containing buttons (button,\r
5455        bitbtn, checkbox, radiobox, toolbar). }\r
5457     function ProcessMessage: Boolean;\r
5458     {* |<#appbutton>\r
5459        Processes one message. See also ProcessMessages. }\r
5461     procedure ProcessMessages;\r
5462     {* |<#appbutton>\r
5463        Processes pending messages during long cycle of calculation,\r
5464        allowing to window to be repainted if needed and to respond to other\r
5465        messages. But if there are no such messages, your application can be\r
5466        stopped until such one appear in messages queue. To prevent such\r
5467        situation, use method ProcessPendingMessages instead. }\r
5469     procedure ProcessMessagesEx;\r
5470     {* Version of ProcessMessages, which works always correctly, even if\r
5471        the application is minimized or background. }\r
5473     procedure ProcessPendingMessages;\r
5474     {* |<#appbutton>\r
5475        Similar to ProcessMessages, but without waiting of\r
5476        message in messages queue. I.e., if there are no pending\r
5477        messages, this method immediately returns control to your\r
5478        code. This method is better to call during long cycle of\r
5479        calculation (then ProcessMessages). }\r
5480     procedure ProcessPaintMessages;\r
5481     {* }\r
5482     function WndProc( var Msg: TMsg ): Integer; virtual;\r
5483     {* Responds to all Windows messages, posted (sended) to the\r
5484        window, before all other proceeding. You can override it in\r
5485        derived controls, but in KOL there are several other ways\r
5486        to control message flow of existing controls without deriving\r
5487        another costom controls for only such purposes. See OnMessage,\r
5488        AttachProc.  }\r
5489     property HasBorder: Boolean read GetHasBorder write SetHasBorder;\r
5490     {* |<#form>\r
5491        Obvious. Form-aware. }\r
5493     property HasCaption: Boolean read GetHasCaption write SetHasCaption;\r
5494     {* |<#form>\r
5495        Obvious. Form-aware. }\r
5496     property CanResize: Boolean read GetCanResize write SetCanResize;\r
5497     {* |<#form>\r
5498        Obvious. Form-aware. }\r
5499     property StayOnTop: Boolean read GetStayOnTop write SetStayOnTop;\r
5500     {* |<#form>\r
5501        Obvious. Form-aware, but can be applied to controls. }\r
5502     property Border: Integer read fMargin write fMargin;\r
5503     {* |<#form>\r
5504        Distance between edges and child controls and between child\r
5505        controls by default (if methods PlaceRight, PlaceDown, PlaceUnder,\r
5506        ResizeParent, ResizeParentRight, ResizeParentBottom are called).\r
5507        |<br>\r
5508        Originally was named Margin, now I recommend to use the name 'Border' to\r
5509        avoid confusion with MarginTop, MarginBottom, MarginLeft and\r
5510        MarginRight properties.\r
5511        |<br>\r
5512        Initial value is always 2. Border property is used in realigning\r
5513        child controls (when its Align property is not caNone), and value\r
5514        of this property determines size of borders between edges of children\r
5515        and its parent and between aligned controls too.\r
5516        |<br>\r
5517        See also properties MarginLeft, MarginRight, MarginTop, MarginBottom. }\r
5518     function SetBorder( Value: Integer ): PControl;\r
5519     {* Assigns new Border value, and returns @ Self. }\r
5521     property Margin: Integer read fMargin write fMargin;\r
5522     {* |<#form>\r
5523        Old name for property Border. }\r
5525     property MarginTop: Integer index 1\r
5526              {$IFDEF F_P}   read GetClientMargin\r
5527              {$ELSE DELPHI} read fClientTop\r
5528              {$ENDIF F_P/DELPHI} write SetClientMargin;\r
5529     {* Additional distance between true window client top and logical top of\r
5530        client rectangle. This value is added to Top of rectangle, returning\r
5531        by property ClientRect. Together with other margins and property Border,\r
5532        this property allows to change view of form for case, that Align property\r
5533        is used to align controls on parent (it is possible to provide some\r
5534        distance from child controls to its parent, and between child controls.\r
5535        |<br>\r
5536        Originally this property was introduced to compensate incorrect\r
5537        ClientRect property, calculated for some types of controls.\r
5538        |<br>\r
5539        See also properties Border, MarginBottom, MarginLeft, MarginRight. }\r
5540     property MarginBottom: Integer index 2\r
5541              {$IFDEF F_P}   read GetClientMargin\r
5542              {$ELSE DELPHI} read fClientBottom\r
5543              {$ENDIF F_P/DELPHI} write SetClientMargin;\r
5544     {* The same as MarginTop, but a distance between true window Bottom of\r
5545        client rectangle and logical bottom one. Take in attention, that this value\r
5546        should be POSITIVE to make logical bottom edge located above true edge.\r
5547        |<br>\r
5548        See also properties Border, MarginTop, MarginLeft, MarginRight. }\r
5549     property MarginLeft: Integer index 3\r
5550              {$IFDEF F_P}   read GetClientMargin\r
5551              {$ELSE DELPHI} read fClientLeft\r
5552              {$ENDIF F_P/DELPHI} write SetClientMargin;\r
5553     {* The same as MarginTop, but a distance between true window Left of\r
5554        client rectangle and logical left edge.\r
5555        |<br>\r
5556        See also properties Border, MarginTop, MarginRight, MarginBottom. }\r
5557     property MarginRight: Integer index 4\r
5558              {$IFDEF F_P}   read GetClientMargin\r
5559              {$ELSE DELPHI} read fClientRight\r
5560              {$ENDIF F_P/DELPHI} write SetClientMargin;\r
5561     {* The same as MarginLeft, but a distance between true window Right of\r
5562        client rectangle and logical bottom one. Take in attention, that this value\r
5563        should be POSITIVE to make logical right edge located left of true edge.\r
5564        |<br>\r
5565        See also properties Border, MarginTop, MarginLeft, MarginBottom. }\r
5567     property Tabstop: Boolean read fTabstop write fTabstop;\r
5568     {* True, if control can be focused using tabulating between controls.\r
5569        Set it to False to make control unavailable for keyboard, but only\r
5570        for mouse. }\r
5572     property TabOrder: Integer read fTabOrder write SetTabOrder;\r
5573     {* Order of tabulating of controls. Initially, TabOrder is equal to\r
5574        creation order of controls. If TabOrder changed, TabOrder of\r
5575        all controls with not less value of one is shifted up. To place\r
5576        control before another, assign TabOrder of one to another.\r
5577        For example:\r
5578        !             Button1.TabOrder := EditBox1.TabOrder;\r
5579        In code above, Button1 is placed just before EditBox1 in tabulating\r
5580        order (value of TabOrder of EditBox1 is incremented, as well as\r
5581        for all follow controls). }\r
5583     property Focused: Boolean read GetFocused write SetFocused;\r
5584     {* True, if the control is current on form (but check also, what form\r
5585        itself is focused). For form it is True, if the form is active (i.e.\r
5586        it is foreground and capture keyboard). Set this value to True to make\r
5587        control current and focused (if applicable). }\r
5589     function BringToFront: PControl;\r
5590     {* Changes z-order of the control, bringing it to the topmost level. }\r
5591     function SendToBack: PControl;\r
5592     {* Changes z-order of the control, sending it to the back of siblings. }\r
5593     property TextAlign: TTextAlign read GetTextAlign write SetTextAlign;\r
5594     {* |<#label>\r
5595        |<#panel>\r
5596        |<#button>\r
5597        |<#bitbtn>\r
5598        |<#edit>\r
5599        |<#memo>\r
5600        Text horizontal alignment. Applicable to labels, buttons,\r
5601        multi-line edit boxes, panels. }\r
5602     property VerticalAlign: TVerticalAlign read GetVerticalAlign write SetVerticalAlign;\r
5603     {* |<#button>\r
5604        |<#label>\r
5605        |<#panel>\r
5606        Text vertical alignment. Applicable to buttons, labels and panels. }\r
5607     property WordWrap: Boolean read fWordWrap;\r
5608     {* TRUE, if this is a label, created using NewWordWrapLabel. }\r
5609     property ShadowDeep: Integer read FShadowDeep write SetShadowDeep;\r
5610     {* |<#3dlabel>\r
5611        Deep of a shadow (for label effect only, created calling NewLabelEffect). }\r
5613     property CannotDoubleBuf: Boolean read fCannotDoubleBuf write fCannotDoubleBuf;\r
5614     {* }\r
5615     property DoubleBuffered: Boolean read fDoubleBuffered write SetDoubleBuffered;\r
5616     {* Set it to true for some controls, which are flickering in repainting\r
5617        (like label effect). Slow, and requires additional code. This property\r
5618        is inherited by all child controls.\r
5619        |<br>&nbsp;&nbsp;&nbsp;\r
5620        Note: RichEdit control can not become DoubleBuffered. }\r
5621     //function IsSelfOrParentDblBuf: Boolean;\r
5622     {* Returns true, if DoubleBuffered or one of parents is DoubleBuffered. }\r
5623     function DblBufTopParent: PControl;\r
5624     {* Returns the topmost DoubleBuffered Parent control. }\r
5625     property Transparent: Boolean read fTransparent write SetTransparent;\r
5626     {* Set it to true to get special effects. Transparency also uses\r
5627        DoubleBuffered and inherited by child controls.\r
5628        |<br>&nbsp;&nbsp;&nbsp;\r
5629        Please note, that some controls can not be shown properly, when\r
5630        Transparent is set to True for it. If You want to make edit control\r
5631        transparent (e.g., over gradient filled panel), handle its OnChanged\r
5632        property and call there Invalidate to provide repainting of edit\r
5633        control content. Note also, that for RichEdit control property\r
5634        Transparent has no effect (as well as DoubleBuffered). But special\r
5635        property RE_Transparent is designed especially for RichEdit control\r
5636        (it works fine, but with great number of flicks while resizing\r
5637        of a control). Another note is about Edit control. To allow editing\r
5638        of transparent edit box, it is necessary to invalidate it for\r
5639        every pressed character. Or, use Ed_Transparent property instead. }\r
5641     property Ed_Transparent: Boolean read fTransparent write EdSetTransparent;\r
5642     {* |<#edit>\r
5643        |<#memo>\r
5644        Use this property for editbox to make it really Transparent. Remember,\r
5645        that though Transparent property is inherited by child controls from\r
5646        its parent, this is not so for Ed_Transparent. So, it is necessary to\r
5647        set Ed_Transparent to True for every edit control explicitly. }\r
5648     property AlphaBlend: Integer read fAlphaBlend write SetAlphaBlend;\r
5649     {* |<#form>\r
5650        If assigned to 0..254, makes window (form or control) semi-transparent\r
5651        (Win2K only).\r
5652        |<br>\r
5653        Depending on value assigned, it is possible to adjust transparency\r
5654        level ( 0 - totally transparent, 255 - totally opaque).  }\r
5656     property LookTabKeys: TTabKeys read fLookTabKeys write fLookTabKeys;\r
5657     {* Set of keys which can be used as tabulation keys in a control. }\r
5658     procedure GotoControl( Key: DWORD );\r
5659     {* |<#form>\r
5660        Emulates tabulation key press w/o sending message to current control.\r
5661        Can be applied to a form or to any its control. If VK_TAB is used,\r
5662        state of shift kay is checked in: if it is pressed, tabulate is in\r
5663        backward direction. }\r
5664     property SubClassName: String read get_ClassName write set_ClassName;\r
5665     {* Name of window class - unique for every window class\r
5666        in every run session of a program. }\r
5668     property OnClose: TOnEventAccept read fOnClose write fOnClose;\r
5669     {* |<#form>\r
5670        |<#applet>\r
5671        Called before closing the window. It is possible to set Accept\r
5672        parameter to False to prevent closing the window. This event events\r
5673        is not called when windows session is finishing (to handle this\r
5674        event, handle WM_QUERYENDSESSION message, or assign OnQueryEndSession\r
5675        event to another or the same event handler). }\r
5677     property OnQueryEndSession: TOnEventAccept read fOnQueryEndSession write SetOnQueryEndSession;\r
5678     {* |<#form>\r
5679        |<#applet>\r
5680        Called when WM_QUERYENDSESSION message come in. It is possible to set Accept\r
5681        parameter to False to prevent closing the window (in such case session ending\r
5682        is halted). It is possible to check CloseQueryReason property to find out,\r
5683        why event occur. }\r
5684     property CloseQueryReason: TCloseQueryReason read fCloseQueryReason;\r
5685     {* Reason why OnClose or OnQueryEndSession called. }\r
5686     property OnMinimize: TOnEvent index 0\r
5687              {$IFDEF F_P}   read GetOnMinMaxRestore\r
5688              {$ELSE DELPHI} read fOnMinimize\r
5689              {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;\r
5690     {* |<#form>\r
5691        Called when window is minimized. }\r
5692     property OnMaximize: TOnEvent index 8\r
5693              {$IFDEF F_P}   read GetOnMinMaxRestore\r
5694              {$ELSE DELPHI} read fOnMaximize\r
5695              {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;\r
5696     {* |<#form>\r
5697        Called when window is maximized. }\r
5698     property OnRestore: TOnEvent index 16\r
5699              {$IFDEF F_P}   read GetOnMinMaxRestore\r
5700              {$ELSE DELPHI} read fOnRestore\r
5701              {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;\r
5702     {* |<#form>\r
5703        Called when window is restored from minimized or maximized state. }\r
5705     property UpdateRgn: HRgn read fUpdRgn;\r
5706     {* A handle of update region. Valid only in OnPaint method. You\r
5707        can use it to improve painting (for speed), if necessary. When\r
5708        UpdateRgn is obtained in response to WM_PAINT message, value\r
5709        of the property EraseBackground is used to pass it to the API\r
5710        function GetUpdateRgn. If UpdateRgn = 0, this means that entire\r
5711        window should be repainted. Otherwise, You (e.g.) can check\r
5712        if the rectangle is in clipping region using API function\r
5713        RectInRegion. }\r
5715     property EraseBackground: Boolean read fEraseUpdRgn write fEraseUpdRgn;\r
5716     {* This value is used to pass it to the API function GetUpdateRgn,\r
5717        when UpadateRgn property is obtained first in responce to WM_PAINT\r
5718        message. If EraseBackground is set to True, system is responsible\r
5719        for erasing background of update region before painting. If not\r
5720        (default), the entire region invalidated should be painted by your\r
5721        event handler. }\r
5723     property OnPaint: TOnPaint read fOnPaint write SetOnPaint;\r
5724     {* Event to set to override standard control painting. Can be applied\r
5725        to any control (though originally was designed only for paintbox\r
5726        control). When an event handler is called, it is possible to use\r
5727        UpdateRgn to examine what parts of window require painting to\r
5728        improve performance of the painting operation. }\r
5731     property OnEraseBkgnd: TOnPaint read fOnEraseBkgnd write SetOnEraseBkgnd;\r
5732     {* This event allows to override erasing window background in response\r
5733        to WM_ERASEBKGND message. This allows to add some decorations to\r
5734        standard controls without overriding its painting in total.\r
5735        Note: When erase background, remember, that property ClientRect can\r
5736        return not true client rectangle of the window - use GetClientRect\r
5737        API function instead. For example:\r
5738     !\r
5739     !var BkBmp: HBitmap;\r
5740     !\r
5741     !procedure TForm1.KOLForm1FormCreate(Sender: PObj);\r
5742     !begin\r
5743     !  Toolbar1.OnEraseBkgnd := DecorateToolbar;\r
5744     !  BkBmp := LoadBitmap( hInstance, 'BK1' );\r
5745     !end;\r
5746     !\r
5747     !procedure TForm1.DecorateToolbar(Sender: PControl; DC: HDC);\r
5748     !var CR: TRect;\r
5749     !begin\r
5750     !  GetClientRect( Sender.Handle, CR );\r
5751     !  Sender.Canvas.Brush.BrushBitmap := BkBmp;\r
5752     !  Sender.Canvas.FillRect( CR );\r
5753     !end;\r
5754     !\r
5755      }\r
5758     property OnClick: TOnEvent read fOnClick write fOnClick;\r
5759     {* |<#button>\r
5760        |<#checkbox>\r
5761        |<#radiobox>\r
5762        |<#toolbar>\r
5763        Called on click at control. For buttons, checkboxes and radioboxes\r
5764        is called regadless if control clicked by mouse or keyboard. For toolbar,\r
5765        the same event is used for all toolbar buttons and toolbar itself.\r
5766        To determine which toolbar button is clicked, check CurIndex property.\r
5767        And note, that all the buttons including separator buttons are enumerated\r
5768        starting from 0. Though images are stored (and prepared) only for\r
5769        non-separator buttons. And to determine, if toolbar button was clicked\r
5770        with right mouse button, check RightClick property. }\r
5771     property RightClick: Boolean read fRightClick;\r
5772     {* |<#toolbar>\r
5773        |<#listview>\r
5774        Use this property to determine which mouse button was clicked\r
5775        (applicable to toolbar in the OnClick event handler). }\r
5776     property OnEnter: TOnEvent read fOnEnter write fOnEnter;\r
5777     {* Called when control receives focus. }\r
5778     property OnLeave: TOnEvent read fOnLeave write fOnLeave;\r
5779     {* Called when control looses focus. }\r
5780     property OnChange: TOnEvent read fOnChange write fOnChange;\r
5781     {* |<#edit>\r
5782        |<#memo>\r
5783        |<#listbox>\r
5784        |<#combo>\r
5785        |<#tabcontrol>\r
5786        Called when edit control is changed, or selection in listbox or\r
5787        current index in combobox is changed (but if OnSelChanged assigned,\r
5788        the last is called for change selection). To respond to check/uncheck\r
5789        checkbox or radiobox events, use OnClick instead. }\r
5790     property OnSelChange: TOnEvent read fOnSelChange write fOnSelChange;\r
5791     {* |<#richedit>\r
5792        |<#listbox>\r
5793        |<#combo>\r
5794        |<#treeview>\r
5795        Called for rich edit control, listbox, combobox or treeview when current selection\r
5796        (range, or current item) is changed. If not assigned, but OnChange is\r
5797        assigned, OnChange is called instead. }\r
5798     property OnResize: TOnEvent read FOnResize write SetOnResize;\r
5799     {* Called whenever control receives message WM_SIZE (thus is, if\r
5800        control is resized. }\r
5801     property OnMove: TOnEvent read FOnMove write SetOnMove;\r
5802     {* Called whenever control receives message WM_MOVE (i.e. when control is\r
5803        moved over its parent). }\r
5805     property MinSizePrev: Integer read fSplitMinSize1 write fSplitMinSize1;\r
5806     {* |<#splitter>\r
5807        Minimal allowed (while dragging splitter) size of previous control\r
5808        for splitter (see NewSplitter). }\r
5809     property SplitMinSize1: Integer read fSplitMinSize1 write fSplitMinSize1;\r
5810     {* The same as MinSizePrev. }\r
5811     property MinSizeNext: Integer read fSplitMinSize2 write fSplitMinSize2;\r
5812     {* |<#splitter>\r
5813        Minimal allowed (while dragging splitter) size of the rest of parent\r
5814        of splitter or of SecondControl (see NewSplitter). }\r
5815     property SplitMinSize2: Integer read fSplitMinSize2 write fSplitMinSize2;\r
5816     {* The same as MinSizeNext. }\r
5817     property SecondControl: PControl read fSecondControl write fSecondControl;\r
5818     {* |<#splitter>\r
5819        Second control to check (while dragging splitter) if its size not less\r
5820        than SplitMinSize2 (see NewSplitter). By default, second control is\r
5821        not necessary, and needed only in rare case when SecondControl can not\r
5822        be determined automatically to restrict splitter right (bottom) position. }\r
5823     property OnSplit: TOnSplit read fOnSplit write fOnSplit;\r
5824     {* |<#splitter>\r
5825        Called when splitter control is dragging - to allow for\r
5826        your event handler to decide if to accept new size of\r
5827        left (top) control, and new size of the rest area of parent. }\r
5828     property Dragging: Boolean read FDragging;\r
5829     {* |<#splitter>\r
5830        True, if splitter control is dragging now by user with left\r
5831        mouse button. Also, this property can be used to detect if the control\r
5832        is dragging with mouse (after calling DragStartEx method). }\r
5833     procedure DragStart;\r
5834     {* Call this method for a form or control to drag it with left mouse button,\r
5835        when mouse left button is already down. Dragging is stopped when left mouse\r
5836        button is released. See also DragStartEx, DragStopEx. }\r
5837     procedure DragStartEx;\r
5838     {* Call this method to start dragging the form by mouse. To stop\r
5839        dragging, call DragStopEx method. (Tip: to detect mouse up event,\r
5840        use OnMouseUp event of the dragging control). This method can be used\r
5841        to move any control with the mouse, not only entire form. State of\r
5842        mouse button is not significant. Determine dragging state of the control\r
5843        checking its Dragging property. }\r
5844     procedure DragStopEx;\r
5845     {* Call this method to stop dragging the form (started by DragStopEx). }\r
5846     procedure DragItem( OnDrag: TOnDrag );\r
5847     {* Starts dragging something with mouse. During the process,\r
5848        callback function OnDrag is called, which allows to control\r
5849        drop target, change cursor shape, etc. }\r
5851     property OnKeyDown: TOnKey read fOnKeyDown write SetOnKeyDown;\r
5852     {* Obvious. }\r
5853     property OnKeyUp: TOnKey read fOnKeyUp write SetOnKeyUp;\r
5854     {* Obvious. }\r
5855     property OnChar: TOnChar read fOnChar write SetOnChar;\r
5856     {* Obvious. }\r
5858     property OnMouseDown: TOnMouse read fOnMouseDown write SetMouseDown;\r
5859     {* Obvious. }\r
5860     property OnMouseUp: TOnMouse read fOnMouseUp write SetMouseUp;\r
5861     {* Obvious. }\r
5862     property OnMouseMove: TOnMouse read fOnMouseMove write SetMouseMove;\r
5863     {* Obvious. }\r
5864     property OnMouseDblClk: TOnMouse read fOnMouseDblClk write SetMouseDblClk;\r
5865     {* Obvious. }\r
5866     property OnMouseWheel: TOnMouse read fOnMouseWheel write SetMouseWheel;\r
5867     {* Obvious. }\r
5869     property OnMouseEnter: TOnEvent read fOnMouseEnter write SetOnMouseEnter;\r
5870     {* Is called when mouse is entered into control. See also OnMouseLeave. }\r
5871     property OnMouseLeave: TOnEvent read fOnMouseLeave write SetOnMouseLeave;\r
5872     {* Is called when mouse is leaved control. If this event is assigned,\r
5873        then mouse is captured on mouse enter event to handle all other\r
5874        mouse events until mouse cursor leaves the control. }\r
5875     property OnTestMouseOver: TOnTestMouseOver read fOnTestMouseOver write SetOnTestMouseOver;\r
5876     {* |<#bitbtn>\r
5877        Special event, which allows to extend OnMouseEnter / OnMouseLeave\r
5878        (and also Flat property for BitBtn control). If a handler is assigned\r
5879        to this event, actual testing whether mouse is in control or not,\r
5880        is occuring in the handler. So, it is possible to simulate more\r
5881        careful hot tracking for controls with non-rectangular shape (such\r
5882        as glyphed BitBtn control). }\r
5884     property MouseInControl: Boolean read fMouseInControl;\r
5885     {* |<#bitbtn>\r
5886        This property can return True only if OnMouseEnter / OnMouseLeave\r
5887        event handlers are set for a control (or, for BitBtn, property Flat\r
5888        is set to True. Otherwise, False is returned always. }\r
5890     property Flat: Boolean read fFlat write SetFlat;\r
5891     {* |<#bitbtn>\r
5892        Set it to True for BitBtn, to provide either flat border for a button\r
5893        or availability of "highlighting" (correspondent to glyph index 4).\r
5894        |<br>\r
5895        Note: this can work incorrectly a bit under win95 without comctl32.dll\r
5896        updated. Therefore, application will launch. To enforce correct working\r
5897        even under Win95, use your own timer, which event handler checks for\r
5898        mouse over bitbtn control, e.g.:\r
5899        !    procedure TForm1.Timer1Timer(Sender: PObj);\r
5900        !    var P: TPoint;\r
5901        !    begin\r
5902        !      if not BitBtn1.MouseInControl then Exit;\r
5903        !      GetCursorPos( P );\r
5904        !      P := BitBtn1.Screen2Client( P );\r
5905        !      if not PtInRect( BitBtn1.ClientRect, P ) then\r
5906        !      begin\r
5907        !        BitBtn1.Flat := FALSE;\r
5908        !        BitBtn1.Flat := TRUE;\r
5909        !      end;\r
5910        !    end;\r
5911     }\r
5912     property RepeatInterval: Integer read fRepeatInterval write fRepeatInterval;\r
5913     {* |<#bitbtn>\r
5914        If this property is set to non-zero, it is interpreted (for BitBtn\r
5915        only) as an interval in milliseconds between repeat button down events,\r
5916        which are generated after first mouse or button click and until\r
5917        button is released. Though, if the button is pressed with keyboard (with\r
5918        space key), RepeatInterval value is ignored and frequency of repeatitive\r
5919        clicking is determined by user keyboard settings only. }\r
5920     function LikeSpeedButton: PControl;\r
5921     {* |<#button>\r
5922        |<#bitbtn>\r
5923        Transparent method (returns control itself). Makes button not focusable. }\r
5925     function Add( const S: String ): Integer;\r
5926     {* |<#listbox>\r
5927        |<#combo>\r
5928        Only for listbox and combobox. }\r
5930     function Insert( Idx: Integer; const S: String ): Integer;\r
5931     {* |<#listbox>\r
5932        |<#combo>\r
5933        Only for listbox and combobox. }\r
5934     procedure Delete( Idx: Integer );\r
5935     {* |<#listbox>\r
5936        |<#combo>\r
5937        Only for listbox and combobox. }\r
5938     procedure Clear;\r
5939     {* Clears object content. Has different sense for different controls.\r
5940        E.g., for label, editbox, button and other simple controls it\r
5941        assigns empty string to Caption property. For listbox, combobox,\r
5942        listview it deletes all items. For toolbar, it deletes all buttons.\r
5943        Et so on. }\r
5945     property Progress: Integer index ((PBM_SETPOS or $8000) shl 16) or PBM_GETPOS\r
5946                                read GetIntVal write SetIntVal;\r
5947     {* |<#progressbar>\r
5948        Only for ProgressBar. }\r
5949     property MaxProgress: Integer index ((PBM_SETRANGE32 or $8000) shl 16) or PBM_GETRANGE\r
5950                                read GetIntVal write SetMaxProgress;\r
5951     {* |<#progressbar>\r
5952        Only for ProgressBar. 100 is the default value. }\r
5953     property ProgressColor: TColor read fTextColor write SetProgressColor;\r
5954     {* |<#progressbar>\r
5955        Only for ProgressBar. }\r
5956     property ProgressBkColor: TColor read fColor write SetCtlColor; //SetProgressBkColor;\r
5957     {* |<#progressbar>\r
5958        Obsolete. Now the same as Color. }\r
5960     property StatusText[ Idx: Integer ]: PChar read GetStatusText write SetStatusText;\r
5961     {* |<#form>\r
5962        Only for forms to set/retrieve status text to/from given status panel.\r
5963        Panels are enumerated from 0 to 254, 255 is to indicate simple\r
5964        status bar. Size grip in right bottom corner of status window is\r
5965        displayed only if form still CanResize.\r
5966        |<br>\r
5967        When a status text is set first time, status bar window is created\r
5968        (always aligned to bottom), and form is resizing to preset client height.\r
5969        While status bar is showing, client height value is returned without\r
5970        height of status bar. To remove status bar, call RemoveStatus method for\r
5971        a form.\r
5972        |<br>\r
5973        By default, text is left-aligned within the specified part of a status\r
5974        window. You can embed tab characters (#9) in the text to center or\r
5975        right-align it. Text to the right of a single tab character is centered,\r
5976        and text to the right of a second tab character is right-aligned.\r
5977        |<br>\r
5978        If You use separate status bar onto several panels, these automatically\r
5979        align its widths to the same value (width divided to number of panels).\r
5980        To adjust status panel widths for every panel, use property StatusPanelRightX.\r
5981     }\r
5982     property SimpleStatusText: PChar index 255 read GetStatusText write SetStatusText;\r
5983     {* |<#form>\r
5984        Only for forms to set/retrive status text to/from simple status bar.\r
5985        Size grip in right bottom corner of status window is displayed only\r
5986        if form CanResize.\r
5987        |<br>\r
5988        When status text set first time, (simple) status bar window is created\r
5989        (always aligned to bottom), and form is resizing to preset client height.\r
5990        While status bar is showing, client height value is returned without\r
5991        height of status bar. To remove status bar, call RemoveStatus method for\r
5992        a form.\r
5993        |<br>\r
5994        By default, text is left-aligned within the specified part of a status\r
5995        window. You can embed tab characters (#9) in the text to center or\r
5996        right-align it. Text to the right of a single tab character is centered,\r
5997        and text to the right of a second tab character is right-aligned.\r
5998     }\r
5999     property StatusCtl: PControl read fStatusCtl;\r
6000     {* Pointer to Status bar control. To "create" child controls on\r
6001        the status bar, first create it as a child of form, for instance, and\r
6002        then change its property Parent, e.g.:\r
6003        ! var Progress1: PControl;\r
6004        ! ...\r
6005        ! Progress1 := NewProgressBar( Form1 );\r
6006        ! Progress1.Parent := Form1.StatusCtl;\r
6007        (If you use MCK, code should be another a bit, and in this case it is\r
6008        possible to create and adjust the control at design-time, and at run-time\r
6009        change its parent control. E.g. (Progress1 is created at run-time here too):\r
6010        ! Progress1 := NewProgressBar( Form );\r
6011        ! Progress1.Parent := Form.StatusCtl;\r
6012        ).\r
6013        Do not forget to provide StatusCtl to be existing first (e.g. assign\r
6014        one-space string to SimpleStatusText property of the form, for MCK do\r
6015        so using Object Inspector).\r
6016        }\r
6017     property SizeGrip: Boolean read fSizeGrip write fSizeGrip;\r
6018     {* Size grip for status bar. Has effect only before creating window. }\r
6020     procedure RemoveStatus;\r
6021     {* |<#form>\r
6022        Call it to remove status bar from a form (created in result of assigning\r
6023        value(s) to StatusText[], SimpleStatusText properties). When status bar is\r
6024        removed, form is resized to preset client height. }\r
6025     function StatusPanelCount: Integer;\r
6026     {* |<#form>\r
6027        Returns number of status panels defined in status bar. }\r
6028     property StatusPanelRightX[ Idx: Integer ]: Integer read GetStatusPanelX write SetStatusPanelX;\r
6029     {* |<#form>\r
6030        Use this property to adjust status panel right edges (if the status bar is\r
6031        divided onto several subpanels). If the right edge for the last panel is\r
6032        set to -1 (by default) it is expanded to the right edge of a form window.\r
6033        Otherwise, status bar can be shorter then form width. }\r
6034     property StatusWindow: HWND read fStatusWnd;\r
6035     {* |<#form>\r
6036        Provided for case if You want to use API direct message sending to\r
6037        status bar. }\r
6039     property Color1: TColor read fColor1 write SetColor1;\r
6040     {* |<#gradient>\r
6041        Top line color for GradientPanel. }\r
6042     property Color2: TColor read fColor2 write SetColor2;\r
6043     {* |<#gradient>\r
6044        |<#3Dlabel>\r
6045        Bottom line color for GradientPanel, or shadow color for LabelEffect.\r
6046        (If clNone, shadow color for LabelEffect is calculated as a mix bitween\r
6047        TextColor and clBlack). }\r
6048     property GradientStyle: TGradientStyle read FGradientStyle write SetGradientStyle;\r
6049     {* |<#gradient>\r
6050        Styles other then gsVertical and gsHorizontal has effect only for\r
6051        gradient panel, created by NewGradientPanelEx. }\r
6052     property GradientLayout: TGradientLayout read FGradientLayout write SetGradientLayout;\r
6053     {* |<#gradient>\r
6054        Has only effect for gradient panel, created by NewGradientPanelEx.\r
6055        Ignored for styles gsVertical and gsHorizontal. }\r
6057     //======== Image lists (for ListView, TreeView, ToolBar and TabControl):\r
6058     property ImageListSmall: PImageList index 16 read GetImgListIdx write SetImgListIdx;\r
6059     {* |<#listview>\r
6060        Image list with small icons used with List View control. If not set,\r
6061        last added (i.e. created with a control as an owner) image list with\r
6062        small icons is used. }\r
6063     property ImageListNormal: PImageList index 32 read GetImgListIdx write SetImgListIdx;\r
6064     {* |<#listview>\r
6065        |<#treeview>\r
6066        |<#tabcontrol>\r
6067        |<#bitbtn>\r
6068        Image list with normal size icons used with List View control (or with\r
6069        icons for BitBtn, TreeView, ToolBar or TabControl). If not set,\r
6070        last added (i.e. created with a control as an owner) image list is used.\r
6071        }\r
6072     property ImageListState: PImageList index 0 read GetImgListIdx write SetImgListIdx;\r
6073     {* |<#listview>\r
6074        |<#treeview>\r
6075        Image list used as a state images list for ListView or TreeView control. }\r
6077     //========\r
6078     function SetUnicode( Unicode: Boolean ): PControl;\r
6079     {* |<#listview>\r
6080        |<#treeview>\r
6081        |<#tabcontrol>\r
6082        Sets control as Unicode or not. The control itself is returned as for\r
6083        other "transparent" functions. A conditional define UNICODE_CTRLS must\r
6084        be added to a project to provide handling unicode messages. }\r
6086     //======== TabControl-specific properties and methods:\r
6087     property Pages[ Idx: Integer ]: PControl read GetPages;\r
6088     {* |<#tabcontrol>\r
6089        Returns controls, which can be used as parent for controls, placed on\r
6090        different pages of a tab control. Use it like in follows example:\r
6091        | Label1 := NewLabel( TabControl1.Pages[ 0 ], 'Label1' );\r
6092        To find number of pages available, check out Count property of the tab\r
6093        control. Pages are enumerated from 0 to Count - 1, as usual. }\r
6094     property TC_Pages[ Idx: Integer ]: PControl read GetPages;\r
6095     {* |<#tabcontrol>\r
6096        The same as above. }\r
6097     function TC_Insert( Idx: Integer; const TabText: String; TabImgIdx: Integer ): PControl;\r
6098     {* |<#tabcontrol>\r
6099        Inserts new tab before given, returns correspondent page control\r
6100        (which can be used as a parent for controls to place on the page). }\r
6101     procedure TC_Delete( Idx: Integer );\r
6102     {* |<#tabcontrol>\r
6103        Removes tab from tab control, destroying all its child controls. }\r
6104     property TC_Items[ Idx: Integer ]: String read TCGetItemText write TCSetItemText;\r
6105     {* |<#tabcontrol>\r
6106        Text, displayed on tab control tabs. }\r
6107     property TC_Images[ Idx: Integer ]: Integer read TCGetItemImgIDx write TCSetItemImgIdx;\r
6108     {* |<#tabcontrol>\r
6109        Image index for a tab in tab control. }\r
6110     property TC_ItemRect[ Idx: Integer ]: TRect read TCGetItemRect;\r
6111     {* |<#tabcontrol>\r
6112        Item rectangle for a tab in tab control. }\r
6113     procedure TC_SetPadding( cx, cy: Integer );\r
6114     {* |<#tabcontrol>\r
6115        Sets space padding around tab text in a tab of tab control. }\r
6116     function TC_TabAtPos( x, y: Integer ): Integer;\r
6117     {* |<#tabcontrol>\r
6118        Returns index of tab, found at the given position (relative to\r
6119        a client rectangle of tab control). If no tabs found at the\r
6120        position, -1 is returned. }\r
6121     function TC_DisplayRect: TRect;\r
6122     {* |<#tabcontrol>\r
6123        Returns rectangle, occupied by a page rather then tab. }\r
6124     function TC_IndexOf(const S: String): Integer;\r
6125     {* |<#tabcontrol>\r
6126        By Mr Brdo. Index of page by its Caption. }\r
6127     function TC_SearchFor(const S: String; StartAfter: Integer; Partial: Boolean): Integer;\r
6128     {* |<#tabcontrol>\r
6129        By Mr Brdo. Index of page by its Caption. }\r
6131     //======== ListView style and options:\r
6132     property LVStyle: TListViewStyle read fLVStyle write SetLVStyle;\r
6133     {* |<#listview>\r
6134        ListView style of view. Can be changed at run time. }\r
6136     property LVOptions: TListViewOptions read fLVOptions write SetLVOptions;\r
6137     {* |<#listview>\r
6138        ListView options. Can be changed at run time. }\r
6140     property LVTextColor: TColor index LVM_GETTEXTCOLOR\r
6141              {$IFDEF F_P}   read LVGetColorByIdx\r
6142              {$ELSE DELPHI} read fTextColor\r
6143              {$ENDIF F_P/DELPHI} write LVSetColorByIdx;\r
6144     {* |<#listview>\r
6145        ListView text color. Use it instead of TextColor. }\r
6146     property LVTextBkColor: TColor index LVM_GETTEXTBKCOLOR\r
6147              {$IFDEF F_P}   read LVGetColorByIdx\r
6148              {$ELSE DELPHI} read fLVTextBkColor\r
6149              {$ENDIF F_P/DELPHI} write LVSetColorByIdx;\r
6150     {* |<#listview>\r
6151        ListView background color for text. }\r
6152     property LVBkColor: TColor read fColor write SetCtlColor; //LVSetBkColor;\r
6153     {* |<#listview>\r
6154        ListView background color.  Use it instead of Color. }\r
6156     //======== List View columns handling:\r
6157     property LVColCount: Integer read fLVColCount;\r
6158     {* |<#listview>\r
6159        ListView (additional) column count. Value 0 means that there are\r
6160        no columns (single item text / icon is used). If You want\r
6161        to provide several columns, first call LVColAdd to "insert" column 0,\r
6162        i.e. to provide header text for first column (with index 0).\r
6163        If there are no column, nothing will be shown in lvsDetail /\r
6164        lvsDetailNoHeader view style. }\r
6165     procedure LVColAdd( const aText: String; aalign: TTextAlign; aWidth: Integer );\r
6166     {* |<#listview>\r
6167        Adds new column. Pass 'width' <= 0 to provide default column width.\r
6168        'text' is a column header text. }\r
6169     {$IFNDEF _FPC}\r
6170     {$IFNDEF _D2}\r
6171     procedure LVColAddW( const aText: WideString; aalign: TTextAlign; aWidth: Integer );\r
6172     {* |<#listview>\r
6173        Adds new column (unicode version). }\r
6174     {$ENDIF _D2}\r
6175     {$ENDIF _FPC}\r
6176     procedure LVColInsert( ColIdx: Integer; const aText: String; aAlign: TTextAlign; aWidth: Integer );\r
6177     {* |<#listview>\r
6178        Inserts new column at the Idx position (1-based column index). }\r
6179     {$IFNDEF _FPC}\r
6180     {$IFNDEF _D2}\r
6181     procedure LVColInsertW( ColIdx: Integer; const aText: WideString; aAlign: TTextAlign; aWidth: Integer );\r
6182     {* |<#listview>\r
6183        Inserts new column at the Idx position (1-based column index). }\r
6184     {$ENDIF _D2}\r
6185     {$ENDIF _FPC}\r
6186     procedure LVColDelete( ColIdx: Integer );\r
6187     {* |<#listview>\r
6188        Deletes column from List View }\r
6189     property LVColWidth[ Item: Integer ]: Integer index LVM_GETCOLUMNWIDTH\r
6190              read GetItemVal write SetItemVal;\r
6191     {* |<#listview>\r
6192        Retrieves or changes column width. For lvsList view style, the same width\r
6193        is returned for all columns (ColIdx is ignored). It is possible to use\r
6194        special values to assign to a property:\r
6195        |<br> LVSCW_AUTOSIZE - Automatically sizes the column\r
6196        |<br> LVSCW_AUTOSIZE_USEHEADER - Automatically sizes the column to fit\r
6197        the header text\r
6198        |<br>\r
6199        To set coumn width in lvsList view mode, column index must be -1\r
6200        (and Width to set must be in range 0..32767 always). }\r
6201     property LVColText[ Idx: Integer ]: String read GetLVColText write SetLVColText;\r
6202     {* |<#listview>\r
6203        Allows to get/change column header text at run time. }\r
6204     {$IFNDEF _FPC}\r
6205     {$IFNDEF _D2}\r
6206     property LVColTextW[ Idx: Integer ]: WideString read GetLVColTextW write SetLVColTextW;\r
6207     {* |<#listview>\r
6208        Allows to get/change column header text at run time. }\r
6209     {$ENDIF _D2}\r
6210     {$ENDIF _FPC}\r
6211     property LVColAlign[ Idx: Integer ]: TTextAlign read GetLVColalign write SetLVColalign;\r
6212     {* |<#listview>\r
6213        Column text aligning. }\r
6214     property LVColImage[ Idx: Integer ]: Integer index LVCF_IMAGE or (24 shl 16) read GetLVColEx write SetLVColEx;\r
6215     {* |<#listview>\r
6216        Only starting from comctrl32.dll of version 4.70 (IE4+). Allows to\r
6217        set an image for list view column itself from the ImageListSmall.\r
6218     }\r
6219     property LVColOrder[ Idx: Integer ]: Integer index LVCF_ORDER or (28 shl 16) read GetLVColEx write SetLVColEx;\r
6220     {* |<#listview>\r
6221        Only starting from comctrl32.dll of version 4.70 (IE4+). Allows to\r
6222        set visual order of the list view column from the ImageListSmall.\r
6223        This value does not affect the index, by which the column is still\r
6224        accessible in the column array.\r
6225     }\r
6227     //======== List View items handling:\r
6228     property LVCount: Integer read GetItemsCount write SetItemsCount;\r
6229     {* |<#listview>\r
6230        Returns item count for ListView control. It is possible to use Count\r
6231        property instead when obtaining of item count is needed only. But this this\r
6232        property allows also to set actual count of list view items when a list\r
6233        view is virtual. }\r
6235     property LVCurItem: Integer read GetLVCurItem write SetLVCurItem;\r
6236     {* |<#listview>\r
6237        Returns first selected item index in a list view. See also LVNextSelected\r
6238        and LVNextItem functions. }\r
6240     function LVNextItem( IdxPrev: Integer; Attrs: DWORD ): Integer;\r
6241     {* |<#listview>\r
6242        Returns an index of the next after IdxPrev item with given attributes in\r
6243        the list view. }\r
6244     function LVNextSelected( IdxPrev: Integer ): Integer;\r
6245     {* |<#listview>\r
6246        Returns an index of next (after IdxPrev) selected item in a list view. }\r
6248     function LVAdd( const aText: String; ImgIdx: Integer; State: TListViewItemState;\r
6249                      StateImgIdx, OverlayImgIdx: Integer; Data: DWORD ): Integer;\r
6250     {* |<#listview>\r
6251        Adds new line to the end of ListView control. Only content of item itself\r
6252        is set (aText, ImgIdx). To change other column text and attributes of\r
6253        item added, use appropriate properties / methods ().\r
6254        |<br>\r
6255        Returns an index of added item.\r
6256        |<br>\r
6257        There is no Unicode version defined, use LVItemAddW instead. }\r
6258     function LVItemAdd( const aText: String ): Integer;\r
6259     {* |<#listview>\r
6260        Adds an item to the end of list view. Returns an index of the item added. }\r
6261     {$IFNDEF _FPC}\r
6262     {$IFNDEF _D2}\r
6263     function LVItemAddW( const aText: WideString ): Integer;\r
6264     {* |<#listview>\r
6265        Adds an item to the end of list view. Returns an index of the item added. }\r
6266     {$ENDIF _D2}\r
6267     {$ENDIF _FPC}\r
6268     function LVInsert( Idx: Integer; const aText: String; ImgIdx: Integer;\r
6269               State: TListViewItemState;  StateImgIdx, OverlayImgIdx: Integer; Data: DWORD ): Integer;\r
6270     {* |<#listview>\r
6271        Inserts new line before line with index Idx in ListView control. Only\r
6272        content of item itself is set (aText, ImgIdx). To change other column\r
6273        text and attributes of item added, use appropriate properties / methods ().\r
6274        if ImgIdx = I_IMAGECALLBACK, event handler OnGetLVItemImgIdx is responsible\r
6275        for returning image index for an item ( /// not implemented yet /// )\r
6276        Pass StateImgIdx and OverlayImgIdx = 0 (ignored in that case) or 1..15 to\r
6277        use correspondent icon from ImageListState image list.\r
6278        |<br> Returns an index of item inserted.\r
6279        |<br> There is no unicode version of this method, use LVItemInsertW. }\r
6280     function LVItemInsert( Idx: Integer; const aText: String ): Integer;\r
6281     {* |<#listview>\r
6282        Inserts an item to Idx position. }\r
6283     {$IFNDEF _FPC}\r
6284     {$IFNDEF _D2}\r
6285     function LVItemInsertW( Idx: Integer; const aText: WideString ): Integer;\r
6286     {* |<#listview>\r
6287        Inserts an item to Idx position. }\r
6288     {$ENDIF _D2}\r
6289     {$ENDIF _FPC}\r
6291     procedure LVDelete( Idx: Integer );\r
6292     {* |<#listview>\r
6293        Deletes item of ListView with subitems (full row - in lvsDetail view style. }\r
6294     procedure LVSetItem( Idx, Col: Integer; const aText: String; ImgIdx: Integer;\r
6295               State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer; Data: DWORD );\r
6296     {* |<#listview>\r
6297        Use this method to set item data and item columns data for ListView control.\r
6298        It is possible to pass I_SKIP as ImgIdx, StateImgIdx, OverlayImgIdx values to\r
6299        skip setting this fields. But all other are set always. Like in LVInsert /\r
6300        LVAdd, ImgIdx can be I_IMAGECALLBACK to determine that image will be\r
6301        retrieved in OnGetItemImgIdx event handler when needed.\r
6302        |<br>\r
6303        If this method is called to set data for column > 0, parameters ImgIdx and\r
6304        Data are ignored anyway.\r
6305        |<br> There is no unicode version of this method, use other methods\r
6306        to set up listed properties separately using correspondent W-functions. }\r
6308     property LVItemState[ Idx: Integer ]: TListViewItemState read LVGetItemState write LVSetItemState;\r
6309     {* |<#listview>\r
6310        Access to list view item states set [lvisBlend, lvisHighlight, lvisFocus,\r
6311        lvisSelect]. When assign new value to the property, it is possible to use\r
6312        special index value -1 to change state for all items for a list view\r
6313        (but only when lvoMultiselect style is applied to the list view, otherwise\r
6314        index -1 is referring to the last item of the list view). }\r
6316     property LVItemIndent[ Idx: Integer ]: Integer read LVGetItemIndent write LVSetItemIndent;\r
6317     {* Item indentation. Indentation is calculated as this value multiplied to\r
6318        image list ImgWidth value (Image list must be applied to list view).\r
6319        Note: indentation supported only if IE3.0 or higher installed. }\r
6320     property LVItemStateImgIdx[ Idx: Integer ]: Integer read LVGetSttImgIdx write LVSetSttImgIdx;\r
6321     {* |<#listview>\r
6322        Access to state image of the item. Use index -1 to assign the same state\r
6323        image index to all items of the list view at once (fast).\r
6324        Option lvoCheckBoxes just means, that control itself creates special inner\r
6325        image list for two state images. Later it is possible to examine checked\r
6326        state for items or set checked state programmatically by changing\r
6327        LVItemStateImgIdx[ ] property. Value 1 corresponds to unchecked state,\r
6328        2 to checked. Value 0 allows to remove checkbox at all. So, to check all\r
6329        added items by default (e.g.), do following:\r
6330        ! ListView1.LVItemStateImgIdx[ -1 ] := 2;\r
6331        |<br>Use 1-based index of the image\r
6332        in image list ImageListState. Value 0 reserved to use as "no state image".\r
6333        Values 1..15 can be used only - this is the Windows restriction on\r
6334        state images. }\r
6335     property LVItemOverlayImgIdx[ Idx: Integer ]: Integer read LVGetOvlImgIdx write LVSetOvlImgIdx;\r
6336     {* |<#listview>\r
6337        Access to overlay image of the item. Use index -1 to assign the same\r
6338        overlay image to all items of the list view at once (fast). }\r
6339     property LVItemData[ Idx: Integer ]: DWORD read LVGetItemData write LVSetItemData;\r
6340     {* |<#listview>\r
6341        Access to user defined data, assiciated with the item of the list view. }\r
6342     procedure LVSelectAll;\r
6343     {* |<#listview>\r
6344        Call this method to select all the items of the list view control. }\r
6345     property LVSelCount: Integer read GetSelLength write SetSelLength;\r
6346     {* |<#listview>\r
6347        Returns number of items selected in listview. }\r
6348     property LVItemImageIndex[ Idx: Integer ]: Integer read LVGetItemImgIdx write LVSetItemImgIdx;\r
6349     {* |<#listview>\r
6350        Image index of items in listview. When an item is created (using LVItemAdd\r
6351        or LVItemInsert), image index 0 is set by default (not -1 like in VCL!). }\r
6352     property LVItems[ Idx, Col: Integer ]: String read LVGetItemText write LVSetItemText;\r
6353     {* |<#listview>\r
6354        Access to List View item text. }\r
6355     {$IFNDEF _FPC}\r
6356     {$IFNDEF _D2}\r
6357     property LVItemsW[ Idx, Col: Integer ]: WideString read LVGetItemTextW write LVSetItemTextW;\r
6358     {* |<#listview>\r
6359        Access to List View item text. }\r
6360     {$ENDIF _D2}\r
6361     {$ENDIF _FPC}\r
6362     function LVItemRect( Idx: Integer; Part: TGetLVItemPart ): TRect;\r
6363     {* |<#listview>\r
6364        Returns rectangle occupied by given item part(s) in ListView window.\r
6365        Empty rectangle is returned, if the item is not viewing currently. }\r
6366     function LVSubItemRect( Idx, ColIdx: Integer ): TRect;\r
6367     {* |<#listview>\r
6368        Returns rectangle occupied by given item's subitem in ListView window,\r
6369        in lvsDetail or lvsDetailNoHeader style. Empty rectangle (0,0,0,0) is\r
6370        returned if the item is not viewing currently. Left or/and right bounds\r
6371        of the rectangle returned can be outbound item rectangle if only a part\r
6372        of the subitem is visible or the subitem is not visible in the item,\r
6373        which is visible itself. }\r
6374     property LVItemPos[ Idx: Integer ]: TPoint read LVGetItemPos write LVSetItemPos;\r
6375     {* |<#listview>\r
6376        Position of List View item (can be changed in icon or small icon view). }\r
6377     function LVItemAtPos( X, Y: Integer ): Integer;\r
6378     {* |<#listview>\r
6379        Return index of item at the given position. }\r
6380     function LVItemAtPosEx( X, Y: Integer; var Where: TWherePosLVItem ): Integer;\r
6381     {* |<#listview>\r
6382        Retrieves index of item and sets in Where, what part of item is under\r
6383        given coordinates. If there are no items at the specified position,\r
6384        -1 is returned. }\r
6385     procedure LVMakeVisible( Item: Integer; PartiallyOK: Boolean );\r
6386     {* |<#listview>\r
6387        Makes listview item visible. Ignred when Item passed < 0. }\r
6388     procedure LVEditItemLabel( Idx: Integer );\r
6389     {* |<#listview>\r
6390        Begins in-place editing of item label (first column text). }\r
6391     procedure LVSort;\r
6392     {* |<#listview>\r
6393        Initiates sorting of list view items. This sorting procedure is available only\r
6394        for Win2K, WinNT4 with IE5, Win98 or Win95 with IE5. See also LVSortData. }\r
6395     procedure LVSortData;\r
6396     {* |<#listview>\r
6397        Initiates sorting of list view items. This sorting procedure is always available\r
6398        in Windows95/98, NT/2000. But OnCompareLVItems procedure receives not indexes of\r
6399        items compared but its Data field associated instead. }\r
6400     procedure LVSortColumn( Idx: Integer );\r
6401     {* |<#listview>\r
6402        This is a method to simplify sort by column. Just call it in your OnColumnClick\r
6403        event passing column index and enjoy with your list view sorted automatically\r
6404        when column header is clicked. Requieres Windows2000 or Winows98, not supported\r
6405        under WinNT 4.0 and below and under Windows95.\r
6406        |<br>\r
6407        Either lvoSortAscending or lvoSortDescending option must be set in\r
6408        LVOptions, otherwise no sorting is performed. }\r
6409     function LVIndexOf( const S: String ): Integer;\r
6410     {* Returns first list view item index with caption matching S.\r
6411        The same as LVSearchFor( S, -1, FALSE ). }\r
6412     {$IFNDEF _FPC}\r
6413     {$IFNDEF _D2}\r
6414     function LVIndexOfW( const S: WideString ): Integer;\r
6415     {* Returns first list view item index with caption matching S.\r
6416        The same as LVSearchForW( S, -1, FALSE ). }\r
6417     {$ENDIF _D2}\r
6418     {$ENDIF _FPC}\r
6419     function LVSearchFor( const S: String; StartAfter: Integer; Partial: Boolean ): Integer;\r
6420     {* Searches an item with Caption equal to S (or starting from S, if Partial = TRUE).\r
6421        Searching is started after an item specified by StartAfter parameter. }\r
6422     {$IFNDEF _FPC}\r
6423     {$IFNDEF _D2}\r
6424     function LVSearchForW( const S: WideString; StartAfter: Integer; Partial: Boolean ): Integer;\r
6425     {* Searches an item with Caption equal to S (or starting from S, if Partial = TRUE).\r
6426        Searching is started after an item specified by StartAfter parameter. }\r
6427     {$ENDIF _D2}\r
6428     {$ENDIF _FPC}\r
6430     //======== List view page:\r
6431     property LVTopItem: Integer index LVM_GETTOPINDEX read GetIntVal; //LVGetTopItem;\r
6432     {* |<#listview>\r
6433        Returns index of topmost visible item of ListView in lvsList view style. }\r
6434     property LVPerPage: Integer index LVM_GETCOUNTPERPAGE read GetIntVal; //LVGetPerPage;\r
6435     {* |<#listview>\r
6436        Returns the number of fully-visible items if successful. If the current\r
6437        view is icon or small icon view, the return value is the total number\r
6438        of items in the list view control. }\r
6440     //======== List View specific events:\r
6441     property OnEndEditLVItem: TOnEditLVItem read fOnEditLVITem write SetOnEditLVItem;\r
6442     {* |<#listview>\r
6443        Called when edit of an item label in ListView control finished. Return\r
6444        True to accept new label text, or false - to not accept it (item label\r
6445        will not be changed). If handler not set to an event, all changes are\r
6446        accepted. }\r
6448     property OnDeleteLVItem: TOnDeleteLVItem read fOnDeleteLVItem write SetOnDeleteLVItem;\r
6449     {* |<#listview>\r
6450        Called for every deleted list view item. }\r
6451     property OnDeleteAllLVItems: TOnEvent read fOnDeleteAllLVItems write SetOnDeleteAllLVItems;\r
6452     {* |<#listview>\r
6453        Called when all the items of the list view control are to be deleted. If after\r
6454        returning from this event handler event OnDeleteLVItem is yet assigned,\r
6455        an event OnDeleteLVItem will be called for every deleted item. }\r
6456     property OnLVData: TOnLVData read fOnLVData write SetOnLVData;\r
6457     {* |<#listview>\r
6458        Called to provide virtual list view with actual data. To use list view as\r
6459        virtaul list view, define also lvsOwnerData style and set Count property\r
6460        to actual row count of the list view. This manner of working with list view\r
6461        control can greatly improve performance of an application when working with\r
6462        huge data sets represented in listview control. }\r
6463     {$IFNDEF _FPC}\r
6464     {$IFNDEF _D2}\r
6465     property OnLVDataW: TOnLVDataW read fOnLVDataW write SetOnLVDataW;\r
6466     {* |<#listview>\r
6467        The same as OnLVData, but for unicode version of the list view allows\r
6468        to return WideString text in the event handler. Though for unicode list\r
6469        view it is still possible to use ordinary event OnLVData, it is\r
6470        very recommended to use this event istead. }\r
6471     {$ENDIF _D2}\r
6472     {$ENDIF _FPC}\r
6474     property OnCompareLVItems: TOnCompareLVItems read fOnCompareLVItems write fOnCompareLVItems;\r
6475     {* |<#listview>\r
6476        Event to compare two list view items during sort operation (initiated by\r
6477        LVSort method call). Do not send any messages to the list view control\r
6478        while it is sorting - results can be unpredictable! }\r
6479     property OnColumnClick: TOnLVColumnClick read fOnColumnClick write SetOnColumnClick;\r
6480     {* |<#listview>\r
6481        This event handler is called when column of the list view control is clicked.\r
6482        You can use this event to initiate sorting of list view items by this column. }\r
6483     property OnLVStateChange: TOnLVStateChange read FOnLVStateChange write SetOnLVStateChange;\r
6484     {* |<#listview>\r
6485        This event occure when an item or items range in list view control are\r
6486        changing its state (e.g. selected or unselected). }\r
6487     property OnLVDelete: TOnLVDelete read FOnLVDelete write SetOnLVDelete;\r
6488     {* |<#listview>\r
6489        This event is called when an item is deleted in the listview.\r
6490        Do not add, delete, or rearrange items in the list view while processing\r
6491        this notification. }\r
6492     property OnDrawItem: TOnDrawItem read fOnDrawItem write SetOnDrawItem;\r
6493     {* |<#listview>\r
6494        |<#listbox>\r
6495        |<#combo>\r
6496        This event can be used to implemet custom drawing for list view, list box, dropped\r
6497        list of a combobox. For a list view, custom drawing using this event is possible\r
6498        only in lvsDetail and lvsDetailNoHeader styles, and OnDrawItem is called to draw\r
6499        entire row at once only. See also OnLVCustomDraw event. }\r
6501     property OnLVCustomDraw: TOnLVCustomDraw read FOnLVCustomDraw write SetOnLVCustomDraw;\r
6502     {* |<#listview>\r
6503        Custom draw event for listview. For every item to be drawn, this event\r
6504        can be called several times during a single drawing cycle - depending on\r
6505        a result, returned by an event handler. Stage can have one of following\r
6506        values:\r
6507        |<pre>\r
6508        CDDS_PREERASE\r
6509        CDDS_POSTERASE\r
6510        CDDS_ITEMPREERASE\r
6511        CDDS_PREPAINT\r
6512        CDDS_ITEMPREPAINT\r
6513        CDDS_ITEM\r
6514        CDDS_SUBITEM + CDDS_ITEMPREPAINT\r
6515        CDDS_SUBITEM + CDDS_ITEMPOSTPAINT\r
6516        CDDS_ITEMPOSTPAINT\r
6517        CDDS_POSTPAINT\r
6518        </pre>\r
6519        When called, see on Stage to get know, on what stage the event is\r
6520        activated. And depend on the stage and on what you want to paint,\r
6521        return a value as a result, which instructs the system, if to use\r
6522        default drawing on this (and follows) stage(s) for the item, and if\r
6523        to notify further about different stages of drawing the item during\r
6524        this drawing cycle. Possible values to return are:\r
6525        |<pre>\r
6526        CDRF_DODEFAULT - perform default drawing. Do not notify further for this\r
6527                       item (subitem) (or for entire listview, if called with\r
6528                       flag CDDS_ITEM reset - ?);\r
6529        CDRF_NOTIFYITEMDRAW - return this value, when the event is called the\r
6530                       first time in a cycle of drawing, with ItemIdx = -1 and\r
6531                       flag CDDS_ITEM reset in Stage parameter;\r
6532        CDRF_NOTIFYPOSTERASE - usually can be used to provide default erasing,\r
6533                       if you want to perform drawing immediately after that;\r
6534        CDRF_NOTIFYPOSTPAINT - return this value to provide calling the event\r
6535                       after performing default drawing. Useful when you wish\r
6536                       redraw only a part of the (sub)item;\r
6537        CDRF_SKIPDEFAULT - return this value to inform the system that all\r
6538                       drawing is done and system should not peform any more\r
6539                       drawing for the (sub)item during this drawing cycle.\r
6540        CDRF_NEWFONT - informs the system, that font is changed and default\r
6541                       drawing should be performed with changed font;\r
6542        |</pre>\r
6543        If you want to get notifications for each subitem, do not use option\r
6544        lvoOwnerDrawFixed, because such style prevents system from notifying\r
6545        the application for each subitem to be drawn in the listview and only\r
6546        notifications will be sent about entire items.\r
6547        |<br>\r
6548        See also NM_CUSTOMDRAW in API Help.\r
6549     }\r
6551     procedure Set_LVItemHeight(Value: Integer);\r
6552     function SetLVItemHeight(Value: Integer): PControl;\r
6553     property LVItemHeight: Integer read fLVItemHeight write Set_LVItemHeight;\r
6556     //======== TreeView specific properties and methods:\r
6557     function TVInsert( nParent, nAfter: THandle; const Txt: String ): THandle;\r
6558     {* |<#treeview>\r
6559        Inserts item to a tree view. If nParent is 0 or TVI_ROOT, the item is\r
6560        inserted at the root of tree view. It is possible to pass following special\r
6561        values as nAfter parameter:\r
6562        |<pre>\r
6563        TVI_FIRST        Inserts the item at the beginning of the list.\r
6564        TVI_LAST         Inserts the item at the end of the list.\r
6565        TVI_SORT         Inserts the item into the list in alphabetical order.\r
6566        |</pre> }\r
6567     {$IFNDEF _FPC}\r
6568     {$IFNDEF _D2}\r
6569     function TVInsertW( nParent, nAfter: THandle; const Txt: WideString ): THandle;\r
6570     {* |<#treeview>\r
6571        Inserts item to a tree view. If nParent is 0 or TVI_ROOT, the item is\r
6572        inserted at the root of tree view. It is possible to pass following special\r
6573        values as nAfter parameter:\r
6574        |<pre>\r
6575        TVI_FIRST        Inserts the item at the beginning of the list.\r
6576        TVI_LAST         Inserts the item at the end of the list.\r
6577        TVI_SORT         Inserts the item into the list in alphabetical order.\r
6578        |</pre><br>\r
6579        This version of the method is Unicode. The tree view control should be\r
6580        set up as unicode control calling Perform( TVM_SETUNICODEFORMAT, 1, 0 ),\r
6581        and conditional symbol UNICODE_CTRLS must be defined to provide event\r
6582        handling for such kind of tree view (and other Unicode) controls. }\r
6583     {$ENDIF _D2}\r
6584     {$ENDIF _FPC}\r
6585     procedure TVDelete( Item: THandle );\r
6586     {* |<#treeview>\r
6587        Removes an item from the tree view. If value TVI_ROOT is passed, all items\r
6588        are removed. }\r
6590     property TVSelected: THandle index TVGN_CARET read TVGetItemIdx write TVSetItemIdx;\r
6591     {* |<#treeview>\r
6592        Returns or sets currently selected item handle in tree view. }\r
6594     property TVDropHilighted: THandle index TVGN_DROPHILITE read TVGetItemIdx write TVSetItemIdx;\r
6595     {* |<#treeview>\r
6596        Returns or sets item, which is currently highlighted as a drop target. }\r
6597     property TVDropHilited: THandle index TVGN_DROPHILITE read TVGetItemIdx write TVSetItemIdx;\r
6598     {* The same as TVDropHilighted. }\r
6599     property TVFirstVisible: THandle index TVGN_FIRSTVISIBLE read TVGetItemIdx write TVSetItemIdx;\r
6600     {* |<#treeview>\r
6601        Returns or sets given item to top of tree view. }\r
6603     property TVIndent: Integer index TVM_GETINDENT read GetIntVal write SetIntVal;\r
6604     {* |<#treeview>\r
6605        The amount, in pixels, that child items are indented relative to their\r
6606        parent items. }\r
6607     property TVVisibleCount: Integer index TVM_GETVISIBLECOUNT read GetIntVal;\r
6608     {* |<#treeview>\r
6609        Returns number of fully (not partially) visible items in tree view. }\r
6611     property TVRoot: THandle index TVGN_ROOT read TVGetItemIdx;\r
6612     {* |<#treeview>\r
6613        Returns handle of root item in tree view (or 0, if tree is empty). }\r
6614     property TVItemChild[ Item: THandle ]: THandle index TVGN_CHILD read TVGetItemNext;\r
6615     {* |<#treeview>\r
6616        Returns first child item for given one. }\r
6617     property TVItemHasChildren[ Item: THandle ]: Boolean read TV_GetItemHasChildren write TV_SetItemHasChildren;\r
6618     {* |<#treeview>\r
6619        TRUE, if an Item has children. Set this value to true if you want to\r
6620        force [+] sign appearing left from the node, even if there are no\r
6621        subnodes added to the node yet. }\r
6622     property TVItemChildCount[ Item: THandle ]: Integer read TV_GetItemChildCount;\r
6623     {* |<#treeview>\r
6624        Returns number of node child items in tree view.\r
6625     }\r
6626     property TVItemNext[ Item: THandle ]: THandle index TVGN_NEXT read TVGetItemNext;\r
6627     {* |<#treeview>\r
6628        Returns next sibling item handle for given one (or 0, if passed item is\r
6629        the last child for its parent node). }\r
6630     property TVItemPrevious[ Item: THandle ]: THandle index TVGN_PREVIOUS read TVGetItemNext;\r
6631     {* |<#treeview>\r
6632        Returns previous sibling item (or 0, if the is no such item). }\r
6633     property TVItemNextVisible[ Item: THandle ]: THandle index TVGN_NEXTVISIBLE read TVGetItemNext;\r
6634     {* |<#treeview>\r
6635        Returns next visible item (passed item must be visible too, to determine,\r
6636        if it is really visible, use property TVItemRect or TVItemVisible. }\r
6637     property TVItemPreviousVisible[ Item: THandle ]: THandle index TVGN_PREVIOUSVISIBLE read TVGetItemNext;\r
6638     {* |<#treeview>\r
6639        Returns previous visible item. }\r
6640     property TVItemParent[ Item: THandle ]: THandle index TVGN_PARENT read TVGetItemNext;\r
6641     {* |<#treeview>\r
6642        Returns parent item for given one (or 0 for root item). }\r
6644     property TVItemText[ Item: THandle ]: String read TVGetItemText write TVSetItemText;\r
6645     {* |<#treeview>\r
6646        Text of tree view item. }\r
6647     {$IFNDEF _FPC}\r
6648     {$IFNDEF _D2}\r
6649     property TVItemTextW[ Item: THandle ]: WideString read TVGetItemTextW write TVSetItemTextW;\r
6650     {* |<#treeview>\r
6651        Text of tree view item. }\r
6652     {$ENDIF _D2}\r
6653     {$ENDIF _FPC}\r
6654     function TVItemPath( Item: THandle; Delimiter: Char ): String;\r
6655     {* |<#treeview>\r
6656        Returns full path from the root item to given item. Path is calculated\r
6657        as a concatenation of all parent nodes text strings, separated by\r
6658        given delimiter character.\r
6659        |<br>Please note, that returned path has no trailing delimiter, this\r
6660        character is only separating different parts of the path.\r
6661        |<br>If Item is not specified ( =0 ), path is returned\r
6662        for Selected item. }\r
6663     {$IFNDEF _FPC}\r
6664     {$IFNDEF _D2}\r
6665     function TVItemPathW( Item: THandle; Delimiter: WideChar ): WideString;\r
6666     {* |<#treeview>\r
6667        Returns full path from the root item to given item. Path is calculated\r
6668        as a concatenation of all parent nodes text strings, separated by\r
6669        given delimiter character. If Item is not specified ( =0 ), path is returned\r
6670        for Selected item. }\r
6671     {$ENDIF _D2}\r
6672     {$ENDIF _FPC}\r
6674     property TVItemRect[ Item: THandle; TextOnly: Boolean ]: TRect read TVGetItemRect;\r
6675     {* |<#treeview>\r
6676        Returns rectangle, occupied by an item in tree view. }\r
6678     property TVItemVisible[ Item: THandle ]: Boolean read TVGetItemVisible write TVSetITemVisible;\r
6679     {* |<#treeview>\r
6680        Returs True, if item is visible in tree view. It is also possible to\r
6681        assign True to this property to ensure that a tree view item is visible\r
6682        (if False is assigned, this does nothing). }\r
6683     function TVItemAtPos( x, y: Integer; var Where: DWORD ): THandle;\r
6684     {* |<#treeview>\r
6685        Returns handle of item found at specified position (relative to upper left\r
6686        corener of client area of the tree view). If no item found, 0 is returned.\r
6687        Variable Where receives additional flags combination, describing more\r
6688        detailed, on which part of item or tree view given point is located,\r
6689        such as:\r
6690        |<pre>\r
6691        TVHT_ABOVE              Above the client area\r
6692        TVHT_BELOW              Below the client area\r
6693        TVHT_NOWHERE            In the client area, but below the last item\r
6694        TVHT_ONITEM             On the bitmap or label associated with an item\r
6695        TVHT_ONITEMBUTTON       On the button associated with an item\r
6696        TVHT_ONITEMICON         On the bitmap associated with an item\r
6697        TVHT_ONITEMINDENT       In the indentation associated with an item\r
6698        TVHT_ONITEMLABEL        On the label (string) associated with an item\r
6699        TVHT_ONITEMRIGHT        In the area to the right of an item\r
6700        TVHT_ONITEMSTATEICON    On the state icon for a tree-view item that is in a user-defined state\r
6701        TVHT_TOLEFT             To the right of the client area\r
6702        TVHT_TORIGHT            To the left of the client area\r
6703        |</pre> }\r
6705     property TVRightClickSelect: Boolean read fTVRightClickSelect write SetTVRightClickSelect;\r
6706     {* |<#treeview>\r
6707        Set this property to True to allow change selection to an item, clicked with right mouse button. }\r
6708     property TVEditing: Boolean read fEditing;\r
6709     {* |<#treeview>\r
6710        Returns True, if tree view control is editing its item label. }\r
6712     property TVItemBold[ Item: THandle ]: Boolean index TVIS_BOLD read TVGetItemStateFlg write TVSetItemStateFlg;\r
6713     {* |<#treeview>\r
6714        True, if item is bold. }\r
6715     property TVItemCut[ Item: THandle ]: Boolean index TVIS_CUT read TVGetITemStateFlg write TVSetItemStateFlg;\r
6716     {* |<#treeview>\r
6717        True, if item is selected as part of "cut and paste" operation. }\r
6718     property TVItemDropHighlighted[ Item: THandle ]: Boolean index TVIS_DROPHILITED read TVGetITemStateFlg write TVSetItemStateFlg;\r
6719     {* |<#treeview>\r
6720        True, if item is selected as drop target. }\r
6721     property TVItemDropHilited[ Item: THandle ]: Boolean index TVIS_DROPHILITED read TVGetITemStateFlg write TVSetItemStateFlg;\r
6722     {* The same as TVItemDropHighlighted. }\r
6723     property TVItemExpanded[ Item: THandle ]: Boolean index TVIS_EXPANDED read TVGetITemStateFlg; // write TVSetItemStateFlg;\r
6724     {* |<#treeview>\r
6725        True, if item's list of child items is currently expanded. To change\r
6726        expanded state, use method TVExpand. }\r
6727     property TVItemExpandedOnce[ Item: THandle ]: Boolean index TVIS_EXPANDEDONCE read TVGetITemStateFlg; // write TVSetItemStateFlg;\r
6728     {* |<#treeview>\r
6729        True, if item's list of child items has been expanded at least once. }\r
6730     property TVItemSelected[ Item: THandle ]: Boolean index TVIS_SELECTED read TVGetITemStateFlg write TVSetItemStateFlg;\r
6731     {* |<#treeview>\r
6732        True, if item is selected. }\r
6734     procedure TVExpand( Item: THandle; Flags: DWORD );\r
6735     {* |<#treeview>\r
6736        Call it to expand/collapse item's child nodes. Possible values for Flags\r
6737        parameter are:\r
6738        <pre>\r
6739        TVE_COLLAPSE         Collapses the list.\r
6740        TVE_COLLAPSERESET    Collapses the list and removes the child items. Note\r
6741                             that TVE_COLLAPSE must also be specified.\r
6742        TVE_EXPAND           Expands the list.\r
6743        TVE_TOGGLE           Collapses the list if it is currently expanded or\r
6744                             expands it if it is currently collapsed.\r
6745        </pre>\r
6746        }\r
6747     procedure TVSort( N: THandle );\r
6748     {* |<#treeview>\r
6749        By Alex Mokrov. Sorts treeview. If N = 0, entire treeview is sorted.\r
6750        Otherwise, children of the given node only.\r
6751     }\r
6753     property TVItemImage[ Item: THandle ]: Integer index TVIF_IMAGE read TVGetItemImage write TVSetItemImage;\r
6754     {* |<#treeview>\r
6755        Image index for an item of tree view. To tell that there are no image\r
6756        set, use index -2 (value -1 is reserved for callback image). }\r
6757     property TVItemSelImg[ Item: THandle ]: Integer index TVIF_SELECTEDIMAGE read TVGetItemImage write TVSetItemImage;\r
6758     {* |<#treeview>\r
6759        Image index for an item of tree view in selected state. Use value -2 to\r
6760        provide no image, -1 used for callback image. }\r
6761     property TVItemOverlay[ Item: THandle ]: Integer index TVIS_OVERLAYMASK or $80000\r
6762                              read TVGetItemImage write TVSetItemImage;\r
6763     {* |<#treeview>\r
6764        Overlay image index for an item in tree view. }\r
6765     property TVItemStateImg[ Item: THandle ]: Integer index TVIS_STATEIMAGEMASK or $C0000\r
6766                               read TVGetItemImage write TVSetItemImage;\r
6767     {* |<#treeview>\r
6768        State image index for an item in tree view. Use 1-based index of the image\r
6769        in image list ImageListState. Value 0 reserved to use as "no state image".\r
6770        Values 1..15 can be used only - this is the Windows restriction on\r
6771        state images. }\r
6773     property TVItemData[ Item: THandle ]: Pointer read TVGetItemData write TVSetItemData;\r
6774     {* |<#treeview>\r
6775        Stores any program-defined pointer with the item. }\r
6776     procedure TVEditItem( Item: THandle );\r
6777     {* |<#treeview>\r
6778        Begins editing given item label in tree view. }\r
6779     procedure TVStopEdit( Cancel: Boolean );\r
6780     {* |<#treeview>\r
6781        Ends editing item label, started by user or explicitly by TVEditItem method. }\r
6783     property OnTVBeginDrag: TOnTVBeginDrag read fOnTVBeginDrag write fOnTVBeginDrag;\r
6784     {* |<#treeview>\r
6785        Is called for tree view, when its item is to be dragging. }\r
6786     property OnTVBeginEdit: TOnTVBeginEdit read fOnTVBeginEdit write fOnTVBeginEdit;\r
6787     {* |<#treeview>\r
6788        Is called for tree view, when its item label is to be editing. }\r
6789     property OnTVEndEdit: TOnTVEndEdit read fOnTVEndEdit write fOnTVEndEdit;\r
6790     {* |<#treeview>\r
6791        Is called when item label is edited. It is possible to cancel\r
6792        edit, returning False as a result. }\r
6793     property OnTVExpanding: TOnTVExpanding read fOnTVExpanding write fOnTVExpanding;\r
6794     {* |<#treeview>\r
6795        Is called just before expanding/collapsing item. It is possible to\r
6796        return False to prevent expanding item. }\r
6797     property OnTVExpanded: TOnTVExpanded read fOnTVExpanded write fOnTVExpanded;\r
6798     {* |<#treeview>\r
6799        Is called after expanding/collapsing item children. }\r
6800     property OnTVDelete: TOnTVDelete read fOnTVDelete write SetOnTVDelete;\r
6801     {* |<#treeview>\r
6802        Is called just before deleting item. You may use this event to free\r
6803        resources, associated with an item (see TVItemData property). }\r
6804     //----------------- by Sergey Shisminzev:\r
6805     property OnTVSelChanging: TOnTVSelChanging read fOnTVSelChanging write fOnTVSelChanging;\r
6806     {* |<#treeview>\r
6807        Is called before changing the selection. The handler can return FALSE\r
6808        to prevent changing the selection. }\r
6809     //--------------------------------------\r
6811     //======== Toolbar specific methods:\r
6812     procedure TBAddBitmap( Bitmap: HBitmap );\r
6813     {* |<#toolbar>\r
6814        Adds bitmaps to a toolbar. You can pass special values as Bitmap to\r
6815        add one of predefined system button images bitmaps:\r
6816        |<br> THandle(-1) to add standard small icons,\r
6817        |<br> THandle(-2) to add standard large icons,\r
6818        |<br> THandle(-5) to add standard small view icons,\r
6819        |<br> THandle(-6) to add standard large view icons,\r
6820        |<br> THandle(-9) to add standard small view icons,\r
6821        |<br> THandle(-10) to add standard large view icons,\r
6822        (in that case use following values as indexes to the standard and view\r
6823        bitmaps:\r
6824        |<br>\r
6825        STD_COPY, STD_CUT, STD_DELETE, STD_FILENEW, STD_FILEOPEN, STD_FILESAVE,\r
6826        STD_FIND, STD_HELP, STD_PASTE, STD_PRINT, STD_PRINTPRE, STD_PROPERTIES,\r
6827        STD_REDO, STD_REPLACE, STD_UNDO,\r
6828        |<br>\r
6829        VIEW_LARGEICONS, VIEW_SMALLICONS,\r
6830        VIEW_LIST, VIEW_DETAILS, VIEW_SORTNAME, VIEW_SORTSIZE, VIEW_SORTDATE,\r
6831        VIEW_SORTTYPE (use it as parameters BtnImgIdxArray in TBAddButtons or\r
6832        TBInsertButtons methods, and in assigning value to TBButtonImage[ ]\r
6833        property).\r
6834        Added bitmaps have indeces starting from previous count of images\r
6835        (as these are appended to existing - if any).\r
6836        |<br>\r
6837        Note, that if You add your own (custom) bitmap, it is not transparent.\r
6838        Do not assume that clSilver is always equal to clBtnFace. Use API\r
6839        function CreateMappedBitmap to load bitmap from resource and map\r
6840        desired colors as you wish (e.g., convert clTeal to clBtnFace). Or,\r
6841        call defined in KOL function LoadMappedBitmap to do the same more easy.\r
6842        Unfortunately, resource identifier for bitmap to pass it to LoadMappedBitmap\r
6843        or to CreateMappedBitmap seems must be integer, so it is necessary to\r
6844        create rc-file manually and compile using Borland Resource Compiler to\r
6845        figure it out. }\r
6848     function TBAddButtons( const Buttons: array of PChar; const BtnImgIdxArray: array\r
6849               of Integer ): Integer;\r
6850     {* |<#toolbar>\r
6851        Adds buttons to toolbar. Last string in Buttons array *must* be empty\r
6852        ('' or nil), so to add buttons without text, pass ' ' string (one space\r
6853        char). It is not necessary to provide image indexes for all\r
6854        buttons (it is sufficient to assign index for first button only).\r
6855        But in place, correspondent to separator button (defined by string '-'),\r
6856        any integer must be passed to assign follow image indexes correctly.\r
6857        See example.\r
6858        |*Toolbar adding buttons sample.\r
6859        Code below shows how to call TBAddButtons method to add two buttons with\r
6860        a separator between these buttons. idxNew and idxOld are integer\r
6861        expressions assigning image indexes to buttons 'New' and 'Old'. This\r
6862        indexes are zero-based and refer to bitmap images, added earlier (either\r
6863        in creating toolbar by call of NewToolbar or later in call of TBAddBitmap).\r
6864        !\r
6865        !     TBAddButtons( [ '&New', '-', '&Old', '' ], [ idxNew, 0, idxOld ] );\r
6866        !\r
6867        |*\r
6868        To add check buttons, use prefix '+' or '-' in button definition\r
6869        string. If next character is '!', such buttons are grouped to a\r
6870        radio-group. Also, it is possible to use '^' prefix (must be first) to\r
6871        define button with small drop-down section (use also OnTBDropDown event\r
6872        to respond to clicking drop down section of such buttons).\r
6873        |<br>\r
6874        This function returns command id for first added button (other\r
6875        id's can be calculated incrementing the result by one for each\r
6876        button, except separators, which have no command id).\r
6877        |<br>\r
6878        Note: for static toolbar (single in application and created\r
6879        once) ids are started from value 100. }\r
6881     function TBInsertButtons( BeforeIdx: Integer; Buttons: array of PChar;\r
6882              BtnImgIdxArray: array of Integer ): Integer;\r
6883     {* |<#toolbar>\r
6884        Inserts buttons before button with given index on toolbar. Returns\r
6885        command identifier for first button inserted (other can be calculated\r
6886        incrementing returned value needed times. See also TBAddButtons. }\r
6888     procedure TBDeleteButton( BtnID: Integer );\r
6889     {* |<#toolbar>\r
6890        Deletes single button given by its command id. To delete separator,\r
6891        use TBDeleteBtnByIdx instead. }\r
6893     procedure TBDeleteBtnByIdx( Idx: Integer );\r
6894     {* |<#toolbar>\r
6895        Deletes single button given by its index in toolbar (not by command ID). }\r
6897     procedure TBAssignEvents( BtnID: Integer; Events: array of TOnToolbarButtonClick );\r
6898     {* |<#toolbar>\r
6899        Allows to assign separate OnClick events for every toolbar button.\r
6900        BtnID should be toolbar button ID or index of the first button to\r
6901        assign event. If it is an ID, events are assigned to buttons in\r
6902        creation order. Otherwise, events are assigned in placement order.\r
6903        Anyway, separator buttons are not skipped, so pass at least nil for such\r
6904        button as an event.\r
6905        |<br>\r
6906        Please note, that though not all buttons should exist before\r
6907        assigning events to it, therefore at least the first button\r
6908        (specified by BtnID) must be already added before calling TBAssignEvents. }\r
6910     procedure TBResetImgIdx( BtnID, BtnCount: Integer );\r
6911     {* |<#toolbar>\r
6912        Resets image index for BtnCount buttons starting from BtnID. }\r
6914     property CurItem: Integer read fCurItem;\r
6915     {* |<#toolbar>\r
6916        For toolbar, in OnClick event this property can be used to determine\r
6917        which button was clicked (100-based button id in toolbar). It is also\r
6918        possible to use CurIndex property (zero-based) for this purpose as\r
6919        well, but do not assume, that CurItem always equal to CurIndex+100.\r
6920        At least, it is possible to call TBItem2Index function to convert\r
6921        button ID to its index in toolbar.\r
6922        |<br>\r
6923        In case, when button (or toolbar itself) is clicked using right\r
6924        mouse button, CurItem and CurIndex are always set to -1. To further\r
6925        determine which button was clicked, get mouse coordinates on screen,\r
6926        apply Screen2Client method of toolbar control to it and then use\r
6927        TBButtonAtPos function to determine which button was under cursor.\r
6928     }\r
6930     property TBButtonCount: Integer read GetItemsCount; //TBGetButtonCount;\r
6931     {* |<#toolbar>\r
6932        Returns count of buttons on toolbar. The same as Count. }\r
6934     property TBBtnImgWidth: Integer read fTBBtnImgWidth write fTBBtnImgWidth;\r
6935     {* |<#toolbar>\r
6936        Custom toolbar buttons width. Set it before assigning buttons bitmap.\r
6937        Changing this property after assigning the bitmap has no effect. }\r
6939     function TBItem2Index( BtnID: Integer ): Integer;\r
6940     {* |<#toolbar>\r
6941        Converts button command id to button index for tool bar. }\r
6943     function TBIndex2Item( Idx: Integer ): Integer;\r
6944     {* |<#toolbar>\r
6945        Converts toolbar button index to its command ID. }\r
6947     property TBButtonEnabled[ BtnID: Integer ]: Boolean index TB_ENABLEBUTTON\r
6948              read TBGetBtnStt write TBSetBtnStt;\r
6949     {* |<#toolbar>\r
6950        Obvious. }\r
6952     property TBButtonVisible[ BtnID: Integer ]: Boolean read TBGetButtonVisible\r
6953                               write TBSetButtonVisible;\r
6954     {* |<#toolbar>\r
6955        Allows to hide/show some of toolbar buttons. }\r
6957     property TBButtonChecked[ BtnID: Integer ]: Boolean index TB_CHECKBUTTON\r
6958              read TBGetBtnStt write TBSetBtnStt;\r
6959     {* |<#toolbar>\r
6960        Allows to determine 'checked' state of a button (e.g., radio-button),\r
6961        and to check it programmatically. }\r
6963     property TBButtonMarked[ BtnID: Integer ]: Boolean index TB_MARKBUTTON\r
6964              read TBGetBtnStt write TBSetBtnStt;\r
6965     {* |<#toolbar>\r
6966        Returns True if toolbar button is marked (highlighted). Allows to\r
6967        highlight buttons assigning True to this value. }\r
6969     property TBButtonPressed[ BtnID: Integer ]: Boolean index TB_PRESSBUTTON\r
6970              read TBGetBtnStt write TBSetBtnStt;\r
6971     {* |<#toolbar>\r
6972        Allows to detrmine if toolbar button (given by its command ID) pressed,\r
6973        and press/unpress it programmatically. }\r
6975     property TBButtonText[ BtnID: Integer ]: String read TBGetButtonText write TBSetButtonText;\r
6976     {* |<#toolbar>\r
6977        Obtains toolbar button text and allows to change it. Be sure that text\r
6978        is not empty for all buttons, if You want for it to be shown (if at least\r
6979        one button has empty text, no text labels will be shown at all). At\r
6980        least set it to ' ' for buttons, which You do not want to show labels,\r
6981        if You want from other ones to have it. }\r
6983     property TBButtonImage[ BtnID: Integer ]: Integer read TBGetBtnImgIdx write TBSetBtnImgIdx;\r
6984     {* |<#toolbar>\r
6985        Allows to access/change button image. }\r
6987     property TBButtonRect[ BtnID: Integer ]: TRect read TBGetButtonRect;\r
6988     {* |<#toolbar>\r
6989        Obtains rectangle occupied by toolbar button in toolbar window.\r
6990        (It is not possible to obtain rectangle for buttons, currently\r
6991        not visible). }\r
6993     property TBButtonWidth[ BtnID: Integer ]: Integer read TBGetBtnWidth write TBSetBtnWidth;\r
6994     {* |<#toolbar>\r
6995        Allows to obtain / change toolbar button width. }\r
6997     property TBButtonsMinWidth: Integer index 0\r
6998              {$IFDEF F_P}   read TBGetBtMinMaxWidth\r
6999              {$ELSE DELPHI} read FTBBtMinWidth\r
7000              {$ENDIF F_P/DELPHI} write TBSetBtMinMaxWidth;\r
7001     {* |<#toolbar>\r
7002        Allows to set minimal width for all toolbar buttons. }\r
7003     property TBButtonsMaxWidth: Integer index 1\r
7004              {$IFDEF F_P}   read TBGetBtMinMaxWidth\r
7005              {$ELSE DELPHI} read FTBBtMaxWidth\r
7006              {$ENDIF F_P/DELPHI} write TBSetBtMinMaxWidth;\r
7007     {* |<#toolbar>\r
7008        Allows to set maximal width for all toolbar buttons. }\r
7010     function TBButtonAtPos( X, Y: Integer ): Integer;\r
7011     {* |<#toolbar>\r
7012        Returns command ID of button at the given position on toolbar,\r
7013        or -1, if there are no button at the position. Value 0 is returned\r
7014        for separators. }\r
7016     function TBBtnIdxAtPos( X, Y: Integer ): Integer;\r
7017     {* |<#toolbar>\r
7018        Returns index of button at the given position on toolbar.\r
7019        This also can be index of separator button. -1 is returned if\r
7020        there are no buttons found at the position. }\r
7022     property TBRows: Integer read TBGetRows write TBSetRows;\r
7023     {* |<#toolbar>\r
7024        Returns number of rows for toolbar and allows to try to set\r
7025        desired number of rows (but system can set another number of\r
7026        rows in some cases). This property has no effect if tboWrapable\r
7027        style not present in Options when toolbar is created. }\r
7029     procedure TBSetTooltips( BtnID1st: Integer; Tooltips: array of PChar );\r
7030     {* |<#toolbar>\r
7031        Allows to assign tooltips to several buttons. Until this procedure\r
7032        is not called, tooltips list is not created and no code is added\r
7033        to executable. This method of tooltips maintainance for toolbar buttons\r
7034        is useful both for static and dynamic toolbars (meaning "dynamic" -\r
7035        toolbars with buttons, deleted and inserted at run-time). }\r
7037     property OnTBDropDown: TOnEvent read fOnDropDown write fOnDropDown;\r
7038     {* |<#toolbar>\r
7039        This event is called for drop down buttons, when user click drop part\r
7040        of drop down button. To determine for which button event is called,\r
7041        look at CurItem or CurIndex property. It is also possible to use\r
7042        common (with combobox) property OnDropDown. }\r
7044     property OnTBClick: TOnEvent read fOnClick write fOnClick;\r
7045     {* |<#toolbar>\r
7046        The same as OnClick. }\r
7048     //================== RichEdit specific: ==================\r
7050     property MaxTextSize: DWORD read GetMaxTextSize write SetMaxTextSize;\r
7051     {* |<#richedit>\r
7052        This property valid also for simple edit control, not only for RichEdit.\r
7053        But for usual edit control, maximum text size available is 32K. For\r
7054        RichEdit, limit is 4Gb. By default, RichEdit is limited to\r
7055        32767 bytes (to set maximum size available to 2Gb, assign MaxInt value\r
7056        to a property). Also, to get current text size of RichEdit, use property\r
7057        TextSize or RE_TextSize[ ]. }\r
7058     property TextSize: Integer read GetTextSize;\r
7059     {* |<#richedit>\r
7060        Common for edit and rich edit controls property, which returns size of\r
7061        text in edit control. Also, for any other control (or form, or applet\r
7062        window) returns size (in characters) of Caption or Text (what is, the\r
7063        same property actually). }\r
7064     property RE_TextSize[ Units: TRichTextSize ]: Integer read REGetTextSize;\r
7065     {* |<#richedit>\r
7066        For RichEdit control, it returns text size, measured in desired units\r
7067        (rtsChars - characters, including OLE objects, counted as a single\r
7068        character; rtsBytes - presize length of text image (if it would be stored\r
7069        in file or stream). Please note, that for RichEdit1.0, only size in\r
7070        characters can be obtained. }\r
7071     function RE_TextSizePrecise: Integer;\r
7072     {* |<#richedit>\r
7073        By Savva. Returns length of rich edit text. }\r
7075     property RE_CharFmtArea: TRichFmtArea read fRECharArea write fRECharArea;\r
7076     {* |<#richedit>\r
7077        By default, this property is raSelection. Changing it, You determine in\r
7078        for which area characters format is applyed, when changing\r
7079        character formatting properties below (not paragraph formatting).\r
7080        |&A=<a href=#RE_CharFmtArea target=main>%0</a>\r
7081     }\r
7082     property RE_CharFormat: TCharFormat read REGetCharformat write RESetCharFormat;\r
7083     {* |<#richedit>\r
7084        In differ to follow properties, which allow to control certain formatting\r
7085        attributes, this property provides low level access for formatting current\r
7086        character area (see RE_CharFmtArea). It returns TCharFormat structure,\r
7087        filled in with formatting attributes, and by assigning another value to\r
7088        this property You can change desired attributes as You wish. Even if\r
7089        RichEdit1.0 is used, TCharFormat2 is returned (but extended fields are\r
7090        ignored for RichEdit1.0). }\r
7091     property RE_Font: PGraphicTool read REGetFont write RESetFont;\r
7092     {* |<#richedit>\r
7093        Font of the first character in current selection (when retrieve).\r
7094        When set (or subproperties of RE_Font are set), all font attributes are\r
7095        applied to entire <A area>. To apply only needed attributes, use another\r
7096        properties: RE_FmtBold, RE_FmtItalic, RE_FmtStrikeout, RE_FmtUnderline,\r
7097        RE_FmtName, etc.\r
7098        |<br>\r
7099        Note, that font size is measured in twips, which is about 1/10 of pixel. }\r
7100     property RE_FmtBold: Boolean index CFM_BOLD read REGetFontEffects write RESetFontEffect;\r
7101     {* |<#richedit>\r
7102        Formatting flag. When retrieve, returns True, if fsBold style RE_Font.FontStyle\r
7103        is valid for a first character in the selection. When set, changes fsBold\r
7104        style (True - set, False - reset) for all characters in <A area>. }\r
7105     property RE_FmtBoldValid: Boolean index CFM_BOLD read REGetFontMask;\r
7106     {* }\r
7107     property RE_FmtItalic: Boolean index CFM_ITALIC read REGetFontEffects write RESetFontEffect;\r
7108     {* |<#richedit>\r
7109        Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsItalic\r
7110        style valid for the first character of the selection, and when set, changes\r
7111        only fsItalic style for an <A area>. }\r
7112     property RE_FmtItalicValid: Boolean index CFM_ITALIC read REGetFontMask;\r
7113     {* }\r
7114     property RE_FmtStrikeout: Boolean index CFM_STRIKEOUT read REGetFontEffects write RESetFontEffect;\r
7115     {* |<#richedit>\r
7116        Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsStrikeout\r
7117        style valid for the first selected character, and when set, changes only\r
7118        fsStrikeout style for an <A area>. }\r
7119     property RE_FmtStrikeoutValid: Boolean index CFM_STRIKEOUT read REGetFontMask;\r
7120     {* }\r
7121     property RE_FmtUnderline: Boolean index CFM_UNDERLINE read REGetFontEffects write RESetFontEffect;\r
7122     {* |<#richedit>\r
7123        Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsUnderline\r
7124        style valid for the first selected character, and when set, changes\r
7125        fsUnderline style for an <A area>. }\r
7126     property RE_FmtUnderlineValid: Boolean index CFM_UNDERLINE read REGetFontMask;\r
7127     {* }\r
7128     property RE_FmtUnderlineStyle: TRichUnderline\r
7129              read REGetUnderlineEx write RESetUnderlineEx;\r
7130     {* |<#richedit>\r
7131        Extended underline style. To check, if this property is valid for\r
7132        entire selection, examine RE_FmtUnderlineValid value. }\r
7133     property RE_FmtProtected: Boolean index CFM_PROTECTED read REGetFontEffects write RESetFontEffect;\r
7134     {* |<#richedit>\r
7135        Formatting flag. When retrieving, shows, is the first character of the selection\r
7136        is protected from changing it by user (True) or not (False). To get know,\r
7137        if retrived value is valid for entire selection, check the property\r
7138        RE_FmtProtectedValid. When set, makes all characters in <A area> protected (\r
7139        True) or not (False). }\r
7140     property RE_FmtProtectedValid: Boolean index CFM_PROTECTED read REGetFontMask;\r
7141     {* |<#richedit>\r
7142        True, if property RE_FmtProtected is valid for entire selection, when\r
7143        retrieving it. }\r
7144     property RE_FmtHidden: Boolean index CFM_HIDDEN read REGetFontEffects write RESetFontEffect;\r
7145     {* |<#richedit>\r
7146        For RichEdit3.0, makes text hidden (not displayed). }\r
7147     property RE_FmtHiddenValid: Boolean index CFM_HIDDEN read REGetFontMask;\r
7148     {* |<#richedit>\r
7149        Returns True, if RE_FmtHidden style is valid for entire selection. }\r
7151     property RE_FmtLink: Boolean index $20 {CFM_LINK} read REGetFontEffects write RESetFontEffect;\r
7152     {* |<#richedit>\r
7153        Returns True, if the first selected character is a part of link (URL). }\r
7154        // by Sergey Shisminzev\r
7156     property RE_FmtLinkValid: Boolean index $20 {CFM_LINK} read REGetFontMask;\r
7157     {* }\r
7158     property RE_FmtFontSize: Integer index (12 shl 16) or CFM_SIZE read REGetFontAttr write RESetFontAttr;\r
7159     {* |<#richedit>\r
7160        Formatting value: font size, in twips (1/1440 of an inch, or 1/20 of a\r
7161        printer's point, or about 1/10 of pixel). When retrieving, returns\r
7162        RE_Font.FontHeight.\r
7163        When set, changes font size for entire <A area> (but does not change\r
7164        other font attributes). }\r
7165     property RE_FmtFontSizeValid: Boolean read REGetFontSizeValid;\r
7166     {* |<#richedit>\r
7167        Returns True, if property RE_FmtFontSize is valid for entire selection,\r
7168        when retrieving it. }\r
7169     //property RE_FmtBackColor: Integer index (62 shl 16) or CFM_BACKCOLOR read REGetFontAttr write RESetFontAttr1;\r
7170     {* |<#richedit>\r
7171        Background color for an <A area>. }\r
7172     //property RE_FmtBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontEffect;\r
7173     {* |<#richedit>\r
7174        True, if RE_FmtBackColor valid for entire <A area>. }\r
7175     property RE_FmtAutoBackColor: Boolean index CFM_BACKCOLOR read REGetFontEffects write RESetFontEffect;\r
7176     {* |<#richedit>\r
7177        True, when automatic back color is used. }\r
7178     property RE_FmtAutoBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontMask;\r
7179     {* }\r
7180     property RE_FmtFontColor: Integer index (20 shl 16) or CFM_COLOR read REGetFontAttr write RESetFontAttr1;\r
7181     {* |<#richedit>\r
7182        Formatting value (font color). When retrieving, returns RE_Font.Color.\r
7183        When set, changes font color for entire <A area> (but does not change\r
7184        other font attributes). }\r
7185     property RE_FmtFontColorValid: Boolean index CFM_COLOR read REGetFontMask;\r
7186     {* |<#richedit>\r
7187        Returns True, if property RE_FmtFontColor valid for entire selection,\r
7188        when retrieving it. }\r
7189     property RE_FmtAutoColor: Boolean index CFM_COLOR read REGetFontEffects write RESetFontEffect;\r
7190     {* |<#richedit>\r
7191        True, when automatic text color is used (in such case, RE_FmtFontColor\r
7192        assignment is ignored for current area). }\r
7193     property RE_FmtAutoColorValid: Boolean index CFM_COLOR read REGetFontMask;\r
7194     {* }\r
7195     property RE_FmtBackColor: Integer index (64 shl 16) or CFM_BACKCOLOR read REGetFontAttr write RESetFontAttr1;\r
7196     {* |<#richedit>\r
7197        Formatting value (back color). Only available for Rich Edit 2.0 and higher.\r
7198        When set, changes background color for entire <A area> (but does not change\r
7199        other font attributes). }\r
7200     property RE_FmtBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontMask;\r
7201     {* }\r
7202     property RE_FmtFontOffset: Integer index (16 shl 16) or CFM_OFFSET read REGetFontAttr write RESetFontAttr;\r
7203     {* |<#richedit>\r
7204        Formatting value (font vertical offset from baseline, positive values\r
7205        correspond to subscript). When retrieving, returns offset for first\r
7206        character in the selection. When set, changes font offset for entire\r
7207        <A area>. To get know, is retrieved value valid for entire selction,\r
7208        check RE_FmtFontOffsetValid property. }\r
7209     property RE_FmtFontOffsetValid: Boolean index CFM_OFFSET read REGetFontMask;\r
7210     {* |<#richedit>\r
7211        Returns True, if property RE_FmtFontOffset is valid for entire selection,\r
7212        when retrieving it. }\r
7213     property RE_FmtFontCharset: Integer index (25 shl 16) or CFM_CHARSET read REGetFontAttr write RESetFontAttr;\r
7214     {* |<#richedit>\r
7215        Returns charset for first character in current selection, when retrieved\r
7216        (and to get know, if this value is valid for entire selection, check\r
7217        property RE_FmtFontCharsetValid). When set, changes charset for all\r
7218        characters in <A area>, but does not alter other formatting attributes. }\r
7219     property RE_FmtFontCharsetValid: Boolean index CFM_CHARSET read REGetFontMask;\r
7220     {* |<#richedit>\r
7221        Returns True, only if rerieved property RE_FmtFontCharset is valid for\r
7222        entire selection. }\r
7223     property RE_FmtFontName: String read REGetFontName write RESetFontName;\r
7224     {* |<#richedit>\r
7225        Returns font face name for first character in the selection, when retrieved,\r
7226        and sets font name for entire <A area>, wnen assigned to (without\r
7227        changing of other formatting attributes). To get know, if retrived\r
7228        font name valid for entire selection, examine property RE_FmtFontNameValid. }\r
7229     property RE_FmtFontNameValid: Boolean index CFM_FACE read REGetFontMask;\r
7230     {* |<#richedit>\r
7231        Returns True, only if the font name is the same for entire selection,\r
7232        thus is, if rerieved property value RE_FmtFontName is valid for entire\r
7233        selection. }\r
7235     property RE_ParaFmt: TParaFormat read REGetParaFmt write RESetParaFmt;\r
7236     {* |<#richedit>\r
7237        Allows to retrieve or set paragraph formatting attributes for currently\r
7238        selected paragraph(s) in RichEdit control. See also following properties,\r
7239        which allow to do the same for certain paragraph format attributes\r
7240        separately. }\r
7241     property RE_TextAlign: TRichTextAlign read REGetTextAlign write RESetTextAlign;\r
7242     {* |<#richedit>\r
7243        Returns text alignment for current selection and allows to change it\r
7244        (without changing other formatting attributes). }\r
7245     property RE_TextAlignValid: Boolean index PFM_ALIGNMENT read REGetParaAttrValid;\r
7246     {* |<#richedit>\r
7247        Returns True, if property RE_TextAlign is valid for entire selection. If\r
7248        False, it is concerning only start of selection. }\r
7249     property RE_Numbering: Boolean read REGetNumbering write RESetNumbering;\r
7250     {* |<#richedit>\r
7251        Returns True, if selected text is numbered (or has style of list with\r
7252        bullets). To get / change numbering style, see properties\r
7253        RE_NumStyle and RE_NumBrackets. }\r
7254     property RE_NumStyle: TRichNumbering read REGetNumStyle write RESetNumStyle;\r
7255     {* |<#richedit>\r
7256        Advanced numbering style, such as rnArabic etc. If You use it, do not\r
7257        change RE_Numbering property simultaneously - this can cause changing\r
7258        style to rnBullets only. }\r
7259     property RE_NumStart: Integer read REGetNumStart write RESetNumStart;\r
7260     {* |<#richedit>\r
7261        Starting number for advanced numbering style. If this property is not\r
7262        set, numbering is starting by default from 0. For rnLRoman and rnURoman\r
7263        this cause, that first item has no number to be shown (ancient Roman\r
7264        people did not invent '0'). }\r
7265     property RE_NumBrackets: TRichNumBrackets read REGetNumBrackets write RESetNumBrackets;\r
7266     {* |<#richedit>\r
7267        Brackets style for advanced numbering. rnbPlain is default\r
7268        brackets style, and every time, when RE_NumStyle is changed,\r
7269        RE_NumBrackets is reset to rnbPlain. }\r
7270     property RE_NumTab: Integer read REGetNumTab write RESetNumTab;\r
7271     {* |<#richedit>\r
7272        Tab between start of number and start of paragraph text. If too small too\r
7273        view number, number is not displayed. (Default value seems to be sufficient\r
7274        though). }\r
7275     property RE_NumberingValid: Boolean index PFM_NUMBERING read REGetParaAttrValid;\r
7276     {* |<#richedit>\r
7277        Returns True, if RE_Numbering, RE_NumStyle, RE_NumBrackets, RE_NumTab,\r
7278        RE_NumStart properties are valid for entire selection. }\r
7279     property RE_Level: Integer read REGetLevel;\r
7280     {* |<#richedit>\r
7281        Outline level (for numbering paragraphs?). Read only. }\r
7282     property RE_SpaceBefore: Integer index 0 or PFM_SPACEBEFORE read REGetSpacing write RESetSpacing;\r
7283     {* |<#richedit>\r
7284        Spacing before paragraph. }\r
7285     property RE_SpaceBeforeValid: Boolean index PFM_SPACEBEFORE read REGetParaAttrValid;\r
7286     {* |<#richedit>\r
7287        True, if RE_SpaceBefore value is valid for all selected paragraph (if\r
7288        False, this value is valid only for first paragraph. }\r
7289     property RE_SpaceAfter: Integer index 4 or PFM_SPACEAFTER read REGetSpacing write RESetSpacing;\r
7290     {* |<#richedit>\r
7291        Spacing after paragraph. }\r
7292     property RE_SpaceAfterValid: Boolean index PFM_SPACEAFTER read REGetParaAttrValid;\r
7293     {* |<#richedit>\r
7294        True, only if RE_SpaceAfter value is valid for all selected paragraphs. }\r
7295     property RE_LineSpacing: Integer index 8 or PFM_LINESPACING read REGetSpacing write RESetSpacing;\r
7296     {* |<#richedit>\r
7297        Linespacing in paragraph (this value is based on RE_SpacingRule property). }\r
7298     property RE_SpacingRule: Integer read REGetSpacingRule write RESetSpacingRule;\r
7299     {* |<#richedit>\r
7300        Linespacing rule. Do not know what is it. }\r
7301     property RE_LineSpacingValid: Boolean index PFM_LINESPACING read REGetParaAttrValid;\r
7302     {* |<#richedit>\r
7303        True, only if RE_LineSpacing and RE_SpacingRule values are valid for\r
7304        entire selection. }\r
7305     property RE_Indent: Integer index (20 shl 16) or PFM_OFFSET read REGetParaAttr write RESetParaAttr;\r
7306     {* |<#richedit>\r
7307        Returns left indentation for paragraph in current selection and allows\r
7308        to change it (without changing other formatting attributes). }\r
7309     property RE_IndentValid: Boolean index PFM_OFFSET read REGetParaAttrValid;\r
7310     {* |<#richedit>\r
7311        Returns True, if RE_Indent property is valid for entire selection. }\r
7312     property RE_StartIndent: Integer index (12 shl 16) or PFM_OFFSETINDENT read REGetParaAttr write RESetParaAttr;\r
7313     {* |<#richedit>\r
7314        Returns left indentation for first line in paragraph for current\r
7315        selection, and allows to change it (without changing other formatting\r
7316        attributes). }\r
7317     property RE_StartIndentValid: Boolean read REGetStartIndentValid;\r
7318     {* |<#richedit>\r
7319        Returns True, if property RE_StartIndent is valid for entire selection. }\r
7320     property RE_RightIndent: Integer index (16 shl 16) or PFM_RIGHTINDENT read REGetParaAttr write RESetParaAttr;\r
7321     {* |<#richedit>\r
7322        Returns right indent for paragraph in current selection, and allow to\r
7323        change it (without changing other formatting attributes). }\r
7324     property RE_RightIndentValid: Boolean index PFM_RIGHTINDENT read REGetParaAttrValid;\r
7325     {* |<#richedit>\r
7326        Returns True, if property RE_RightIndent is valid for entire selection only. }\r
7327     property RE_TabCount: Integer read REGetTabCount write RESetTabCount;\r
7328     {* |<#richedit>\r
7329        Number of tab stops in current selection. This value can not be set greater\r
7330        then MAX_TAB_COUNT (32). }\r
7331     property RE_Tabs[ Idx: Integer ]: Integer read REGetTabs write RESetTabs;\r
7332     {* |<#richedit>\r
7333        Tab stops for RichEdit control. }\r
7334     property RE_TabsValid: Boolean index PFM_TABSTOPS read REGetParaAttrValid;\r
7335     {* |<#richedit>\r
7336        Returns True, if properties RE_Tabs[ ] and RE_TabCount are valid for\r
7337        entire selection. }\r
7340     // following does not work now :\r
7341     property RE_BorderWidth[ Side: TBorderEdge ]: Integer index 2 read REGetBorder write RESetBorder;\r
7342     { * |<#richedit>\r
7343        Border width. }\r
7344     property RE_BorderSpace[ Side: TBorderEdge ]: Integer index 0 read REGetBorder write RESetBorder;\r
7345     { * |<#richedit>\r
7346        Border space. }\r
7347     property RE_BorderStyle[ Side: TBorderEdge ]: Integer index 4 read REGetBorder write RESetBorder;\r
7348     { * |<#richedit>\r
7349        Border style. }\r
7350     property RE_BorderValid: Boolean index PFM_BORDER read REGetParaAttrValid;\r
7351     { * |<#richedit>\r
7352        Returns True, if border style, space and width are the same for all\r
7353        paragraphs in selection. }\r
7354     property RE_Table: Boolean index $C000 read REGetParaEffect write RESetParaEffect;\r
7355     { * |<#richedit>\r
7356        True, if current paragraph is a part of table (row, cell or cell end).\r
7357        seems working as read only property. }\r
7358     // end of experiment section\r
7360     function RE_FmtStandard: PControl;\r
7361     {* |<#richedit>\r
7362        "Transparent" method (returns @Self as a result), which (when called)\r
7363        provides "standard" keyboard interface for formatting Rich text (just\r
7364        call this method, for example:\r
7365        !    RichEd1 := NewRichEdit( Panel1, [ ] ).SetAlign( caClient ).RE_FmtStandard;\r
7366        Following keys will be maintained additionally:\r
7367        |<pre>\r
7368        CTRL+I - switch "Italic",\r
7369        CTRL+B - switch "Bold",\r
7370        CTRL+U - switch "Underline",\r
7371        CTRL+SHIFT+U - swith underline type\r
7372                     and turn underline on (note, that some of underline styles\r
7373                     can not be shown properly in RichEdit v2.0 and lower,\r
7374                     though RichEdit2.0 stores data successfully).\r
7375        CTRL+O - switch "StrikeOut",\r
7376        CTRL+'gray+' - increase font size,\r
7377        CTRL+'gray-' - decrease font size,\r
7378        CTRL+SHIFT+'gray+' - superscript,\r
7379        CTRL+SHIFT+'gray-' - subscript.\r
7380        CTRL+SHIFT+Z - ReDo\r
7381        |</pre>\r
7382        And, though following standard formatting keys are provided by RichEdit\r
7383        control itself in Windows2000, some of these are not functioning\r
7384        automatically in earlier Windows versions, even for RichEdit2.0. So,\r
7385        functionality of some of these (marked with (*) ) are added here too:\r
7386        |<pre>\r
7387        CTRL+L - align paragraph left,           (*)\r
7388        CTRL+R - align paragraph right,          (*)\r
7389        CTRL+E - align paragraph center,         (*)\r
7390        CTRL+A - select all,                     (*)\r
7391        double-click on word - select word,\r
7392        CTRL+Right - to next word,\r
7393        CTRL+Left - to previous word,\r
7394        CTRL+Home - to the beginning of text,\r
7395        CTRL+End - to the end of text.\r
7396        CTRL+Z - UnDo\r
7397        |</pre>\r
7398        If You originally assign some (plain) text to Text property, switching "underline"\r
7399        can also change other font attributes, e.g., "bold" - if fsBold style is\r
7400        in default Font. To prevent such behavior, select entire text first (see\r
7401        SelectAll) and make assignment to RE_Font property, e.g.:\r
7402        !        RichEd1.SelectAll;\r
7403        !        RichEd1.RE_Font := RichEd1.RE_Font;\r
7404        !        RichEd1.SelLength := 0;\r
7405        |<br>\r
7406        And, some other notices about formatting. Please remember, that only True\r
7407        Type fonts can be succefully scaled and transformed to get desired effects\r
7408        (e.g., bold). By default, RichEdit uses System font face name, which can\r
7409        even have problems with fsBold style. Please remember also, that assigning\r
7410        RE_Font to RE_Font just initializying formatting attributes, making all\r
7411        those valid in entire text, but does not change font attributes. To use\r
7412        True Type font, directly assign face name You wish, e.g.:\r
7413        !        RichEd1.SelectAll;\r
7414        !        RichEd1.RE_Font := RichEd1.RE_Font;\r
7415        !        RichEd1.RE_Font.FontName := 'Arial';\r
7416        !        RichEd1.SelLength := 0;\r
7417     }\r
7418     property RE_AutoKeyboard: Boolean index 1 read REGetLangOptions write RESetLangOptions;\r
7419     {* |<#richedit>\r
7420        True if autokeyboard on (lovely "feature" of automatic switching keyboard\r
7421        language when caret is over another language text). For older RichEdit,\r
7422        is 'on' always, for newest - 'off' by default. }\r
7424     property RE_OverwriteMode: Boolean read REGetOverwite write RESetOverwrite;\r
7425     {* |<#richedit>\r
7426        This property allows to control insert/overwrite mode. First, to examine, if\r
7427        insert or overwrite mode is current (but it is necessary either to\r
7428        access this property, at least once, immediately after creating RichEdit\r
7429        control, or to assign event OnRE_InsOvrMode_Change to your handler).\r
7430        Second, to set desired mode programmatically - by assigning value to\r
7431        this property (You also have to initialize monitoring procedure by either\r
7432        reading RE_OverwriteMode property or assigning handler to event\r
7433        OnRE_InsOvrMode_Change immediately following RichEdit control creation). }\r
7434     property OnRE_InsOvrMode_Change: TOnEvent read fOnREInsModeChg write fOnREInsModeChg;\r
7435     {* |<#richedit>\r
7436        This event is called, whenever key INSERT is pressed in control (and for\r
7437        RichEdit, this means, that insert mode is changed). }\r
7438     property RE_DisableOverwriteChange: Boolean read fReOvrDisable write RESetOvrDisable;\r
7439     {* |<#richedit>\r
7440        It is possible to disable switching between "insert" and "overwrite" mode\r
7441        by user (therefore, event OnRE_InsOvrMode_Change continue works, but it\r
7442        just called when key INSERT is pressed, though RE_OverwriteMode property\r
7443        is not actually changed if switching is disabled). }\r
7445     function RE_LoadFromStream( Stream: PStream; Length: Integer;\r
7446                                 Format: TRETextFormat; SelectionOnly: Boolean ): Boolean;\r
7447     {* |<#richedit>\r
7448        Use this method rather then assignment to RE_Text property, if\r
7449        source is stored in file or stream (to minimize resources during\r
7450        loading of RichEdit content). Data is loading starting from current\r
7451        position in stream and no more then Length bytes are loaded (use -1\r
7452        value to load to the end of stream). Loaded data replaces entire\r
7453        content of RichEdit control, or selection only, depending on SelectionOnly\r
7454        flag.\r
7455        |<br>&nbsp;&nbsp;&nbsp;\r
7456        If You want to provide progress (e.g. in form of progress bar), assign\r
7457        OnProgress event to your handler - and to examine current position of\r
7458        loading, read TSream.Position property of soiurce stream). }\r
7459     function RE_SaveToStream( Stream: PStream; Format: TRETextFormat; SelectionOnly: Boolean ): Boolean;\r
7460     {* |<#richedit>\r
7461        Use this method rather then RE_TextProperty to store data to file\r
7462        or stream (to minimize resources during saving of RichEdit content).\r
7463        Data is saving starting from current position in a stream (until\r
7464        end of RichEdit data). If SelectionOnly flag is True, only selected\r
7465        part of RichEdit text is saved.\r
7466        |<br>&nbsp;&nbsp;&nbsp;\r
7467        Like for RE_LoadFromStream, it is possible to assign your method to\r
7468        OnProgress event (but to calculate progress of save-to-stream operation,\r
7469        compare current stream position with RE_Size[ rsBytes ] property\r
7470        value). }\r
7472     property OnProgress: TOnEvent read fOnProgress write fOnProgress;\r
7473     {* |<#richedit>\r
7474        This event is called during RE_SaveToStream, RE_LoadFromStream (and also\r
7475        during RE_SaveToFile, RE_LoadFromFile and while accessing or changing\r
7476        RE_Text property). To calculate relative progress, it is possible to\r
7477        examine current position in stream/file with its total size while reading,\r
7478        or with rich edit text size, while writing (property RE_TextSize[ rsBytes ]).\r
7479     }\r
7480     function RE_LoadFromFile( const Filename: String; Format: TRETextFormat;\r
7481              SelectionOnly: Boolean ): Boolean;\r
7482     {* |<#richedit>\r
7483        Use this method rather then other assignments to RE_Text property,\r
7484        if a source for RichEdit is the file. See also RE_LoadFromStream. }\r
7485     function RE_SaveToFile( const Filename: String; Format: TRETextFormat;\r
7486              SelectionOnly: Boolean ): Boolean;\r
7487     {* |<#richedit>\r
7488        Use this method rather then other similar, if You want to store\r
7489        entire content of RichEdit or selection only of RichEdit to a file. }\r
7491     property RE_Text[ Format: TRETextFormat; SelectionOnly: Boolean ]: String read REReadText write REWriteText;\r
7492     {* |<#richedit>\r
7493        This property allows to get / replace content of RichEdit control\r
7494        (entire text or selection only). Using different formats, it is\r
7495        possible to exclude or replace undesired formatting information\r
7496        (see TRETextFormat specification). To get or replace entire text\r
7497        in reText mode (plain text only), it is possible to use habitual\r
7498        for edit controls Text property.\r
7499        |<br>&nbsp;&nbsp;&nbsp;\r
7500        Note: it is possible to append text to the end of RichEdit control\r
7501        using method Add, but only if property RE_Text is accessed at least\r
7502        once:\r
7503        !               RichEdit1.RE_Text[ reText, True ];\r
7504        (This line can be written immediatelly after creating RichEdit control). }\r
7506     procedure RE_Append( const S: String; ACanUndo: Boolean );\r
7507     {* }\r
7508     procedure RE_InsertRTF( const S: String );\r
7509     {* }\r
7510     property RE_Error: Integer read fREError;\r
7511     {* |<#richedit>\r
7512        Contains error code, if access to RE_Text failed. }\r
7514     procedure RE_HideSelection( aHide: Boolean );\r
7515     {* |<#richedit>\r
7516        Allows to hide / show selection in RichEdit. }\r
7518     function RE_SearchText( const Value: String; MatchCase, WholeWord, ScanForward: Boolean;\r
7519                             SearchFrom, SearchTo: Integer ): Integer;\r
7520     {* |<#richedit>\r
7521        Searches given string starting from SearchFrom position up to SearchTo\r
7522        position (to the end of text, if SearchTo is -1). Returns zero-based\r
7523        character position of the next match, or -1 if there are no more matches.\r
7524        To search in bacward direction, set ScanForward to False, and pass\r
7525        SearchFrom > SearchTo (or even SearchFrom = -1 and SearchTo = 0). }\r
7527     property RE_AutoURLDetect: Boolean read REGetAutoURLDetect write RESetAutoURLDetect;\r
7528     {* |<#richedit>\r
7529        If set to True, automatically detects URLs (and highlights it with\r
7530        blue color, applying fsItalic and fsUnderline font styles (while\r
7531        typing and loading). Default value is False. Note: if event OnRE_URLClick\r
7532        or event OnRE_OverURL are set, property RE_AutoURLDetect is set to True\r
7533        automatically. }\r
7535     property RE_URL: String read fREUrl;\r
7536     {* |<#richedit>\r
7537        Detected URL (valid in OnRE_OverURL and OnRE_URLClick event handlers). }\r
7538     property OnRE_OverURL: TOnEvent index 0\r
7539              {$IFDEF F_P}   read REGetOnURL\r
7540              {$ELSE DELPHI} read fOnREOverURL\r
7541              {$ENDIF F_P/DELPHI} write RESetOnURL;\r
7542     {* |<#richedit>\r
7543        Is called when mouse is moving over URL. This can be used to set\r
7544        cursor, for example, depending on type of URL (to determine URL type\r
7545        read property RE_URL). }\r
7546     property OnRE_URLClick: TOnEvent index 8\r
7547              {$IFDEF F_P}   read REGetOnURL\r
7548              {$ELSE DELPHI} read fOnREURLClick\r
7549              {$ENDIF F_P/DELPHI} write RESetOnURL;\r
7550     {* |<#richedit>\r
7551        Is called when click on URL detected. }\r
7553     //property RE_SelectionBar: Boolean read REGetSelectionBar write RESetSelectionBar;\r
7554     //{* ??? - don't know that is this... }\r
7555     function RE_NoOLEDragDrop: PControl;\r
7556     {* |<#richedit>\r
7557        Just prevents drop OLE objects to the rich edit control. Seems not\r
7558        working for some cases. }\r
7560     //function RE_Wyswig: PControl;\r
7562     function RE_Bottomless: PControl;\r
7563     // not finished\r
7565     property RE_Transparent: Boolean read REGetTransparent write RESetTransparent;\r
7566     {* |<#richedit>\r
7567        Use this property to make richedit control transparent, instead of\r
7568        Ed_Transparent or Transparent. But do not place such transparent\r
7569        richedit control directly on form - it can be draw incorrectly when\r
7570        form is activated and rich editr control is not current active control.\r
7571        Use at least panel as a parent instead.\r
7572        }\r
7574     //========== both for Edit and RichEdit: =====================\r
7575     function CanUndo: Boolean;\r
7576     {* |<#richedit>\r
7577        |<#edit>\r
7578        |<#memo>\r
7579        Returns True, if the edit (or RichEdit) control can correctly process\r
7580        the EM_UNDO message. }\r
7581     procedure EmptyUndoBuffer;\r
7582     {* |<#richedit>\r
7583        |<#edit>\r
7584        |<#memo>\r
7585        Reset the undo flag of an edit control, preventing undoing all previous\r
7586        changes. }\r
7587     function Undo: Boolean;\r
7588     {* |<#richedit>\r
7589        |<#edit>\r
7590        |<#memo>\r
7591        For a single-line edit control, the return value is always TRUE. For a\r
7592        multiline edit control and RichEdit control, the return value is TRUE if\r
7593        the undo operation is successful, or FALSE if the undo operation fails. }\r
7595     function RE_Redo: Boolean;\r
7596     {* |<#richedit>\r
7597        Only for RichEdit control: Returns True if successful. }\r
7599     //----------------------------------------------------------------------\r
7600     // DateTimePicker\r
7601     property OnDTPUserString: TDTParseInputEvent read FOnDTPUserString\r
7602              write FOnDTPUserString;\r
7603     {* Special event to parse input from the application. Option dtpoParseInput\r
7604        must be set when control is created. }\r
7605     property DateTime: TDateTime read GetDateTime write SetDateTime;\r
7606     {* DateTime for DateTimePicker control only. }\r
7607     property Date: TDateTime read GetDate write SetDate;\r
7608     {* Date only for DateTimePicker control only. }\r
7609     property Time: TDateTime read GetTime write SetTime;\r
7610     {* Time only for DateTimePicker control only. }\r
7611     property DateTimeRange: TDateTimeRange read GetDateTimeRange\r
7612       write SetDateTimeRange;\r
7613     {* DateTimePicker range. If first date in the agrument assigned is NAN,\r
7614        minimum system allowed value is used as the left bound, and if the second is\r
7615        NAN, maximum system allowed is used as the right one. }\r
7616     property DateTimePickerColors[ Index: TDateTimePickerColor ]: TColor\r
7617       read GetDateTimePickerColor write SetDateTimePickerColor;\r
7618     property DateTimeFormat: String write SetDateTimeFormat;\r
7621     //----------------------------------------------------------------------\r
7623     //----------------------------------------------------------------------\r
7624     // ScrollBar\r
7625     property SBMin: Longint read fSBMinMax.X write SetSBMin;\r
7626     property SBMax: Longint read fSBMinMax.Y write SetSBMax;\r
7627     property SBMinMax: TPoint read fSBMinMax write SetSBMinMax;\r
7628     property SBPosition: Integer read fSBPosition write SetSBPosition;\r
7629     property SBPageSize: Integer read fSBPageSize write SetSBPageSize;\r
7631     property OnSBBeforeScroll: TOnSBBeforeScroll read FOnSBBeforeScroll write FOnSBBeforeScroll;\r
7632     property OnSBScroll: TOnSBScroll read FOnSBScroll write FOnSBScroll;\r
7634     function SBSetScrollInfo(const SI: TScrollInfo): Integer;\r
7635     function SBGetScrollInfo(var SI: TScrollInfo): Boolean;\r
7636     function GetSBMinMax: TPoint;\r
7637     function GetSBPageSize: Integer;\r
7638     function GetSBPosition: Integer;\r
7639     //----------------------------------------------------------------------\r
7642     // "Through", or "transparent" methods to simplify initial\r
7643     // adjustment of controls and make non-visual designing of\r
7644     // forms more easy. All these functions return @Self as a\r
7645     // result, so, it is possible to use such methods immediately\r
7646     // in constructing statement, concatenating it with dots, e.g.:\r
7647     //\r
7648     // NewButton( MyForm, 'Click here' ).PlaceUnder.ResizeParentBottom;\r
7649     //\r
7650     function PlaceRight: PControl;\r
7651     {* Places control right (to previously created on the same parent). }\r
7652     function PlaceDown: PControl;\r
7653     {* Places control below (to previously created on the same parent).\r
7654        Left position is not changed (thus is, kept equal to Parent.Margin). }\r
7655     function PlaceUnder: PControl;\r
7656     {* Places control below (to previously created one, aligning its\r
7657        Left position to Left position of previous control). }\r
7658     function SetSize( W, H: Integer ): PControl;\r
7660     {* Changes size of a control. If W or H less or equal to 0,\r
7661        correspondent size is not changed. }\r
7662     function Size( W, H: Integer ): PControl;\r
7663     {* Like SetSize, but provides automatic resizing of parent control\r
7664        (recursively). Especially useful for aligned controls. }\r
7665     function SetClientSize( W, H: Integer ): PControl;\r
7666     {* Like SetSize, but works setting W = ClientWidth, H = ClientHeight.\r
7667        Use this method for forms, which can not be resized (dialogs). }\r
7669     function AutoSize( AutoSzOn: Boolean ): PControl;\r
7671     {* Determines if to autosize control (like label, button, etc.) }\r
7672     function IsAutoSize: Boolean;\r
7673     {* TRUE, if a control is autosizing. }\r
7674     function AlignLeft( P: PControl ): PControl;\r
7675     {* assigns Left := P.Left }\r
7676     function AlignTop( P: PControl ): PControl;\r
7677     {* assigns Top := P.Top }\r
7678     function ResizeParent: PControl;\r
7679     {* Resizes parent, calling ResizeParentRight and ResizeParentBottom. }\r
7680     function ResizeParentRight: PControl;\r
7681     {* Resizes parent right edge (Margin of parent is added to right\r
7682        coordinate of a control). If called second time (for the same\r
7683        parent), resizes only for increasing of right edge of parent. }\r
7685     function ResizeParentBottom: PControl;\r
7686     {* Resizes parent bottom edge (Margin of parent is added to\r
7687        bottom coordinate of a control). }\r
7688     function CenterOnParent: PControl;\r
7689     {* Centers control on parent, or if applied to a form, centers\r
7690        form on screen. }\r
7692     function Shift( dX, dY : Integer ): PControl;\r
7693     {* Moves control respectively to current position (Left := Left + dX,\r
7694        Top := Top + dY). }\r
7695     function SetPosition( X, Y: Integer ): PControl;\r
7696     {* Moves control directly to the specified position. }\r
7698     function Tabulate: PControl;\r
7699     {* Call it once for form/applet to provide tabulation between controls on\r
7700        form/on all forms using TAB / SHIFT+TAB and arrow keys. }\r
7701     function TabulateEx: PControl;\r
7702     {* Call it once for form/applet to provide tabulation between controls on\r
7703        form/on all forms using TAB / SHIFT+TAB and arrow keys. Arrow keys are\r
7704        used more smart, allowing go to nearest control in certain direction. }\r
7706     function SetAlign( AAlign: TControlAlign ): PControl;\r
7707     {* Assigns passed value to property Align, aligning control on parent,\r
7708        and returns @Self (so it is "transparent" function, which can be\r
7709        used to adjust control at the creation, e.g.:\r
7710        ! MyLabel := NewLabel( MyForm, 'Label1' ).SetAlign( caBottom );\r
7711        See also property Align. }\r
7712     function PreventResizeFlicks: PControl;\r
7713     {* If called, prevents resizing flicks for child controls, aligned to\r
7714        right and bottom (but with a lot of code added to executable - about 3,5K).\r
7715        There is sensible to set DoubleBuffered to True also to eliminate the\r
7716        most of flicks.\r
7717        |<br>&nbsp;&nbsp;&nbsp;\r
7718        This method been applied to a form, prevents, resizing flicks for\r
7719        form and all controls on the form. If it is called for applet window,\r
7720        all forms are affected. And if You want, You can apply it for certain\r
7721        control only - in such case only given control and its children will\r
7722        be resizing without flicks (e.g., using splitter control). }\r
7724     property Checked: Boolean read GetChecked write Set_Checked;\r
7725     {* |<#checkbox>\r
7726        |<#radiobox>\r
7727        For checkbox and radiobox - if it is checked. Do not assign\r
7728        value for radiobox - use SetRadioChecked instead. }\r
7729     function SetChecked(const Value: Boolean): PControl;\r
7730     {* |<#checkbox>\r
7731        Use it to check/uncheck check box control or push button.\r
7732        Do not apply it to check radio buttons - use SetRadioChecked\r
7733        method below. }\r
7734     function SetRadioChecked : PControl;\r
7735     {* |<#radiobox>\r
7736        Use it to check radio button item correctly (unchecking all\r
7737        alternative ones). Actually, method Click is called, and control\r
7738        itself is returned. }\r
7739     function SetRadioCheckedOld: PControl;\r
7740     {* |<#radiobox>\r
7741        Old version of SetRadioChecked (implemented using recommended API\r
7742        call. It does not work properly, if control is not visible\r
7743        (together with its form). }\r
7744     procedure Click;\r
7745     {* |<#button>\r
7746        |<#checkbox>\r
7747        |<#radiobox>\r
7748        Emulates click on control programmatically, sending WM_COMMAND\r
7749        message with BN_CLICKED code. This method is sensible only for\r
7750        buttons, checkboxes and radioboxes. }\r
7752     function Perform( msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;\r
7753     {* Sends message to control's window (created if needed). }\r
7754     procedure AttachProc( Proc: TWindowFunc );\r
7755     {* It is possible to attach dynamically any message handler to window\r
7756        procedure using this method. Last attached procedure is called first.\r
7757        If procedure returns True, further processing of a message is stopped.\r
7758        Attached procedure can be detached using DetachProc (but do not\r
7759        attach/detach procedures during handling of attached procedure -\r
7760        this can hang application). }\r
7761     procedure AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );\r
7762     {* The same as AttachProc, but a handler is executed even after terminating\r
7763        the main message loop processing (i.e. after assigning true to\r
7764        AppletTerminated global variable. }\r
7765     function IsProcAttached( Proc: TWindowFunc ): Boolean;\r
7766     {* Returns True, if given procedure is already in chain of attached\r
7767        ones for given control window proc. }\r
7768     procedure DetachProc( Proc: TWindowFunc );\r
7769     {* Detaches procedure attached earlier using AttachProc. }\r
7771     property OnDropFiles: TOnDropFiles read FOnDropFiles write SetOnDropFiles;\r
7772     {* Assign this event to your handler, if You want to accept drag and drop\r
7773        files from other applications such as explorer onto your control. When\r
7774        this event is assigned to a control or form, this has effect also for\r
7775        all its child controls too. }\r
7777     property CustomData: Pointer read fCustomData write fCustomData;\r
7778     {* Can be used to exend the object when new type of control added. Memory,\r
7779        pointed by this pointer, released automatically in the destructor. }\r
7780     property CustomObj: PObj read fCustomObj write fCustomObj;\r
7781     {* Can be used to exend the object when new type of control added. Object,\r
7782        pointed by this pointer, released automatically in the destructor. }\r
7783     procedure SetAutoPopupMenu( PopupMenu: PObj );\r
7784     {* To assign a popup menu to the control, call SetAutoPopupMenu method of\r
7785        the control with popup menu object as a parameter. }\r
7787     function SupportMnemonics: PControl;\r
7788     {* This method provides supporting mnemonic keys in menus, buttons, checkboxes,\r
7789        toolbar buttons. }\r
7790     property OnScroll: TOnScroll read FOnScroll write SetOnScroll;\r
7791     {* }\r
7795     {$IFDEF USE_CONSTRUCTORS}\r
7796     //------------------------------------------------------------\r
7797     // constructors here:\r
7798     constructor CreateWindowed( AParent: PControl; AClassName: PChar; ACtl3D: Boolean );\r
7799     constructor CreateApplet( const ACaption: String );\r
7800     constructor CreateForm( AParent: PControl; const ACaption: String );\r
7801     constructor CreateControl( AParent: PControl; AClassName: PChar; AStyle: DWORD;\r
7802                                ACtl3D: Boolean; Actions: PCommandActions );\r
7803     constructor CreateButton( AParent: PControl; const ACaption: String );\r
7804     constructor CreateBitBtn( AParent: PControl; const ACaption: String;\r
7805          AOptions: TBitBtnOptions; ALayout: TGlyphLayout; AGlyphBitmap: HBitmap;\r
7806          AGlyphCount: Integer);\r
7807     constructor CreateLabel( AParent: PControl; const ACaption: String );\r
7808     constructor CreateWordWrapLabel( AParent: PControl; const ACaption: String );\r
7809     constructor CreateLabelEffect( AParent: PControl; ACaption: String; AShadowDeep: Integer );\r
7810     constructor CreatePaintBox( AParent: PControl );\r
7811     constructor CreateGradientPanel( AParent: PControl; AColor1, AColor2: TColor );\r
7812     constructor CreateGradientPanelEx( AParent: PControl; AColor1, AColor2: TColor;\r
7813                              AStyle: TGradientStyle; ALayout: TGradientLayout );\r
7814     constructor CreateGroupbox( AParent: PControl; const ACaption: String );\r
7815     constructor CreateCheckbox( AParent: PControl; const ACaption: String );\r
7816     constructor CreateRadiobox( AParent: PControl; const ACaption: String );\r
7817     constructor CreateEditbox( AParent: PControl; AOptions: TEditOptions );\r
7818     constructor CreatePanel( AParent: PControl; AStyle: TEdgeStyle );\r
7819     constructor CreateSplitter( AParent: PControl; AMinSizePrev, AMinSizeNext: Integer;\r
7820                 EdgeStyle: TEdgeStyle );\r
7821     constructor CreateListbox( AParent: PControl; AOptions: TListOptions );\r
7822     constructor CreateCombobox( AParent: PControl; AOptions: TComboOptions );\r
7823     constructor CreateCommonControl( AParent: PControl; AClassName: PChar; AStyle: DWORD;\r
7824                             ACtl3D: Boolean; Actions: PCommandActions );\r
7825     constructor CreateRichEdit( AParent: PControl; AOptions: TEditOptions );\r
7826     constructor CreateRichEdit1( AParent: PControl; AOptions: TEditOptions );\r
7827     constructor CreateProgressbar( AParent: PControl );\r
7828     constructor CreateProgressbarEx( AParent: PControl; AOptions: TProgressbarOptions );\r
7829     constructor CreateListView( AParent: PControl; AStyle: TListViewStyle; AOptions: TListViewOptions;\r
7830                       AImageListSmall, AImageListNormal, AImageListState: PImageList );\r
7831     constructor CreateTreeView( AParent: PControl; AOptions: TTreeViewOptions;\r
7832                       AImgListNormal, AImgListState: PImageList );\r
7833     constructor CreateTabControl( AParent: PControl; ATabs: array of String;\r
7834          AOptions: TTabControlOptions; AImgList: PImageList; AImgList1stIdx: Integer );\r
7835     constructor CreateToolbar( AParent: PControl; AAlign: TControlAlign; AOptions: TToolbarOptions;\r
7836                      ABitmap: HBitmap; AButtons: array of PChar;\r
7837                      ABtnImgIdxArray: array of Integer );\r
7838     {$ENDIF USE_CONSTRUCTORS}\r
7840     {$IFDEF USE_CUSTOMEXTENSIONS}\r
7841       {$I CUSTOM_TCONTROL_EXTENSION.inc}\r
7842     {$ENDIF}\r
7843     // If an option USE_CUSTOMEXTENSIONS is enabled (at the beginning of this\r
7844     // unit), You can freely extend TControl definition by your own fields,\r
7845     // methods and properties. This provides You with capability to extend\r
7846     // TControl implementing another kinds of visual controls without deriving\r
7847     // new descendant objects from TControl. This way is provided to avoid too\r
7848     // large grow of executable size. You also can derive your own controls\r
7849     // from TControl using standard OOP capabilities. In such case an option\r
7850     // USE_CONSTRUCTORS should be turned on (see it at the start of this unit).\r
7851     //   If You choose this "flat" model of extending the TControl with your\r
7852     // own properties, fieds, methods, events, etc. You should provide three\r
7853     // inc-files: CUSTOM_TCONTROL_EXTENSION.inc, containing such definitions\r
7854     // for TControl, CUSTOM_KOL_EXTENSION.inc, containing needed global\r
7855     // declarations, and CUSTOM_CODE_EXTENSION.inc, the implementation of those\r
7856     // two.\r
7857     //   Because KOL is always grow and constantly is extending by me, I also can\r
7858     // add my own complements for TControl. To avoid naming conflicts, I suggest\r
7859     // to use the same naming rule for all of You. Name your fields, properies, etc.\r
7860     // using a form idx_SomeName, where idx is a prefix, containing several\r
7861     // (at least one) letters and digits. E.g. ZK65_OnSomething.\r
7863   protected\r
7864     {$IFDEF USE_DROPDOWNCOUNT}\r
7865     fDropDownCount: Cardinal;\r
7866     {$ENDIF}\r
7867   public\r
7868     {$IFDEF USE_DROPDOWNCOUNT}\r
7869     property DropDownCount: Cardinal read fDropDownCount write fDropDownCount;\r
7870     {$ENDIF}\r
7871   end;\r
7872 //[END OF TControl DEFINITION]\r
7874   {$IFDEF USE_MHTOOLTIP}\r
7875   {$DEFINE interface}\r
7876   {$I KOLMHToolTip}\r
7877   {$UNDEF interface}\r
7878   {$ENDIF}\r
7880 //[Paint Background PROCEDURE]\r
7881 type\r
7882   TOnPaintBkgnd = procedure( Sender: PControl; DC: HDC; Rect: PRect );\r
7883   {* Global event definition. Used to define Global_OnPaintBackground\r
7884      event placeholder. }\r
7886 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );\r
7888 var\r
7889   Global_OnPaintBkgnd: TOnPaintBkgnd = DefaultPaintBackground;\r
7890   {* Global event. It is assigned in XBackgounds.pas add-on to replace\r
7891      PaintBackground method for all TVisual objects, allowing great\r
7892      visualization effect: transparent controls over [animated] bitmap\r
7893      background. Idea:\r
7894      | <a href=mailto:"bw@sunv.com">Wei&nbsp;Bao</a>. Implementation:\r
7895      | <a href=mailto:"bonanzas@xcl.cjb.net">Kladov&nbsp;Vladimir</a>. }\r
7897 procedure DummyPaintProc( Sender: PControl; DC: HDC );\r
7899 //[GetShiftState DECLARATION]\r
7900 function GetShiftState: DWORD;\r
7902 //[WndProcXXX DECLARATIONS]\r
7903 function WndProcMouse( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
7904 function WndProcKeybd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
7905 function WndProcDummy( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
7906 function WndProcBufferedDraw( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
7907 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}\r
7908 function WndProcBtnReturnClick( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
7909 {$ENDIF}\r
7911 //[InitCommonXXXX DECLARATIONS]\r
7912 procedure InitCommonControlSizeNotify( Ctrl: PControl );\r
7913 procedure InitCommonControlCommonNotify( Ctrl: PControl );\r
7915 //[Buffered Draw DECLARATIONS]\r
7916 var\r
7917   Global_OnBufferedDraw: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean\r
7918                          = WndProcDummy;\r
7919   Global_DblBufCreateWnd: procedure( Sender: PObj ) = DummyObjProc;\r
7920   Global_Invalidate: procedure( Sender: PObj ) = DummyObjProc;\r
7921   {* Is called in TControl.Invalidate to extend it in case when DoubleBuffered\r
7922      painting used. }\r
7924   Global_TranspDrawBkgnd: procedure( DC: HDC; Sender: PControl );\r
7926   //Global_OnCreateWindow: procedure( Sender: PObj ) = DummyObjProc;\r
7927   //{* Is called when TControl object is created. }\r
7928   //Global_OnDestroyWindow: procedure( Sender: PObj ) = DummyObjProc;\r
7929   //{* Is called before destroying TControl object (after accepting it,\r
7930   //   if event OnClose is defined). }\r
7931   Global_OnBeginPaint: procedure( Sender: PControl; DC: HDC ) = DummyPaintProc;\r
7932   {* Is called before painting a window. }\r
7933   Global_OnEndPaint: procedure( Sender: PControl; DC: HDC ) = DummyPaintProc;\r
7934   {* Is called after painting a window. }\r
7935   HelpFilePath: PChar;\r
7936   {* Path to application help file. If not assigned, application path with\r
7937      extension replaced to '.hlp' used. To use '.chm' file (HtmlHelp),\r
7938      call AssignHtmlHelp with a path to a html help file (or a name). }\r
7940 //[Html Help DECLARATIONS]\r
7941 procedure AssignHtmlHelp( const HtmlHelpPath: String );\r
7942 procedure HtmlHelpCommand( Wnd: HWnd; const HelpFilePath: String; Cmd, Data: Integer );\r
7943 {* Use this wrapper procedure to call HtmlHelp API function. }\r
7944 //+++++++++++ HTML HELP DEFINITIONS SECTION:\r
7945 // this section is from\r
7946 //   HTML Help API Interface Unit\r
7947 //   Copyright (c) 1999 The Helpware Group\r
7948 // provided for KOL by Alexey Babenko\r
7949 const\r
7950   HH_DISPLAY_TOPIC        = $0000;  {**}\r
7951   HH_HELP_FINDER          = $0000;  // WinHelp equivalent\r
7952   HH_DISPLAY_TOC          = $0001;  // not currently implemented\r
7953   HH_DISPLAY_INDEX        = $0002;  // not currently implemented\r
7954   HH_DISPLAY_SEARCH       = $0003;  // not currently implemented\r
7955   HH_SET_WIN_TYPE         = $0004;\r
7956   HH_GET_WIN_TYPE         = $0005;\r
7957   HH_GET_WIN_HANDLE       = $0006;\r
7958   HH_ENUM_INFO_TYPE       = $0007;  // Get Info type name, call repeatedly to enumerate, -1 at end\r
7959   HH_SET_INFO_TYPE        = $0008;  // Add Info type to filter.\r
7960   HH_SYNC                 = $0009;\r
7961   HH_RESERVED1            = $000A;\r
7962   HH_RESERVED2            = $000B;\r
7963   HH_RESERVED3            = $000C;\r
7964   HH_KEYWORD_LOOKUP       = $000D;\r
7965   HH_DISPLAY_TEXT_POPUP   = $000E;  // display string resource id or text in a popup window\r
7966   HH_HELP_CONTEXT         = $000F;  {**}// display mapped numeric value in dwData\r
7967   HH_TP_HELP_CONTEXTMENU  = $0010;  // text popup help, same as WinHelp HELP_CONTEXTMENU\r
7968   HH_TP_HELP_WM_HELP      = $0011;  // text popup help, same as WinHelp HELP_WM_HELP\r
7969   HH_CLOSE_ALL            = $0012;  // close all windows opened directly or indirectly by the caller\r
7970   HH_ALINK_LOOKUP         = $0013;  // ALink version of HH_KEYWORD_LOOKUP\r
7971   HH_GET_LAST_ERROR       = $0014;  // not currently implemented // See HHERROR.h\r
7972   HH_ENUM_CATEGORY        = $0015;      // Get category name, call repeatedly to enumerate, -1 at end\r
7973   HH_ENUM_CATEGORY_IT     = $0016;  // Get category info type members, call repeatedly to enumerate, -1 at end\r
7974   HH_RESET_IT_FILTER      = $0017;  // Clear the info type filter of all info types.\r
7975   HH_SET_INCLUSIVE_FILTER = $0018;  // set inclusive filtering method for untyped topics to be included in display\r
7976   HH_SET_EXCLUSIVE_FILTER = $0019;  // set exclusive filtering method for untyped topics to be excluded from display\r
7977   HH_INITIALIZE           = $001C;  // Initializes the help system.\r
7978   HH_UNINITIALIZE         = $001D;  // Uninitializes the help system.\r
7979   HH_PRETRANSLATEMESSAGE  = $00fd;  // Pumps messages. (NULL, NULL, MSG*).\r
7980   HH_SET_GLOBAL_PROPERTY  = $00fc;  // Set a global property. (NULL, NULL, HH_GPROP)\r
7982   { window properties }\r
7984 const\r
7985   HHWIN_PROP_TAB_AUTOHIDESHOW = $00000001;  // (1 << 0)  Automatically hide/show tri-pane window\r
7986   HHWIN_PROP_ONTOP            = $00000002;  // (1 << 1)  Top-most window\r
7987   HHWIN_PROP_NOTITLEBAR       = $00000004;  // (1 << 2)  no title bar\r
7988   HHWIN_PROP_NODEF_STYLES     = $00000008;  // (1 << 3)  no default window styles (only HH_WINTYPE.dwStyles)\r
7989   HHWIN_PROP_NODEF_EXSTYLES   = $00000010;  // (1 << 4)  no default extended window styles (only HH_WINTYPE.dwExStyles)\r
7990   HHWIN_PROP_TRI_PANE         = $00000020;  // (1 << 5)  use a tri-pane window\r
7991   HHWIN_PROP_NOTB_TEXT        = $00000040;  // (1 << 6)  no text on toolbar buttons\r
7992   HHWIN_PROP_POST_QUIT        = $00000080;  // (1 << 7)  post WM_QUIT message when window closes\r
7993   HHWIN_PROP_AUTO_SYNC        = $00000100;  // (1 << 8)  automatically ssync contents and index\r
7994   HHWIN_PROP_TRACKING         = $00000200;  // (1 << 9)  send tracking notification messages\r
7995   HHWIN_PROP_TAB_SEARCH       = $00000400;  // (1 << 10) include search tab in navigation pane\r
7996   HHWIN_PROP_TAB_HISTORY      = $00000800;  // (1 << 11) include history tab in navigation pane\r
7997   HHWIN_PROP_TAB_FAVORITES    = $00001000;  // (1 << 12) include favorites tab in navigation pane\r
7998   HHWIN_PROP_CHANGE_TITLE     = $00002000;  // (1 << 13) Put current HTML title in title bar\r
7999   HHWIN_PROP_NAV_ONLY_WIN     = $00004000;  // (1 << 14) Only display the navigation window\r
8000   HHWIN_PROP_NO_TOOLBAR       = $00008000;  // (1 << 15) Don't display a toolbar\r
8001   HHWIN_PROP_MENU             = $00010000;  // (1 << 16) Menu\r
8002   HHWIN_PROP_TAB_ADVSEARCH    = $00020000;  // (1 << 17) Advanced FTS UI.\r
8003   HHWIN_PROP_USER_POS         = $00040000;  // (1 << 18) After initial creation, user controls window size/position\r
8004   HHWIN_PROP_TAB_CUSTOM1      = $00080000;  // (1 << 19) Use custom tab #1\r
8005   HHWIN_PROP_TAB_CUSTOM2      = $00100000;  // (1 << 20) Use custom tab #2\r
8006   HHWIN_PROP_TAB_CUSTOM3      = $00200000;  // (1 << 21) Use custom tab #3\r
8007   HHWIN_PROP_TAB_CUSTOM4      = $00400000;  // (1 << 22) Use custom tab #4\r
8008   HHWIN_PROP_TAB_CUSTOM5      = $00800000;  // (1 << 23) Use custom tab #5\r
8009   HHWIN_PROP_TAB_CUSTOM6      = $01000000;  // (1 << 24) Use custom tab #6\r
8010   HHWIN_PROP_TAB_CUSTOM7      = $02000000;  // (1 << 25) Use custom tab #7\r
8011   HHWIN_PROP_TAB_CUSTOM8      = $04000000;  // (1 << 26) Use custom tab #8\r
8012   HHWIN_PROP_TAB_CUSTOM9      = $08000000;  // (1 << 27) Use custom tab #9\r
8013   HHWIN_TB_MARGIN             = $10000000;  // (1 << 28) the window type has a margin\r
8015   { window parameters }\r
8017 const\r
8018   HHWIN_PARAM_PROPERTIES      = $00000002;  // (1 << 1)  valid fsWinProperties\r
8019   HHWIN_PARAM_STYLES          = $00000004;  // (1 << 2)  valid dwStyles\r
8020   HHWIN_PARAM_EXSTYLES        = $00000008;  // (1 << 3)  valid dwExStyles\r
8021   HHWIN_PARAM_RECT            = $00000010;  // (1 << 4)  valid rcWindowPos\r
8022   HHWIN_PARAM_NAV_WIDTH       = $00000020;  // (1 << 5)  valid iNavWidth\r
8023   HHWIN_PARAM_SHOWSTATE       = $00000040;  // (1 << 6)  valid nShowState\r
8024   HHWIN_PARAM_INFOTYPES       = $00000080;  // (1 << 7)  valid apInfoTypes\r
8025   HHWIN_PARAM_TB_FLAGS        = $00000100;  // (1 << 8)  valid fsToolBarFlags\r
8026   HHWIN_PARAM_EXPANSION       = $00000200;  // (1 << 9)  valid fNotExpanded\r
8027   HHWIN_PARAM_TABPOS          = $00000400;  // (1 << 10) valid tabpos\r
8028   HHWIN_PARAM_TABORDER        = $00000800;  // (1 << 11) valid taborder\r
8029   HHWIN_PARAM_HISTORY_COUNT   = $00001000;  // (1 << 12) valid cHistory\r
8030   HHWIN_PARAM_CUR_TAB         = $00002000;  // (1 << 13) valid curNavType\r
8032   { button constants }\r
8034 const\r
8035   HHWIN_BUTTON_EXPAND         = $00000002;  // (1 << 1)  Expand/contract button\r
8036   HHWIN_BUTTON_BACK           = $00000004;  // (1 << 2)  Back button\r
8037   HHWIN_BUTTON_FORWARD        = $00000008;  // (1 << 3)  Forward button\r
8038   HHWIN_BUTTON_STOP           = $00000010;  // (1 << 4)  Stop button\r
8039   HHWIN_BUTTON_REFRESH        = $00000020;  // (1 << 5)  Refresh button\r
8040   HHWIN_BUTTON_HOME           = $00000040;  // (1 << 6)  Home button\r
8041   HHWIN_BUTTON_BROWSE_FWD     = $00000080;  // (1 << 7)  not implemented\r
8042   HHWIN_BUTTON_BROWSE_BCK     = $00000100;  // (1 << 8)  not implemented\r
8043   HHWIN_BUTTON_NOTES          = $00000200;  // (1 << 9)  not implemented\r
8044   HHWIN_BUTTON_CONTENTS       = $00000400;  // (1 << 10) not implemented\r
8045   HHWIN_BUTTON_SYNC           = $00000800;  // (1 << 11) Sync button\r
8046   HHWIN_BUTTON_OPTIONS        = $00001000;  // (1 << 12) Options button\r
8047   HHWIN_BUTTON_PRINT          = $00002000;  // (1 << 13) Print button\r
8048   HHWIN_BUTTON_INDEX          = $00004000;  // (1 << 14) not implemented\r
8049   HHWIN_BUTTON_SEARCH         = $00008000;  // (1 << 15) not implemented\r
8050   HHWIN_BUTTON_HISTORY        = $00010000;  // (1 << 16) not implemented\r
8051   HHWIN_BUTTON_FAVORITES      = $00020000;  // (1 << 17) not implemented\r
8052   HHWIN_BUTTON_JUMP1          = $00040000;  // (1 << 18)\r
8053   HHWIN_BUTTON_JUMP2          = $00080000;  // (1 << 19)\r
8054   HHWIN_BUTTON_ZOOM           = $00100000;  // (1 << 20)\r
8055   HHWIN_BUTTON_TOC_NEXT       = $00200000;  // (1 << 21)\r
8056   HHWIN_BUTTON_TOC_PREV       = $00400000;  // (1 << 22)\r
8058   HHWIN_DEF_BUTTONS           = (HHWIN_BUTTON_EXPAND\r
8059                                  OR HHWIN_BUTTON_BACK\r
8060                                  OR HHWIN_BUTTON_OPTIONS\r
8061                                  OR HHWIN_BUTTON_PRINT);\r
8064   { Button IDs }\r
8066 const\r
8067   IDTB_EXPAND             = 200;\r
8068   IDTB_CONTRACT           = 201;\r
8069   IDTB_STOP               = 202;\r
8070   IDTB_REFRESH            = 203;\r
8071   IDTB_BACK               = 204;\r
8072   IDTB_HOME               = 205;\r
8073   IDTB_SYNC               = 206;\r
8074   IDTB_PRINT              = 207;\r
8075   IDTB_OPTIONS            = 208;\r
8076   IDTB_FORWARD            = 209;\r
8077   IDTB_NOTES              = 210; // not implemented\r
8078   IDTB_BROWSE_FWD         = 211;\r
8079   IDTB_BROWSE_BACK        = 212;\r
8080   IDTB_CONTENTS           = 213; // not implemented\r
8081   IDTB_INDEX              = 214; // not implemented\r
8082   IDTB_SEARCH             = 215; // not implemented\r
8083   IDTB_HISTORY            = 216; // not implemented\r
8084   IDTB_FAVORITES          = 217; // not implemented\r
8085   IDTB_JUMP1              = 218;\r
8086   IDTB_JUMP2              = 219;\r
8087   IDTB_CUSTOMIZE          = 221;\r
8088   IDTB_ZOOM               = 222;\r
8089   IDTB_TOC_NEXT           = 223;\r
8090   IDTB_TOC_PREV           = 224;\r
8093   { Notification codes }\r
8095 const\r
8096   HHN_FIRST       = (0-860);\r
8097   HHN_LAST        = (0-879);\r
8099   HHN_NAVCOMPLETE   = (HHN_FIRST-0);\r
8100   HHN_TRACK         = (HHN_FIRST-1);\r
8101   HHN_WINDOW_CREATE = (HHN_FIRST-2);\r
8104 type\r
8105   {*** Used by command HH_GET_LAST_ERROR\r
8106    NOTE: Not part of the htmlhelp.h but documented in HH Workshop help\r
8107          You must call SysFreeString(xx.description) to free BSTR\r
8108   }\r
8109   tagHH_LAST_ERROR = packed record\r
8110     cbStruct:      Integer;     // sizeof this structure\r
8111     hr:            Integer;     // Specifies the last error code.\r
8112     description:   PWideChar;   // (BSTR) Specifies a Unicode string containing a description of the error.\r
8113   end;\r
8114   HH_LAST_ERROR = tagHH_LAST_ERROR;\r
8115   THHLastError = tagHH_LAST_ERROR;\r
8118 type\r
8119   {*** Notify event info for HHN_NAVCOMPLETE, HHN_WINDOW_CREATE }\r
8120   PHHNNotify = ^THHNNotify;\r
8121   tagHHN_NOTIFY = packed record\r
8122     hdr:    TNMHdr;\r
8123     pszUrl: PChar;              //PCSTR: Multi-byte, null-terminated string\r
8124   end;\r
8125   HHN_NOTIFY = tagHHN_NOTIFY;\r
8126   THHNNotify = tagHHN_NOTIFY;\r
8128   {** Use by command HH_DISPLAY_TEXT_POPUP}\r
8129   PHHPopup = ^THHPopup;\r
8130   tagHH_POPUP = packed record\r
8131     cbStruct:      Integer;     // sizeof this structure\r
8132     hinst:         HINST;       // instance handle for string resource\r
8133     idString:      cardinal;    // string resource id, or text id if pszFile is specified in HtmlHelp call\r
8134     pszText:       PChar;       // used if idString is zero\r
8135     pt:            TPOINT;      // top center of popup window\r
8136     clrForeground: COLORREF;    // use -1 for default\r
8137     clrBackground: COLORREF;    // use -1 for default\r
8138     rcMargins:     TRect;       // amount of space between edges of window and text, -1 for each member to ignore\r
8139     pszFont:       PChar;       // facename, point size, char set, BOLD ITALIC UNDERLINE\r
8140   end;\r
8141   HH_POPUP = tagHH_POPUP;\r
8142   THHPopup = tagHH_POPUP;\r
8144   {** Use by commands - HH_ALINK_LOOKUP, HH_KEYWORD_LOOKUP}\r
8145   PHHAKLink = ^THHAKLink;\r
8146   tagHH_AKLINK = packed record\r
8147     cbStruct:      integer;     // sizeof this structure\r
8148     fReserved:     BOOL;        // must be FALSE (really!)\r
8149     pszKeywords:   PChar;       // semi-colon separated keywords\r
8150     pszUrl:        PChar;       // URL to jump to if no keywords found (may be NULL)\r
8151     pszMsgText:    PChar;       // Message text to display in MessageBox if pszUrl is NULL and no keyword match\r
8152     pszMsgTitle:   PChar;       // Message text to display in MessageBox if pszUrl is NULL and no keyword match\r
8153     pszWindow:     PChar;       // Window to display URL in\r
8154     fIndexOnFail:  BOOL;        // Displays index if keyword lookup fails.\r
8155   end;\r
8156   HH_AKLINK = tagHH_AKLINK;\r
8157   THHAKLink = tagHH_AKLINK;\r
8160 const\r
8161   HHWIN_NAVTYPE_TOC          = 0;\r
8162   HHWIN_NAVTYPE_INDEX        = 1;\r
8163   HHWIN_NAVTYPE_SEARCH       = 2;\r
8164   HHWIN_NAVTYPE_FAVORITES    = 3;\r
8165   HHWIN_NAVTYPE_HISTORY      = 4;   // not implemented\r
8166   HHWIN_NAVTYPE_AUTHOR       = 5;\r
8167   HHWIN_NAVTYPE_CUSTOM_FIRST = 11;\r
8170 const\r
8171   IT_INCLUSIVE = 0;\r
8172   IT_EXCLUSIVE = 1;\r
8173   IT_HIDDEN    = 2;\r
8175 type\r
8176   PHHEnumIT = ^THHEnumIT;\r
8177   tagHH_ENUM_IT = packed record                  //tagHH_ENUM_IT, HH_ENUM_IT, *PHH_ENUM_IT\r
8178     cbStruct:           Integer;     // size of this structure\r
8179     iType:              Integer;     // the type of the information type ie. Inclusive, Exclusive, or Hidden\r
8180     pszCatName:         PAnsiChar;   // Set to the name of the Category to enumerate the info types in a category; else NULL\r
8181     pszITName:          PAnsiChar;   // volitile pointer to the name of the infotype. Allocated by call. Caller responsible for freeing\r
8182     pszITDescription:   PAnsiChar;   // volitile pointer to the description of the infotype.\r
8183   end;\r
8184   THHEnumIT = tagHH_ENUM_IT;\r
8187 type\r
8188   PHHEnumCat = ^THHEnumCat;\r
8189   tagHH_ENUM_CAT = packed record                 //tagHH_ENUM_CAT, HH_ENUM_CAT, *PHH_ENUM_CAT\r
8190     cbStruct:           Integer;     // size of this structure\r
8191     pszCatName:         PAnsiChar;   // volitile pointer to the category name\r
8192     pszCatDescription:  PAnsiChar;   // volitile pointer to the category description\r
8193   end;\r
8194   THHEnumCat = tagHH_ENUM_CAT;\r
8197 type\r
8198   PHHSetInfoType = ^THHSetInfoType;\r
8199   tagHH_SET_INFOTYPE = packed record             //tagHH_SET_INFOTYPE, HH_SET_INFOTYPE, *PHH_SET_INFOTYPE\r
8200     cbStruct:           Integer;     // the size of this structure\r
8201     pszCatName:         PAnsiChar;   // the name of the category, if any, the InfoType is a member of.\r
8202     pszInfoTypeName:    PAnsiChar;   // the name of the info type to add to the filter\r
8203   end;\r
8204   THHSetInfoType = tagHH_SET_INFOTYPE;\r
8207 type\r
8208   HH_INFOTYPE = DWORD;\r
8209   THHInfoType = HH_INFOTYPE;\r
8210   PHHInfoType = ^THHInfoType;        //PHH_INFOTYPE\r
8213 const\r
8214   HHWIN_NAVTAB_TOP    = 0;\r
8215   HHWIN_NAVTAB_LEFT   = 1;\r
8216   HHWIN_NAVTAB_BOTTOM = 2;\r
8218 const\r
8219   HH_MAX_TABS  = 19;                 // maximum number of tabs\r
8220 const\r
8221   HH_TAB_CONTENTS     = 0;\r
8222   HH_TAB_INDEX        = 1;\r
8223   HH_TAB_SEARCH       = 2;\r
8224   HH_TAB_FAVORITES    = 3;\r
8225   HH_TAB_HISTORY      = 4;\r
8226   HH_TAB_AUTHOR       = 5;\r
8227   HH_TAB_CUSTOM_FIRST = 11;\r
8228   HH_TAB_CUSTOM_LAST  = HH_MAX_TABS;\r
8230   HH_MAX_TABS_CUSTOM = (HH_TAB_CUSTOM_LAST - HH_TAB_CUSTOM_FIRST + 1);\r
8234   { HH_DISPLAY_SEARCH Command Related Structures and Constants }\r
8236 const\r
8237   HH_FTS_DEFAULT_PROXIMITY = (-1);\r
8239 type\r
8240   {** Used by command HH_DISPLAY_SEARCH}\r
8241   PHHFtsQuery = ^THHFtsQuery;\r
8242   tagHH_FTS_QUERY = packed record          //tagHH_FTS_QUERY, HH_FTS_QUERY\r
8243     cbStruct:          integer;      // Sizeof structure in bytes.\r
8244     fUniCodeStrings:   BOOL;         // TRUE if all strings are unicode.\r
8245     pszSearchQuery:    PChar;        // String containing the search query.\r
8246     iProximity:        LongInt;      // Word proximity.\r
8247     fStemmedSearch:    Bool;         // TRUE for StemmedSearch only.\r
8248     fTitleOnly:        Bool;         // TRUE for Title search only.\r
8249     fExecute:          Bool;         // TRUE to initiate the search.\r
8250     pszWindow:         PChar;        // Window to display in\r
8251   end;\r
8252   THHFtsQuery = tagHH_FTS_QUERY;\r
8255   { HH_WINTYPE Structure }\r
8257 type\r
8258   {** Used by commands HH_GET_WIN_TYPE, HH_SET_WIN_TYPE}\r
8259   PHHWinType = ^THHWinType;\r
8260   tagHH_WINTYPE = packed record             //tagHH_WINTYPE, HH_WINTYPE, *PHH_WINTYPE;\r
8261     cbStruct:          Integer;      // IN: size of this structure including all Information Types\r
8262     fUniCodeStrings:   BOOL;         // IN/OUT: TRUE if all strings are in UNICODE\r
8263     pszType:           PChar;        // IN/OUT: Name of a type of window\r
8264     fsValidMembers:    DWORD;        // IN: Bit flag of valid members (HHWIN_PARAM_)\r
8265     fsWinProperties:   DWORD;        // IN/OUT: Properties/attributes of the window (HHWIN_)\r
8267     pszCaption:        PChar;        // IN/OUT: Window title\r
8268     dwStyles:          DWORD;        // IN/OUT: Window styles\r
8269     dwExStyles:        DWORD;        // IN/OUT: Extended Window styles\r
8270     rcWindowPos:       TRect;        // IN: Starting position, OUT: current position\r
8271     nShowState:        Integer;      // IN: show state (e.g., SW_SHOW)\r
8273     hwndHelp:          HWND;         // OUT: window handle\r
8274     hwndCaller:        HWND;         // OUT: who called this window\r
8276     paInfoTypes:       PHHInfoType;  // IN: Pointer to an array of Information Types\r
8278     { The following members are only valid if HHWIN_PROP_TRI_PANE is set }\r
8280     hwndToolBar:       HWND;         // OUT: toolbar window in tri-pane window\r
8281     hwndNavigation:    HWND;         // OUT: navigation window in tri-pane window\r
8282     hwndHTML:          HWND;         // OUT: window displaying HTML in tri-pane window\r
8283     iNavWidth:         Integer;      // IN/OUT: width of navigation window\r
8284     rcHTML:            TRect;        // OUT: HTML window coordinates\r
8286     pszToc:            PChar;        // IN: Location of the table of contents file\r
8287     pszIndex:          PChar;        // IN: Location of the index file\r
8288     pszFile:           PChar;        // IN: Default location of the html file\r
8289     pszHome:           PChar;        // IN/OUT: html file to display when Home button is clicked\r
8290     fsToolBarFlags:    DWORD;        // IN: flags controling the appearance of the toolbar (HHWIN_BUTTON_)\r
8291     fNotExpanded:      BOOL;         // IN: TRUE/FALSE to contract or expand, OUT: current state\r
8292     curNavType:        Integer;      // IN/OUT: UI to display in the navigational pane\r
8293     tabpos:            Integer;      // IN/OUT: HHWIN_NAVTAB_TOP, HHWIN_NAVTAB_LEFT, or HHWIN_NAVTAB_BOTTOM\r
8294     idNotify:          Integer;      // IN: ID to use for WM_NOTIFY messages\r
8295     tabOrder: packed array[0..HH_MAX_TABS] of Byte;  // IN/OUT: tab order: Contents, Index, Search, History, Favorites, Reserved 1-5, Custom tabs\r
8296     cHistory:          Integer;       // IN/OUT: number of history items to keep (default is 30)\r
8297     pszJump1:          PChar;         // Text for HHWIN_BUTTON_JUMP1\r
8298     pszJump2:          PChar;         // Text for HHWIN_BUTTON_JUMP2\r
8299     pszUrlJump1:       PChar;         // URL for HHWIN_BUTTON_JUMP1\r
8300     pszUrlJump2:       PChar;         // URL for HHWIN_BUTTON_JUMP2\r
8301     rcMinSize:         TRect;         // Minimum size for window (ignored in version 1)\r
8303     cbInfoTypes:       Integer;       // size of paInfoTypes;\r
8304     pszCustomTabs:     PChar;         // multiple zero-terminated strings\r
8305   end;\r
8306   HH_WINTYPE = tagHH_WINTYPE;\r
8307   THHWinType = tagHH_WINTYPE;\r
8309 const\r
8310   HHACT_TAB_CONTENTS   = 0;\r
8311   HHACT_TAB_INDEX      = 1;\r
8312   HHACT_TAB_SEARCH     = 2;\r
8313   HHACT_TAB_HISTORY    = 3;\r
8314   HHACT_TAB_FAVORITES  = 4;\r
8316   HHACT_EXPAND         = 5;\r
8317   HHACT_CONTRACT       = 6;\r
8318   HHACT_BACK           = 7;\r
8319   HHACT_FORWARD        = 8;\r
8320   HHACT_STOP           = 9;\r
8321   HHACT_REFRESH        = 10;\r
8322   HHACT_HOME           = 11;\r
8323   HHACT_SYNC           = 12;\r
8324   HHACT_OPTIONS        = 13;\r
8325   HHACT_PRINT          = 14;\r
8326   HHACT_HIGHLIGHT      = 15;\r
8327   HHACT_CUSTOMIZE      = 16;\r
8328   HHACT_JUMP1          = 17;\r
8329   HHACT_JUMP2          = 18;\r
8330   HHACT_ZOOM           = 19;\r
8331   HHACT_TOC_NEXT       = 20;\r
8332   HHACT_TOC_PREV       = 21;\r
8333   HHACT_NOTES          = 22;\r
8335   HHACT_LAST_ENUM      = 23;\r
8338 type\r
8339   {*** Notify event info for HHN_TRACK }\r
8340   PHHNTrack = ^THHNTrack;\r
8341   tagHHNTRACK = packed record                  //tagHHNTRACK, HHNTRACK;\r
8342     hdr:               TNMHdr;\r
8343     pszCurUrl:         PChar;                  // Multi-byte, null-terminated string  \r
8344     idAction:          Integer;                // HHACT_ value\r
8345     phhWinType:        PHHWinType;             // Current window type structure\r
8346   end;\r
8347   HHNTRACK = tagHHNTRACK;\r
8348   THHNTrack = tagHHNTRACK;\r
8351 ///////////////////////////////////////////////////////////////////////////////\r
8352 //\r
8353 // Global Control Properties.\r
8354 //\r
8355 const\r
8356   HH_GPROPID_SINGLETHREAD     = 1;      // VARIANT_BOOL: True for single thread\r
8357   HH_GPROPID_TOOLBAR_MARGIN   = 2;      // long: Provides a left/right margin around the toolbar.\r
8358   HH_GPROPID_UI_LANGUAGE      = 3;      // long: LangId of the UI.\r
8359   HH_GPROPID_CURRENT_SUBSET   = 4;      // BSTR: Current subset.\r
8360   HH_GPROPID_CONTENT_LANGUAGE = 5;      // long: LandId for desired content.\r
8362 type\r
8363   tagHH_GPROPID = HH_GPROPID_SINGLETHREAD..HH_GPROPID_CONTENT_LANGUAGE;                //tagHH_GPROPID, HH_GPROPID\r
8364   HH_GPROPID = tagHH_GPROPID;\r
8365   THHGPropID = HH_GPROPID;\r
8367 ///////////////////////////////////////////////////////////////////////////////\r
8368 //\r
8369 // Global Property structure\r
8370 //\r
8371 {type\r
8372   PHHGlobalProperty = ^THHGlobalProperty;\r
8373   tagHH_GLOBAL_PROPERTY = record                  //tagHH_GLOBAL_PROPERTY, HH_GLOBAL_PROPERTY\r
8374     id:                THHGPropID;\r
8375     Dummy:             Integer;                  // Added to enforce 8-byte packing\r
8376     var_:              VARIANT;\r
8377   end;\r
8378   HH_GLOBAL_PROPERTY = tagHH_GLOBAL_PROPERTY;\r
8379   THHGlobalProperty = tagHH_GLOBAL_PROPERTY;}\r
8380 //[END OF HTMLHELP DECLARATIONS]\r
8382 //[GetCtlBrush DECLARATIONS]\r
8383 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush; //forward;\r
8385 var\r
8386   Global_GetCtlBrushHandle: function( Sender: PControl ): HBrush = SimpleGetCtlBrushHandle;\r
8387   {* Is called to obtain brush handle. }\r
8389   Global_Align: procedure( Sender: PObj ) = DummyObjProc;\r
8390   {* Is set to perform aligning of control, and only if property Align\r
8391      is changed for TControl, or SetAlign method is called for it. }\r
8393 //[WndFunc DECLARATION]\r
8394 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )\r
8395                                    : Integer; stdcall;\r
8396 {* Global message handler for window. Redirects all messages to\r
8397    destination windows, obtaining target TControl object address from\r
8398    window itself, using GetProp API call. }\r
8400 //[Applet VARIABLES]\r
8401 var AppletRunning: Boolean;\r
8402     {* Is set to True while message loop is processing (in Run procedure). }\r
8403     AppletTerminated: Boolean;\r
8404     {* Is set to True when message loop is terminated. }\r
8405     Applet: PControl;\r
8406     {* Applet window object. Actually, can be set to main form if program\r
8407        not needed in special applet button window (useful to make applet\r
8408        button invisible on taskbar, or to have several forms with single\r
8409        applet button - crete it in that case using NewApplet). }\r
8410     AppButtonUsed: Boolean;\r
8411     {* True if special window to represent applet button (may be invisible)\r
8412        is used. If no, every form is represented with its own taskbar button\r
8413        (always visible). }\r
8415 //[Screen DECLARATIONS]\r
8416     ScreenCursor: HCursor;\r
8417     {* Set this global variable to override any cursor settings of current\r
8418        form or control. }\r
8420 function ScreenWidth: Integer;\r
8421 {* Returns screen width in pixels. }\r
8422 function ScreenHeight: Integer;\r
8423 {* Returns screen height in pixels. }\r
8425 //[Status DECLARATIONS]\r
8426 type\r
8427   TStatusOption = ( soNoSizeGrip, soTop );\r
8428   {* Options available for status bars. }\r
8429   TStatusOptions = Set of TStatusOption;\r
8430   {* Status bar options. }\r
8436 //[Run DECLARATION]\r
8437 procedure Run( var AppletWnd: PControl );\r
8438 {* |<#appbutton>\r
8439    Call this procedure to process messages loop of your program.\r
8440    Pass here pointer to applet button object (if You have created it\r
8441    - see NewApplet) or your main form object of type PControl (created\r
8442    using NewForm).\r
8443      |<br><br>\r
8444      |<h1 align=center><font color=#FF8040><a name="visual_objects_constructors"></a>\r
8445        Visual objects constructing functions\r
8446      |</font></h1>\r
8447    Following constructing functions for visual controls are available:\r
8448    |#control\r
8451 //[Applet FUNCTIONS DECLARATIONS]\r
8452 procedure AppletMinimize;\r
8453 {* Minimizes the application (Applet should be assigned to have effect). }\r
8454 procedure AppletHide;\r
8455 {* Minimizes and hides application. }\r
8456 procedure AppletRestore;\r
8457 {* Restores Applet when minimized. }\r
8459 //[Idle handler DECALRATIONS]\r
8460 {YS+}\r
8461 procedure RegisterIdleHandler( const OnIdle: TOnEvent );\r
8462 {* Registers new Idle handler. Idle handler is called each time when\r
8463    message queue becomes empty. }\r
8464 procedure UnRegisterIdleHandler( const OnIdle: TOnEvent );\r
8465 {* Unregisters Idle handler. }\r
8466 {YS-}\r
8470 //[InitCommonXXXX ANOTHER DECLARATIONS]\r
8472 {* ComCtrl32 controls initialization. }\r
8473 procedure InitCommonControls; stdcall;\r
8474 procedure DoInitCommonControls( dwICC: DWORD );\r
8475 {* Calls extended initialization for Common Controls (from ComCtrl32).\r
8476    Pass one of following constants:\r
8477    |<pre>\r
8478   ICC_LISTVIEW_CLASSES   = $00000001; // listview, header\r
8479   ICC_TREEVIEW_CLASSES   = $00000002; // treeview, tooltips\r
8480   ICC_BAR_CLASSES        = $00000004; // toolbar, statusbar, trackbar, tooltips\r
8481   ICC_TAB_CLASSES        = $00000008; // tab, tooltips\r
8482   ICC_UPDOWN_CLASS       = $00000010; // updown\r
8483   ICC_PROGRESS_CLASS     = $00000020; // progress\r
8484   ICC_HOTKEY_CLASS       = $00000040; // hotkey\r
8485   ICC_ANIMATE_CLASS      = $00000080; // animate\r
8486   ICC_WIN95_CLASSES      = $000000FF;\r
8487   ICC_DATE_CLASSES       = $00000100; // month picker, date picker, time picker, updown\r
8488   ICC_USEREX_CLASSES     = $00000200; // comboex\r
8489   ICC_COOL_CLASSES       = $00000400; // rebar (coolbar) control\r
8490   ICC_INTERNET_CLASSES   = $00000800;\r
8491   ICC_PAGESCROLLER_CLASS = $00001000; // page scroller\r
8492   ICC_NATIVEFNTCTL_CLASS = $00002000; // native font control\r
8493    |</pre>\r
8494     }\r
8496 const\r
8497   ICC_LISTVIEW_CLASSES   = $00000001; // listview, header\r
8498   ICC_TREEVIEW_CLASSES   = $00000002; // treeview, tooltips\r
8499   ICC_BAR_CLASSES        = $00000004; // toolbar, statusbar, trackbar, tooltips\r
8500   ICC_TAB_CLASSES        = $00000008; // tab, tooltips\r
8501   ICC_UPDOWN_CLASS       = $00000010; // updown\r
8502   ICC_PROGRESS_CLASS     = $00000020; // progress\r
8503   ICC_HOTKEY_CLASS       = $00000040; // hotkey\r
8504   ICC_ANIMATE_CLASS      = $00000080; // animate\r
8505   ICC_WIN95_CLASSES      = $000000FF;\r
8506   ICC_DATE_CLASSES       = $00000100; // month picker, date picker, time picker, updown\r
8507   ICC_USEREX_CLASSES     = $00000200; // comboex\r
8508   ICC_COOL_CLASSES       = $00000400; // rebar (coolbar) control\r
8509   ICC_INTERNET_CLASSES   = $00000800;\r
8510   ICC_PAGESCROLLER_CLASS = $00001000; // page scroller\r
8511   ICC_NATIVEFNTCTL_CLASS = $00002000; // native font control\r
8513 //[Ole DECLARATIONS]\r
8514 function OleInit: Boolean;\r
8515 {* Calls OleInitialize (once - all other calls are simulated by incrementing\r
8516    call counter. Every OleInit shoud be complemented with correspondent OleUninit.\r
8517    (Though, it is possible to call API function OleUnInitialize once to\r
8518    cancel all OleInit calls). }\r
8519 procedure OleUnInit;\r
8520 {* Decrements counter and calls OleUnInitialize when it is zeroed. }\r
8521 var OleInitCount: Integer;\r
8522 {-}\r
8524 function StringToOleStr(const Source: string): PWideChar;\r
8525 {* }\r
8527 {+}\r
8528 function SysAllocStringLen(psz: PWideChar; len: Integer): PWideChar; stdcall;\r
8529 procedure SysFreeString( psz: PWideChar ); stdcall;\r
8540 { -- Contructors for visual controls -- }\r
8541 //[NewXXXX DECLARATIONS]\r
8543 //[_NewWindowed DECLARATION]\r
8544 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;\r
8546 //[NewApplet DECLARATION]\r
8547 function NewApplet( const Caption: String ): PControl;\r
8548 {* |<#control>\r
8549    Creates applet button window, which has to be parent of all other forms\r
8550    in your project (but this is *not must*). See also comments about NewForm.\r
8551    |<br>\r
8552    Following methods, properties and events are useful to work with applet\r
8553    control:\r
8554    |#appbutton }\r
8556 //[NewForm DECLARATION]\r
8557 function NewForm( AParent: PControl; const Caption: String ): PControl;\r
8558 {* |<#control>\r
8559    Creates form window object and returns pointer to it. If You use only one form,\r
8560    and You are not going to do applet button on task bar invisible, it is not\r
8561    necessary to create also special applet button window - just pass\r
8562    your (main) form object to Run procedure. In that case, it is a good\r
8563    idea to assign pointer to your main form object to Applet variable\r
8564    immediately following creating it - because some objects (e.g. TTimer)\r
8565    want to have Applet assigned to something.\r
8566    |<br>\r
8567    |&D=<a href="tcontrol.htm#%1" target=_top> %0 </a>\r
8568    Following methods, properties and events are useful to work with forms\r
8569    (ones common for all visual objects, such as <D Left>, <D Top>, <D Width>,\r
8570    <D Height>, etc. are not listed here - look TControl for it):\r
8571    |#form }\r
8573 //[_NewControl DECLARATION]\r
8574 function _NewControl( AParent: PControl; ControlClassName: PChar;\r
8575          Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;\r
8577 //[NewButton DECLARATION]\r
8578 function NewButton( AParent: PControl; const Caption: String ): PControl;\r
8579 {* |<#control>\r
8580    Creates button on given parent control or form.\r
8581    Please note, that in Windows, buttons can not change its <D Font> color\r
8582    and to be <D Transparent>.\r
8583    |<br> Following methods, properies and events are (especially) useful with\r
8584    a button:\r
8585    |#button }\r
8587 //[NewBitBtn DECLARATION]\r
8588 function NewBitBtn( AParent: PControl; const Caption: String;\r
8589          Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap; GlyphCount: Integer ): PControl;\r
8590 {* |<#control>\r
8591    Creates image button (actually implemented as owner-drawn). In Options,\r
8592    it is possible to determine, whether bitmap or image list used to contain\r
8593    one or more (up to 5) images, correspondent to certain BitBtn state.\r
8594    |<br>&nbsp;&nbsp;&nbsp;\r
8595    For case of imagelist (option bboImageList), it is possible to use a\r
8596    number of glyphs from the image list, starting from image index given\r
8597    by GlyphCount parameter. Number of used glyphs is passed in that case\r
8598    in high word of GlyphCount parameter (if 0, one image is used therefore).\r
8599    For bboImageList, BitBtn can be Transparent (and in that case bboNoBorder\r
8600    style can be useful to draw custom buttons of non-rectangular shape).\r
8601    |<br>&nbsp;&nbsp;&nbsp;\r
8602    For case of bitmap BitBtn, image is stretched down (if too big), but can\r
8603    not be transparent. It is not necessary for bitmap BitBtn to pass correct\r
8604    GlyphCount - it is calculated on base of bitmap size, if 0 is passed.\r
8605    |<br>&nbsp;&nbsp;&nbsp;\r
8606    And, certainly, BitBtn can be without glyph image (text only). For that\r
8607    case, it is therefore is more flexible and power than usual Button (but\r
8608    requires more code). E.g., BitBtn can change its <D Font>, <D Color>,\r
8609    and to be totally <D Transparent>.\r
8610    Moreover, BitBtn can be <D Flat>, bboFixed, <D SpeedButton> and\r
8611    have property <D RepeatInterval>.\r
8612    |<br>&nbsp;&nbsp;&nbsp;\r
8613    Note: if You use bboFixed Style, use OnChange event instead of OnClick,\r
8614    because <D Checked> state is changed immediately however OnClick occure\r
8615    only when mouse or space key released (and can be not called at all if\r
8616    mouse button is released out of BitBtn bounds). Also, bboFixed defines\r
8617    only which glyph to show (the border if it is not turned off behaves as\r
8618    usual for a button, i.e. it becomes lowered and then raised again at any click).\r
8619    Here You can find references to other properties, events and methods\r
8620    applicable to BitBtn:\r
8621    |#bitbtn }\r
8623 //[NewLabel DECLARATION]\r
8624 function NewLabel( AParent: PControl; const Caption: String ): PControl;\r
8625 {* |<#control>\r
8626    Creates static text control (native Windows STATIC control).\r
8627    Use property <D Caption> at run time to change label text. Also\r
8628    it is possible to adjust label <D Font>, <D Brush> or <D Color>.\r
8629    Label can be <D Transparent>. If You want to have rotated text\r
8630    label, call NewLabelEffect instead and change its <D Font>.FontOrientation.\r
8631    Other references certain for a label:\r
8632    |#label }\r
8634 //[NewWordWrapLabel DECLARATION]\r
8635 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;\r
8636 {* |<#control>\r
8637    Creates multiline static text control (native Windows STATIC control),\r
8638    which can wrap long text onto several lines. See also NewLabel.\r
8639    See also:\r
8640    |#wwlabel\r
8641    |#label }\r
8643 //[NewLabelEffect DECLARATION]\r
8644 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;\r
8645 {* |<#control>\r
8646    Creates 3D-label with capability to rotate its text <D Caption>, which\r
8647    is controlled by changing <D Font>.FontOrientation property. If You want\r
8648    to get flat effect label (e.g. to rotate it only), pass <D ShadowDeep> = 0.\r
8649    Please note, that drawing procedure uses <D Canvas> property, so using of\r
8650    LabelEffect leads to increase size of executable.\r
8651    See also:\r
8652    |#3dlabel\r
8653    |#label }\r
8655 //[NewPaintbox DECLARATION]\r
8656 function NewPaintbox( AParent: PControl ): PControl;\r
8657 {* |<#control>\r
8658    Creates owner-drawn STATIC control. Set its <D OnPaint> event to\r
8659    perform custom painting.\r
8660    |#paintbox }\r
8662 //[NewImageShow DECLARATION]\r
8663 function NewImageShow( AParent: PControl; AImgList: PImageList; ImgIdx: Integer ): PControl;\r
8664 {* |<#control>\r
8665    Creates an image show control, implemented as a paintbox which is used to\r
8666    draw an image from the imagelist. At run-time, use property CurIndex to\r
8667    select another image from the imagelist, and a property ImageListNormal to\r
8668    use another image list. When the control is created, its size becomes\r
8669    equal to dimensions of imagelist (if any). }\r
8671 //[NewScrollBar DECLARATION]\r
8672 function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;\r
8673 { * not yet finished... }\r
8675 //[NewScrollBox DECLARATION]\r
8676 function NewScrollBox( AParent: PControl; EdgeStyle: TEdgeStyle;\r
8677          Bars: TScrollerBars ): PControl;\r
8678 {* |<#control>\r
8679    Creates simple scrolling box, which can be used any way you wish, e.g. to scroll\r
8680    certain large image. To provide automatic scrolling of a set of child controls,\r
8681    use advanced scroll box, created with NewScrollBoxEx. }\r
8683 procedure NotifyScrollBox( Self_, Child: PControl );\r
8686 function NewScrollBoxEx( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;\r
8687 {* |<#control>\r
8688    Creates extended scrolling box control, which automatically scrolls child\r
8689    controls (if any). }\r
8691 //[NewGradientPanel DECLARATION]\r
8692 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;\r
8693 {* |<#control>\r
8694    Creates gradient-filled STATIC control. To adjust colors at the\r
8695    run time, change <D Color1> and <D Color2> properties (which initially are\r
8696    assigned from Color1, Color2 parameters), and call <D Invalidate> method\r
8697    to repaint control. }\r
8699 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;\r
8700                              Style: TGradientStyle; Layout: TGradientLayout ): PControl;\r
8701 {* |<#control>\r
8702    Creates gradient-filled STATIC control. To adjust colors at the\r
8703    run time, change <D Color1> and <D Color2> properties (which initially are\r
8704    assigned from Color1, Color2 parameters), and call <D Invalidate> method\r
8705    to repaint control. Depending on style and first line/point layout, can\r
8706    looking different. Idea: Vladimir Stojiljkovic. }\r
8708 //[NewPanel DECLARATION]\r
8709 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;\r
8710 {* |<#control>\r
8711    Creates panel, which can be parent for other controls (though, any\r
8712    control can be used as a parent for other ones, but panel is specially\r
8713    designed for such purpose). }\r
8715 //[NewMDIxxx DECLARATIONS]\r
8716 function NewMDIClient( AParent: PControl; WindowMenu: THandle ): PControl;\r
8717 {* |<#control>\r
8718    Creates MDI client window, which is a special type of child window,\r
8719    containing all MDI child windows, created calling NewMDIChild function.\r
8720    On a form, MDI client behaves like a panel, so it can be placed and sized\r
8721    (or aligned) like any other controls. To minimize flick during resizing\r
8722    main form having another aligned controls, place MDI client window on\r
8723    a panel and align it caClient in the panel.\r
8724    |<br>Note:\r
8725    MDI client must be a single on the form. }\r
8727 function NewMDIChild( AParent: PControl; const ACaption: String ): PControl;\r
8728 {* |<#control>\r
8729    Creates MDI client window. AParent should be a MDI client window,\r
8730    created with NewMDIClient function. }\r
8732 //[NewSplitter DECLARATIONS]\r
8733 function NewSplitter( AParent: PControl; MinSizePrev, MinSizeNext: Integer ): PControl;\r
8734 {* |<#control>\r
8735    Creates splitter control, which will separate previous one (i.e. last\r
8736    created one before splitter on the same parent) from created\r
8737    next, allowing to user to adjust size of separated controls by dragging\r
8738    the splitter in desired direction. Created splitter becomes vertical\r
8739    or horizontal depending on Align style of previous control on the same\r
8740    parent (if caLeft/caRight then vertical, if caTop/caBottom then horizontal).\r
8741    |<br>&nbsp;&nbsp;&nbsp;\r
8742    Please note, what if previous control has no Align equal to caLeft/caRight\r
8743    or caTop/caBottom, splitter will not be able to function normally. If\r
8744    previous control does not exist, it is yet possible to use splitter as\r
8745    a resizeable panel (but set its initial Align value first - otherwise it\r
8746    is not set by default. Also, change Cursor property as You wish in that\r
8747    case, since it is not set too in case, when previous control does not\r
8748    exist).\r
8749    |<br>&nbsp;&nbsp;&nbsp;\r
8750    Additional parameters determine, which minimal size (width or height -\r
8751    correspondently to split direction) is allowed for left (top) control\r
8752    and to rest of client area of parent, correspondently. (It is possible\r
8753    later to set second control for checking its size with MinSizeNext\r
8754    value - using TControl.SecondControl property). If -1 passed,\r
8755    correspondent control size is not checked during dragging of splitter.\r
8756    Usually 0 is more suitable value (with this value, it is garantee, that\r
8757    splitter will be always available even if mouse was released far from the\r
8758    edge of form).\r
8759    |<br>&nbsp;&nbsp;&nbsp;\r
8760    It is possible for user to press Escape any time while dragging splitter\r
8761    to abort all adjustments made starting from left mouse button push and\r
8762    begin of drag the splitter. But remember please, that such event is\r
8763    controlled using timer, and therefore correspondent keyboard events\r
8764    are received by currently focused control. Be sure, that pressing Escape\r
8765    will not affect to any control on form, which could be focused, otherwise\r
8766    filter keyboard messages (by yourself) to prevent undesired handling of\r
8767    Escape key by certain controls while splitting. (Use Dragging property\r
8768    to check if splitter is dragging by user with mouse).\r
8769    |<br>&nbsp;&nbsp;&nbsp;\r
8770    See also:\r
8771    NewSplitterEx\r
8772    |#splitter }\r
8774 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;\r
8775          EdgeStyle: TEdgeStyle ): PControl;\r
8776 {* |<#control>\r
8777    Creates splitter control. Difference from NewSplitter is what it is possible\r
8778    to determine if a splitter will be beveled or not. See also NewSplitter. }\r
8780 //[NewGroupbox DECLARATION]\r
8781 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;\r
8782 {* |<#control>\r
8783    Creates group box control. Note, that to group radio items, group\r
8784    box is not necessary - any parent can play role of group for radio items.\r
8785    See also NewPanel. }\r
8787 //[NewCheckbox DECLARATION]\r
8788 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;\r
8789 {* |<#control>\r
8790    Creates check box control. Special properties, methods, events:\r
8791    |#checkbox }\r
8793 function NewCheckBox3State( AParent: PControl; const Caption: String ): PControl;\r
8794 {* |<#control>\r
8795    Creates check box control with 3 states. Special properties, methods,\r
8796    events:\r
8797    |#checkbox }\r
8799 //[NewRadiobox DECLARATION]\r
8800 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;\r
8801 {* |<#control>\r
8802    Creates radio box control. Alternative radio items must have the\r
8803    same parent window (regardless of its kind, either groupbox (NewGroupbox),\r
8804    panel (NewPanel) or form itself). Following properties, methods and events\r
8805    are specially for radiobox controls:\r
8806    |#radiobox }\r
8808 //[NewEditbox DECLARATION]\r
8809 function NewEditbox( AParent: PControl; Options: TEditOptions ): PControl;\r
8810 {* |<#control>\r
8811    Creates edit box control. To create multiline edit box, similar to\r
8812    TMemo in VCL, apply eoMultiline in Options. Following properties, methods,\r
8813    events are special for edit controls:\r
8814    |#edit }\r
8816 //[NewRichEdit DECLARATION]\r
8817 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;\r
8818 {* |<#control>\r
8819    Creates rich text edit control. A rich edit control is a window in which\r
8820    the user can enter and edit text. The text can be assigned character and\r
8821    paragraph formatting, and can include embedded OLE objects. Rich edit\r
8822    controls provide a programming interface for formatting text. However, an\r
8823    application must implement any user interface components necessary to make\r
8824    formatting operations available to the user.\r
8825    |<br>&nbsp;&nbsp;&nbsp;\r
8826    Note: eoPassword, eoMultiline options have no effect for RichEdit control.\r
8827    Some operations are supersided with special versions of those, created\r
8828    especially for RichEdit, but in some cases it is necessary to use\r
8829    another properties and methods, specially designed for RichEdit (see\r
8830    methods and properties, which names are starting from RE_...).\r
8831    |<br>&nbsp;&nbsp;&nbsp;\r
8832    Following properties, methods, events are special for edit controls:\r
8833    |#richedit\r
8834    }\r
8836 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;\r
8837 {* |<#control>\r
8838    Like NewRichEdit, but to work with older RichEdit control version 1.0\r
8839    (window class 'RichEdit' forced to use instead of 'RichEdit20A', even\r
8840    if library RICHED20.DLL found and loaded successfully). One more\r
8841    difference - OleInit is not called, so the most of OLE capabilities\r
8842    of RichEdit could not working. }\r
8844 //[NewListbox DECLARATION]\r
8845 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;\r
8846 {* |<#control>\r
8847    Creates list box control. Following properties, methods and events are\r
8848    special for Listbox:\r
8849    |#listbox }\r
8851 //[NewCombobox DECLARATION]\r
8852 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;\r
8853 {* |<#control>\r
8854    Creates new combo box control. Note, that it is not possible to align\r
8855    combobox caLeft or caRight: this can cause infinit recursion in the\r
8856    application.\r
8857    |<br>Following properties, methods and events are\r
8858    special for Combobox:\r
8859    |#combo }\r
8861 //[_NewCommonControl DECLARATION]\r
8862 function _NewCommonControl( AParent: PControl; ClassName: PChar; Style: DWORD;\r
8863                             Ctl3D: Boolean; Actions: PCommandActions ): PControl;\r
8865 //[NewProgressbar DECLARATION]\r
8866 function NewProgressbar( AParent: PControl ): PControl;\r
8867 {* |<#control>\r
8868    Creates progress bar control. Following properties are special for\r
8869    progress bar:\r
8870    |#progressbar\r
8871    See also NewProgressEx. }\r
8873 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;\r
8874 {* |<#control>\r
8875    Can create progress bar with smooth style (progress is not segmented\r
8876    onto bricks) or/and vertical progress bar - using additional parameter.\r
8877    For list of properties, suitable for progress bars, see NewProgressbar. }\r
8879 //[NewListVew DECLARATION]\r
8880 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;\r
8881   ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;\r
8882 {* |<#control>\r
8883    Creates list view control. It is very powerful control, which can partially\r
8884    compensate absence of grid controls (in lvsDetail view mode). Properties,\r
8885    methods and events, special for list view control are:\r
8886    |#listview }\r
8888 //[NewTreeView DECLARATION]\r
8889 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;\r
8890                       ImgListNormal, ImgListState: PImageList ): PControl;\r
8891 {* |<#control>\r
8892    Creates tree view control. See tree view methods and properties:\r
8893    |#treeview }\r
8895 //[NewTabControl DECLARATION]\r
8896 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;\r
8897          ImgList: PImageList; ImgList1stIdx: Integer ): PControl;\r
8898 {* |<#control>\r
8899    Creates new tab control (like notebook). To place child control on a certain\r
8900    page of TabControl, use property Pages[ Idx ], for example:\r
8901    ! Label1 := NewLabel( TabControl1.Pages[ 0 ], 'Label1' );\r
8902    | &nbsp;&nbsp;&nbsp;\r
8903    To determine number of pages at run time, use property <D Count>;\r
8904    |<br> to determine which page is currently selected (or to change\r
8905    selection), use property <D CurrentIndex>;\r
8906    |<br> to feedback to switch between tabs assign your handler to OnSelChange\r
8907    event;\r
8908    |<br>Note, that by default, tab control is created with a border lowered to\r
8909    tab control's parent. To remove it, you can apply WS_EX_TRANSPARENT extended\r
8910    style (see TControl.ExStyle property), but painting of some child controls\r
8911    can be strange a bit in this case (no border drawing for edit controls was\r
8912    found, but not always...). You can also apply style WS_THICKFRAME (TControl.Style\r
8913    property) to make the border raised.\r
8914    |<br> Other methods and properties, suitable for tab control, are:\r
8915    |#tabcontrol }\r
8917 //[NewToolbar DECLARATION]\r
8918 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;\r
8919                      Bitmap: HBitmap; Buttons: array of PChar;\r
8920                      BtnImgIdxArray: array of Integer ) : PControl;\r
8921 {* |<#control>\r
8922    Creates toolbar control. Bitmap must contain images for all buttons\r
8923    excluding separators (defined by string '-' in Buttons array), otherwise\r
8924    last buttons will no have images at all. Image width for every button\r
8925    is assumed to be equal to Bitmap height (if last of "squares" has\r
8926    insufficient width, it will not be used). To define fixed buttons, use\r
8927    characters '+' or '-' as a prefix for button string (even empty). To\r
8928    create groups of (radio-)buttons, use also '!' follow '+' or '-'. (These rules\r
8929    are similar used in menu creation). To define drop down button, use (as\r
8930    first) prefix '^'. (Do not forget to set <D OnTBDropDown> event for this\r
8931    case). If You want to assign images to buttons not in the same order\r
8932    how these are placed in Bitmap (or You use system bitmap), define for every\r
8933    button (in BtnImgIdxArray array) indexes for every button (excluding\r
8934    separator buttons). Otherwise, it is possible to define index only for first\r
8935    button (e.g., [0]). It is also possible to change TBImages[ ] property\r
8936    for such purpose, or do the same in method TBSetBtnImgIdx).\r
8937    |<br>\r
8938    Following properties, methods and event are specially designed to work with\r
8939    toolbar control:\r
8940    |#toolbar\r
8941    |<br>&nbsp;&nbsp;&nbsp;\r
8942    If your project uses Align property to align controls, this can conflict with\r
8943    toolbar native aligning. To solve such problem, place toolbar to parent panel,\r
8944    which has its own Align property assigned to desired value.\r
8945    |<br>\r
8946    To create toolbar with buttons, drawn from top to bottom, instead from left\r
8947    to right, combine caLeft / caRight in Align parameter and style tboWrapable\r
8948    when create toolbar. To adjust width of vertically aligned toolbar, it is\r
8949    possible to call ResizeParentLeft for it. E.g.:\r
8951    ! P0 := NewPanel( W, esRaised ) .SetSize( 30, 0 ) .SetAlign( caLeft );\r
8952    ! //                            ^^^^^^^^^^^^^^^^^            //////\r
8953    !TB := NewToolbar( P0, caLeft, [ tboNoDivider, tboWrapable ], DWORD(-1),\r
8954    ! //                   //////                  ///////////\r
8955    !                  [ ' ', ' ', ' ', '-', ' ', ' ' ],\r
8956    !      [ STD_FILEOPEN ] ).ResizeParentRight;\r
8957    !//Note, that caLeft is *must*, and tboWrapable style too. SetSize for\r
8958    !//parent panel is not necessary, but only if ResizeParentRight is called\r
8959    !//than for Toolbar.\r
8960    |<br><br>\r
8961    One more note: if You create toolbar without text labels (passing ' ' for\r
8962    each button You add), include also option tboTextRight to fix incorrect\r
8963    sizing of buttons under Windows9x.\r
8964    }\r
8966 //[NewDateTimePicker DECLARATION]\r
8967 function NewDateTimePicker( AParent: PControl; Options: TDateTimePickerOptions )\r
8968          : PControl;\r
8969 {* |<#control>\r
8970    Creates date and time picker common control.\r
8975 { -- Constructor for Image List objet -- }\r
8977 //[NewImageList DECLARATION]\r
8978 function NewImageList( AOwner: PControl ): PImageList;\r
8979 {* Constructor of TImageList object. Unlike other non-visual objects, image list\r
8980    can be parented by TControl object (but this does not *must*), and in that\r
8981    case it is destroyed automatically when its parent control is destroyed.\r
8982    Every control can have several TImageList objects, linked to a simple list.\r
8983    But if any TImageList object is destroyed, all following ones are destroyed\r
8984    too (at least, now I implemented it so). }\r
9017 //[TIMER]\r
9018 type\r
9019   {++}(*TTimer = class;*){--}\r
9020   PTimer = {-}^{+}TTimer;\r
9021 { ----------------------------------------------------------------------\r
9023                             TTimer object\r
9025 ----------------------------------------------------------------------- }\r
9026 //[TTimer DEFINITION]\r
9027   TTimer = object( TObj )\r
9028   {* Easy timer incapsulation object. Uses applet window to\r
9029      receive timer events. So, either assign your main form\r
9030      to Applet variable or create applet button object (and\r
9031      assign it to Applet) before enabling timer. }\r
9032   protected\r
9033     fHandle : Integer;\r
9034     fEnabled: Boolean;\r
9035     fInterval: Integer;\r
9036     fOnTimer: TOnEvent;\r
9037     procedure SetEnabled(const Value: Boolean); virtual;\r
9038     procedure SetInterval(const Value: Integer);\r
9039   protected\r
9040   {++}(*public*){--}\r
9041     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
9042     {* Destructor. }\r
9043   public\r
9044     property Handle : Integer read fHandle;\r
9045     {* Windows timer object handle. }\r
9046     property Enabled : Boolean read fEnabled write SetEnabled;\r
9047     {* True, is timer is on. Initially, always False. Before assigning True,\r
9048        make sure, that Applet global variable is assigned to applet object\r
9049        (NewApplet) or to form (NewForm). }\r
9050     property Interval : Integer read fInterval write SetInterval;\r
9051     {* Interval in milliseconds (1000 is default and means 1 second). }\r
9052     property OnTimer : TOnEvent read fOnTimer write fOnTimer;\r
9053     {* Event, which is called when time interval is over. }\r
9054   end;\r
9055 //[END OF TTimer DEFINITION]\r
9057 //[NewTimer DECLARATION]\r
9058 function NewTimer( Interval: Integer ): PTimer;\r
9059 {* Constructs initially disabled timer with interval 1000 (1 second). }\r
9062 //[MULTIMEDIA TIMER]\r
9063 type\r
9064   {++}(*TMMTimer = class;*){--}\r
9065   PMMTimer = {-}^{+}TMMTimer;\r
9067 //[TMMTimer DEFINITION]\r
9068   TMMTimer = object( TTimer )\r
9069   {* Multimedia timer incapsulation object. Does not require Applet or special\r
9070      window to handle it. System creates a thread for each high resolution\r
9071      timer, so using many such objects can degrade total PC performance. }\r
9072   protected\r
9073     FResolution: Integer;\r
9074     FPeriodic: Boolean;\r
9075     procedure SetEnabled(const Value: Boolean); {-}virtual;{+}{++}(*override;*){--}\r
9076   public\r
9077     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
9078     {* }\r
9079     property Resolution: Integer read FResolution write FResolution;\r
9080     {* Minimum timer resolution. The less the more accuracy (0 is exactly\r
9081        Interval milliseconds between timer shots). It is recommended to set\r
9082        this property greater to prevent entire system from reducing overhead.\r
9083        If you change this value, reset and then set Enabled again to apply\r
9084        changes. }\r
9085     property Periodic: Boolean read FPeriodic write FPeriodic;\r
9086     {* TRUE, if timer is periodic (default). Otherwise, timer is one-shot\r
9087        (set it Enabled every time in such case for each shot). If you change\r
9088        this property, reset and set Enabled property again to get effect. }\r
9089   end;\r
9090 //[END OF TMMTimer DEFINITION]\r
9092 //[NewMMTimer DECLARATION]\r
9093 function NewMMTimer( Interval: Integer ): PMMTimer;\r
9094 {* Creates multimedia timer object. Initially, it has Resolution = 0,\r
9095    Periodic = TRUE and Enabled = FALSE. Do not forget also to assign your\r
9096    event handler to OnTimer to do something on timer shot. }\r
9110 //[DIRCHANGE]\r
9111 type\r
9112   {++}(*TDirChange = class;*){--}\r
9113   PDirChange = {-}^{+}TDirChange;\r
9114   {* }\r
9116   TOnDirChange = procedure (Sender: PDirChange; const Path: string) of object;\r
9117   {* Event type to define OnChange event for folder monitoring objects. }\r
9119   TFileChangeFilters = (fncFileName, fncDirName, fncAttributes, fncSize,\r
9120       fncLastWrite, fncLastAccess, fncCreation, fncSecurity);\r
9121   {* Possible change monitor filters. }\r
9122   TFileChangeFilter = set of TFileChangeFilters;\r
9123   {* Set of filters to pass to a constructor of TDirChange object. }\r
9125 { ----------------------------------------------------------------------\r
9127                           TDirChange object\r
9129 ----------------------------------------------------------------------- }\r
9130 //[TDirChange DEFINITION]\r
9131   TDirChange = object(TObj)\r
9132   {* Object type to monitor changes in certain folder. }\r
9133   protected\r
9134     FOnChange: TOnDirChange;\r
9135     FHandle: THandle;\r
9136     FPath: string;\r
9137     FMonitor: PThread;\r
9138     function Execute( Sender: PThread ): Integer;\r
9139     procedure Changed;\r
9140   protected\r
9141   {++}(*public*){--}\r
9142     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
9143     {*}\r
9144   public\r
9145     property Handle: THandle read FHandle;\r
9146     {* Handle of file change notification object. *}\r
9147     property Path: String read FPath; //write SetPath;\r
9148     {* Path to monitored folder (to a root, if tree of folders\r
9149        is under monitoring). }\r
9150   end;\r
9151 //[END OF TDirChange DEFINITION]\r
9153 //[NewDirChangeNotifier DECLARATION]\r
9154 function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;\r
9155                                WatchSubtree: Boolean; ChangeProc: TOnDirChange ): PDirChange;\r
9156 {* Creates notification object TDirChangeNotifier. If something wrong (e.g.,\r
9157    passed directory does not exist), nil is returned as a result. When change\r
9158    is notified, ChangeProc is called always in main thread context.\r
9159    (Please note, that ChangeProc can not be nil).\r
9160    If empty filter is passed, default filter is used:\r
9161    [fncFileName..fncLastWrite]. }\r
9170 { -- TTrayIcon object -- }\r
9171 //[TRAYICON]\r
9173 type\r
9174   TOnTrayIconMouse = procedure( Sender: PObj; Message : Word ) of object;\r
9175   {* Event type to be called when Applet receives a message from an icon,\r
9176      added to the taskbar tray. }\r
9178   {++}(*TTrayIcon = class;*){--}\r
9179   PTrayIcon = {-}^{+}TTrayIcon;\r
9180 { ----------------------------------------------------------------------\r
9182                 TTrayIcon - icon in tray area of taskbar\r
9184 ----------------------------------------------------------------------- }\r
9185 //[TTrayIcon DEFINITION]\r
9186   TTrayIcon = object(TObj)\r
9187   {* Object to place (and change) a single icon onto taskbar tray. }\r
9188   protected\r
9189     FIcon: HIcon;\r
9190     FActive: Boolean;\r
9191     FTooltip: String;\r
9192     FOnMouse: TOnTrayIconMouse;\r
9193     FControl: PControl;\r
9194     fAutoRecreate: Boolean;\r
9195     FNoAutoDeactivate: Boolean;\r
9196     FWnd: HWnd;\r
9197     procedure SetIcon(const Value: HIcon);\r
9198     procedure SetActive(const Value: Boolean);\r
9199     procedure SetTrayIcon( const Value : DWORD );\r
9200     procedure SetTooltip(const Value: String);\r
9201     procedure SetAutoRecreate(const Value: Boolean);\r
9202   protected\r
9203   {++}(*public*){--}\r
9204     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
9205     {* Destructor. Use Free method instead (as usual). }\r
9206   public\r
9207     property Icon : HIcon read FIcon write SetIcon;\r
9208     {* Icon to be shown on taskbar tray. If not set, value of Active\r
9209        property has no effect. It is also possible to assign a value\r
9210        to Icon property after assigning True to Active to install\r
9211        icon first time or to replace icon with another one (e.g. to\r
9212        get animation effect).\r
9213        |<br>&nbsp;&nbsp;&nbsp;\r
9214        Previously allocated icon (if any) is not deleted using\r
9215        DeleteObject. This is normal for icons, loaded from resource\r
9216        (e.g., by LoadIcon API call). But if icon was created (e.g.) by\r
9217        CreateIconIndirect, your code is responsible for destroying\r
9218        of it). }\r
9219     property Active : Boolean read FActive write SetActive;\r
9220     {* Set it to True to show assigned Icon on taskbar tray. Default\r
9221        is False. Has no effect if Icon property is not assigned.\r
9222        TrayIcon is deactivated automatically when Applet is finishing\r
9223        (but only if Applet window is used as a "parent" for tray\r
9224        icon object). }\r
9225     property Tooltip : String read FTooltip write SetTooltip;\r
9226     {* Tooltip string, showing automatically when mouse is moving\r
9227        over installed icon. Though "huge string" type is used, only\r
9228        first 63 characters are considered. Also note, that only in\r
9229        most recent versions of Windows multiline tooltips are supported. }\r
9230     property OnMouse : TOnTrayIconMouse read FOnMouse write FOnMouse;\r
9231     {* Is called then mouse message is taking place concerning installed\r
9232        icon. Only type of message can be obtained (e.g. WM_MOUSEMOVE,\r
9233        WM_LBUTTONDOWN etc.) }\r
9234     property AutoRecreate: Boolean read fAutoRecreate write SetAutoRecreate;\r
9235     {* If set to TRUE, auto-recreating of tray icon is proveded in case,\r
9236        when Explorer is restarted for some (unpredictable) reasons. Otherwise,\r
9237        your tray icon is disappeared forever, and if this is the single way\r
9238        to communicate with your application, the user nomore can achieve it. }\r
9239     property NoAutoDeactivate: Boolean read FNoAutoDeactivate write FNoAutoDeactivate;\r
9240     {* If set to true, tray icon is not removed from tray automatically on\r
9241        WM_CLOSE message receive by owner control. Set Active := FALSE in\r
9242        your code for such case before accepting closing the form. }\r
9243     property Wnd: HWnd read FWnd write FWnd;\r
9244     {* A window to use as a base window for tray icon messages. Overrides\r
9245        parent Control handle is assigned. Note, that if Wnd property used,\r
9246        message handling is not done automatically, and you should do this in\r
9247        your code, or at least for one tray icon object, call AttachProc2Wnd. }\r
9248     procedure AttachProc2Wnd;\r
9249     {* Call this method for a tray icon object in case if Wnd used rather then\r
9250        control. It is enough to call this method once for each Wnd used, even\r
9251        if several other tray icons are also based on the same Wnd. See also\r
9252        DetachProc2Wnd method. }\r
9253     procedure DetachProc2Wnd;\r
9254     {* Call this method to detach window procedure attached via AttachProc2Wnd.\r
9255        Do it once for a Wnd, used as a base to handle tray icon messages.\r
9256        Caution! If you do not call this method before destroying Wnd, the\r
9257        application will not functioning normally. }\r
9258   end;\r
9259   {* When You create invisible application, which should be represented by\r
9260      only the tray icon, prepare a handle for the window, resposible for\r
9261      messages handling. Remember, that window handle is created automatically\r
9262      only when a window is showing first time. If window's property Visible is\r
9263      set to False, You should to call CreateWindow manually.\r
9264      <br>\r
9265      There is a known bug exist with similar invisible tray-iconized applications.\r
9266      When a menu is activated in response to tray mouse event, if there was\r
9267      not active window, belonging to the application, the menu is not disappeared\r
9268      when mouse is clicked anywhere else. This bug is occure in Windows9x/ME.\r
9269      To avoid it, activate first your form window. This last window shoud have\r
9270      status visible (but, certainly, there are no needs to place it on visible\r
9271      part of screen - change its position, so it will not be visible for user,\r
9272      if You wish).\r
9273      <br>\r
9274      Also, to make your application "invisible" but until special event is occure,\r
9275      use Applet separate from the main form, and make for both Visible := False.\r
9276      This allows for You to make your form visible any time You wish, and without\r
9277      making application button visible if You do not wish.\r
9278   }\r
9279   {= Êîãäà Âû äåëàåòå íåâèäèìîå ïðèëîæåíèå, êîòîðîå äîëæíî áûòü ïðåäñòàâëåíî\r
9280      òîëüêî èêîíêîé â òðåå, îáåñïå÷üòå íåíóëåâîé Handle äëÿ îêíà, îòâå÷àþùåãî\r
9281      çà îáðàáîòêó ñîîáùåíèé. Ïîìíèòå, ÷òî Handle îêíà ñîçäàåòñÿ àâòîìàòè÷åñêè\r
9282      òîëüêî â òîò ìîìåíò, êîãäà îíî äîëæíî ïîÿâèòüñÿ â ïåðâûé ðàç. Åñëè ñâîéñòâî\r
9283      îêíà Visible óñòàíîâëåíî â FALSE, íåîáõîäèìî âûçâàòü CreateWindow ñàìîñòîÿòåëüíî.\r
9284      <br>\r
9285      Ñóùåñòâóåò èçâåñòíûé BUG ñ ïîäîáíûìè íåâèäèìûìè ìèíèìèçèðîâàííûìè â òðåé\r
9286      ïðèëîæåíèÿìè. Êîãäà â îòâåò íà ñîáûòèå ìûøè àêòèâèçèðâàíî âûïàäàþùåå ìåíþ,\r
9287      îíî íå èñ÷åçàåò ïî ùåë÷êó ìûøè âíå ýòîãî ìåíþ. Ïðîèñõîäèò ýòî â Windows9x/ME.\r
9288      ÷òîáû ðåøèòü ýòó ïðîáëåìó, ñíà÷àëà àêòèâèçèðóéòå ñâîå îêíî (ôîðìó). Ýòî îêíî\r
9289      äîëæíî áûòü âèäèìûì (íî, êîíå÷íî, åãî ìîæíî ðàçìåñòèòü âíå ïðåäåëîâ âèäèìîé\r
9290      ÷àñòè ýêðàíà, òàê ÷òî ïîëüçîâàòåëþ åãî âèäíî íå áóäåò).\r
9291      <br>\r
9292      Òàê æå, ÷òîáû ñäåëàòü ïðèëîæåíèå íåâèäèìûì, ïî êðàéíåé ìåðå, ïîêà ýòî íå\r
9293      ïîòðåáóåòñÿ, èñïîëüçóéòå îòäåëüíûé ïðåäñòàâèòåëü êëàññà TControl - ãëîáàëüíóþ\r
9294      ïåðåìåííóþ Applet, è ïðèñâîéòå FALSE åå ñâîéñòâó Visible.\r
9295   }\r
9296 //[END OF TTrayIcon DEFINITION]\r
9298 //[NewTrayIcon DECLARATION]\r
9299 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;\r
9300 {* Constructor of TTrayIcon object. Pass main form or applet as Wnd\r
9301    parameter. }\r
9314 //[JUST ONE]\r
9315 { -- JustOne -- }\r
9317 type\r
9318   TOnAnotherInstance = procedure( const CmdLine: String ) of object;\r
9319   {* Event type to use in JustOneNotify function. }\r
9321 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;\r
9322 {* Returns True, if this is a first instance. For all other instances\r
9323    (application is already running), False is returned. }\r
9325 function JustOneNotify( Wnd: PControl; const Identifier : String;\r
9326                         const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;\r
9327 {* Returns True, if this is a first instance. For all other instances\r
9328    (application is already running), False is returned. If handler\r
9329    aOnAnotherInstance passed, it is called (in first instance) every time\r
9330    when another instance of an application is started, receiving command\r
9331    line used to run it. }\r
9349 { -- string (mainly) utility procedures and functions. -- }\r
9351 //[Message Box DECLARATIONS]\r
9352 function MsgBox( const S: String; Flags: DWORD ): DWORD;\r
9353 {* Displays message box with the same title as Applet.Caption. If applet\r
9354    is not running, and Applet global variable is not assigned, caption\r
9355    'Error' is displayed (but actually this is not an error - the system\r
9356    does so, if nil is passed as a title).\r
9357    |<br>&nbsp;&nbsp;&nbsp;\r
9358    Returns ID_... result (correspondently to flags passed (MB_OK, MBYESNO,\r
9359    etc. -> ID_OK, ID_YES, ID_NO, etc.) }\r
9360 procedure MsgOK( const S: String );\r
9361 {* Displays message box with the same title as Applet.Caption (or 'Error',\r
9362    if Applet is not running). }\r
9363 function ShowMsg( const S: String; Flags: DWORD ): DWORD;\r
9364 {* Displays message box like MsgBox, but uses Applet.Handle as a parent\r
9365    (so the message has no button on a task bar). }\r
9366 procedure ShowMessage( const S: String );\r
9367 {* Like ShowMsg, but has only styles MB_OK and MB_SETFOREGROUND. }\r
9368 procedure ShowMsgModal( const S: String );\r
9369 {* This message function can be used out of a message loop (e.g., after\r
9370    finishing the application). It is always modal.\r
9371       Actually, a form with word-wrap label (decorated as borderless edit\r
9372    box with btnFace color) and with OK button is created and shown modal.\r
9373    When a dialog is called from outside message loop, caption 'Information'\r
9374    is always displayed.\r
9375    Dialog form is automatically resized vertically to fit message text\r
9376    (but until screen height is achieved) and shown always centered on\r
9377    screen. The width is fixed (400 pixels).\r
9378    |<br>\r
9379    Do not use this function outside the message loop for case, when the\r
9380    Applet variable is not used in an application. }\r
9381 function ShowQuestion( const S: String; Answers: String ): Integer;\r
9382 {* Modal dialog like ShowMsgModal. It is based on KOL form, so it can\r
9383    be called also out of message loop, e.g. after finishing the\r
9384    application. Also, this function *must* be used in MDI applications\r
9385    in place of any dialog functions, based on MessageBox.\r
9386    |<br>\r
9387    The second parameter should be empty string or several possible\r
9388    answers separated by '/', e.g.: 'Yes/No/Cancel'. Result is\r
9389    a number answered, starting from 1. For example, if  'Cancel'\r
9390    was pressed, 3 will be returned.\r
9391    |<br>\r
9392    User can also press ESCAPE key, or close modal dialog. In such case\r
9393    -1 is returned. }\r
9394 function ShowQuestionEx( const S: String; Answers: String; CallBack: TOnEvent ): Integer;\r
9395 {* Like ShowQuestion, but with CallBack function, called just before showing\r
9396    the dialog. }\r
9397 procedure SpeakerBeep( Freq: Word; Duration: DWORD );\r
9398 {* On Windows NT, calls Windows.Beep. On Windows 9x, produces beep on speaker\r
9399    of desired frequency during given duration time (in milliseconds). }\r
9401 {++}(*\r
9402 function FormatMessage(dwFlags: DWORD; lpSource: Pointer; dwMessageId: DWORD; dwLanguageId: DWORD;\r
9403   lpBuffer: PChar; nSize: DWORD; Arguments: Pointer): DWORD; stdcall;\r
9404 *){--}\r
9405 function SysErrorMessage(ErrorCode: Integer): string;\r
9406 {* Creates and returns a string containing formatted system error message.\r
9407    It is possible then to display this message or write it to a log\r
9408    file, e.g.:\r
9409    !  ShowMsg( SysErrorMessage( GetLastError ) );\r
9413    |&R=<a name="%0"></a><font color=#FF8040><h1>%0</h1></font>\r
9414    <R 64-bit integer numbers>\r
9416 //[I64 TYPE]\r
9417 type\r
9418   I64 = record\r
9419   {* 64 bit integer record. Use it and correspondent functions below in KOL\r
9420      projects to avoid dependancy from Delphi version (earlier versions of\r
9421      Delphi had no Int64 type). }\r
9422     Lo, Hi: DWORD;\r
9423   end;\r
9424   PI64 = ^I64;\r
9425   {* }\r
9428 {-}\r
9429 {$IFNDEF _D4orHigher}\r
9430   Int64 = I64;\r
9431   PInt64 = PI64;\r
9432 {$ENDIF}\r
9434 function MakeInt64( Lo, Hi: DWORD ): I64;\r
9435 {* }\r
9436 function Int2Int64( X: Integer ): I64;\r
9437 {* }\r
9438 procedure IncInt64( var I64: I64; Delta: Integer );\r
9439 {* I64 := I64 + Delta; }\r
9440 procedure DecInt64( var I64: I64; Delta: Integer );\r
9441 {* I64 := I64 - Delta; }\r
9442 function Add64( const X, Y: I64 ): I64;\r
9443 {* Result := X + Y; }\r
9444 function Sub64( const X, Y: I64 ): I64;\r
9445 {* Result := X - Y; }\r
9446 function Neg64( const X: I64 ): I64;\r
9447 {* Result := -X; }\r
9448 function Mul64i( const X: I64; Mul: Integer ): I64;\r
9449 {* Result := X * Mul; }\r
9450 function Div64i( const X: I64; D: Integer ): I64;\r
9451 {* Result := X div D; }\r
9452 function Mod64i( const X: I64; D: Integer ): Integer;\r
9453 {* Result := X mod D; }\r
9454 function Sgn64( const X: I64 ): Integer;\r
9455 {* Result := sign( X ); i.e.:\r
9456    |<br>\r
9457    if X < 0 then -1\r
9458    |<br>\r
9459    if X = 0 then 0\r
9460    |<br>\r
9461    if X > 0 then 1 }\r
9462 function Cmp64( const X, Y: I64 ): Integer;\r
9463 {* Result := sign( X - Y ); i.e.\r
9464    |<br>\r
9465    if X < Y then -1\r
9466    |<br>\r
9467    if X = Y then 0\r
9468    |<br>\r
9469    if X > Y then 1 }\r
9470 function Int64_2Str( X: I64 ): String;\r
9471 {* }\r
9472 function Str2Int64( const S: String ): I64;\r
9473 {* }\r
9474 function Int64_2Double( const X: I64 ): Double;\r
9475 {* }\r
9476 function Double2Int64( D: Double ): I64;\r
9477 {*\r
9481   <R Floating point numbers>\r
9484 const\r
9485   NAN = 0.0 / 0.0;\r
9486 {+}\r
9487   {++}(*const NAN = 1e-100;*){--}\r
9490 function IsNan(const AValue: Double): Boolean;\r
9491 {* Checks is an argument passed is NAN. }\r
9493 function IntPower(Base: Extended; Exponent: Integer): Extended;\r
9494 {* Result := Base ^ Exponent; }\r
9496 //[String<->Double DECLARATIONS]\r
9497 function Str2Double( const S: String ): Double;\r
9498 {* }\r
9500 function Double2Str( D: Double ): String;\r
9501 {* }\r
9502 function Extended2Str( E: Extended ): String;\r
9503 {* }\r
9505 function Double2StrEx( D: Double ): String;\r
9506 {* experimental, do not use }\r
9508 function TruncD( D: Double ): Double;\r
9509 {* Result := trunc( D ) as Double;\r
9510 |<hr>\r
9526   <R Small bit arrays (max 32 bits in array)>\r
9527   See also TBits object.\r
9530 //[SMALL BIT ARRAYS DECLARATIONS]\r
9531 function GetBits( N: DWORD; first, last: Byte ): DWord;\r
9532 {* Retuns bits straing from <first> and to <last> inclusively. }\r
9533 function GetBitsL( N: DWORD; from, len: Byte ): DWord;\r
9534 {* Retuns len bits starting from index <from>.\r
9535 |<hr>\r
9547   <R Arithmetics, geometry and other utility functions>\r
9549   See also units KolMath.pas, CplxMath.pas and Err.pas.\r
9551 //[MulDiv DECLARATION]\r
9552 {$IFNDEF FPC}\r
9553 function MulDiv( A, B, C: Integer ): Integer;\r
9554 {* Returns A * B div C. Small and fast. }\r
9555 {$ENDIF}\r
9557 //[TMethod TYPE]\r
9558 type\r
9559 ///////////////////////////////////////////\r
9560 {$ifndef _D6orHigher}                    //\r
9561 ///////////////////////////////////////////\r
9562    TMethod = packed record\r
9563    {* Is defined here because using of VCL classes.pas unit is\r
9564       not recommended in XCL. This record type is used often\r
9565       to set/access event handlers, referring to a procedure\r
9566       of object (usually to set such event to an ordinal\r
9567       procedure setting Data field to nil. }\r
9568     Code: Pointer; // Pointer to method code.\r
9569     {* If used to fake assigning to event handler of type 'procedure\r
9570        of object' with ordinal procedure pointer, use symbol '@'\r
9571        before method:\r
9572        |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font face="Courier"><b>\r
9573        |    Method.Code := @MyProcedure;\r
9574        |</b></font> }\r
9575     Data: Pointer; // Pointer to object, owning the method.\r
9576     {* To fake event of type 'procedure of object' with setting it to\r
9577        ordinal procedure assign here NIL; }\r
9578    end;\r
9579    {* When assigning TMethod record to event handler, typecast it with\r
9580       desired event type, e.g.:\r
9581       |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font face="Courier"><b>\r
9582       |     SomeObject.OnSomeEvent := TOnSomeEvent( Method );\r
9583       |</b></font><br> }\r
9584 ///////////////////////////////////////////\r
9585 {$endif}                                 //\r
9586 ///////////////////////////////////////////\r
9587    PMethod = ^TMethod;\r
9588    {* }\r
9590    function MakeMethod( Data, Code: Pointer ): TMethod;\r
9591    {* Help function to construct TMethod record. Can be useful to\r
9592       assign regular type procedure/function as event handler for\r
9593       event, defined as object method (do not forget, that in that\r
9594       case it must have first dummy parameter to replace @Self,\r
9595       passed in EAX to methods of object). }\r
9597 //[Rectangles&Points DECLARATIONS]\r
9598    function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;\r
9599    {* Use it instead of VCL Rect function }\r
9600    function RectsEqual( const R1, R2: TRect ): Boolean;\r
9601    {* Returns True if rectangles R1 and R2 have the same bounds }\r
9602    function RectsIntersected( const R1, R2: TRect ): Boolean;\r
9603    {* Returns TRUE if rectangles R1 and R2 have at least one common point.\r
9604       Note, that right and bottom bounds of rectangles are not their part,\r
9605       so, if such points are lying on that bounds, FALSE is returned. }\r
9606    function PointInRect( const P: TPoint; const R: TRect ): Boolean;\r
9607    {* Returns True if point P is located in rectangle R (including\r
9608       left and top bounds but without right and bottom bounds of the\r
9609       rectangle). }\r
9610    function MakePoint( X, Y: Integer ): TPoint;\r
9611    {* Use instead of VCL function Point }\r
9612 //[MakeFlags DECLARATION]\r
9613    function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;\r
9614    {* }\r
9616   function MakeDateTimeRange( D1, D2: TDateTime ): TDateTimeRange;\r
9617   {* Returns TDateTimeRange from two TDateTime bounds. }\r
9619 //[Integer FUNCTIONS DECLARATIONS]\r
9620    procedure Swap( var X, Y: Integer );\r
9621    {* exchanging values }\r
9622    function Min( X, Y: Integer ): Integer;\r
9623    {* minimum of two integers }\r
9624    function Max( X, Y: Integer ): Integer;\r
9625    {* maximum of two integers }\r
9626    function Abs( X: Integer ): Integer;\r
9627    {* absolute value }\r
9628    function Sgn( X: Integer ): Integer;\r
9629    {* sign of X: if X < 0, -1 is returned, if > 0, then +1, otherwise 0. }\r
9630    function iSqrt( X: Integer ): Integer;\r
9631    {* square root\r
9632    |<hr>\r
9637   <R String to number and number to string conversions>\r
9639 //[Integer<->String DECLARATIONS]\r
9640 function Int2Hex( Value : DWord; Digits : Integer ) : String;\r
9641 {* Converts integer Value into string with hex number. Digits parameter\r
9642    determines minimal number of digits (will be completed by adding\r
9643    necessary number of leading zeroes). }\r
9644 function Int2Str( Value : Integer ) : String;\r
9645 {* Obvious. }\r
9646 function UInt2Str( Value: DWORD ): String;\r
9647 {* The same as Int2Str, but for unsigned integer value. }\r
9648 function Int2StrEx( Value, MinWidth: Integer ): String;\r
9649 {* Like Int2Str, but resulting string filled with leading spaces to provide\r
9650    at least MinWidth characters. }\r
9651 function Int2Rome( Value: Integer ): String;\r
9652 {* Represents number 1..8999 to Rome numer. }\r
9653 function Int2Ths( I : Integer ) : String;\r
9654 {* Converts integer into string, separating every three digits from each\r
9655    other by ',' character. (Convert to thousands). }\r
9656 function Int2Digs( Value, Digits : Integer ) : String;\r
9657 {* Converts integer to string, inserting necessary number of leading zeroes\r
9658    to provide desired length of string, given by Digits parameter. If\r
9659    resulting string is greater then Digits, string is not truncated anyway. }\r
9660 function Num2Bytes( Value : Double ) : String;\r
9661 {* Converts double float to string, considering it as a bytes count.\r
9662    If Value is sufficiently large, number is represented in kilobytes (with\r
9663    following letter K), or in megabytes (M), gigabytes (G) or terabytes (T).\r
9664    Resulting string number is truncated to two decimals (.XX) or to one (.X),\r
9665    if the second is 0. }\r
9666 function S2Int( S: PChar ): Integer;\r
9667 {* Converts null-terminated string to Integer. Scanning stopped when any\r
9668    non-digit character found. Even empty string or string not containing\r
9669    valid integer number silently converted to 0. }\r
9670 function Str2Int(const Value : String) : Integer;\r
9671 {* Converts string to integer. First character, which can not be\r
9672    recognized as a part of number, regards as a separator. Even\r
9673    empty string or string without number silently converted to 0. }\r
9674 function Hex2Int( const Value : String) : Integer;\r
9675 {* Converts hexadecimal number to integer. Scanning is stopped\r
9676    when first non-hexadicimal character is found. Leading dollar ('$')\r
9677    character is skept (if present). Minus ('-') is not concerning as\r
9678    a sign of number and also stops scanning.}\r
9679 function cHex2Int( const Value : String) : Integer;\r
9680 {* As Hex2Int, but also checks for leading '0x' and skips it. }\r
9681 function Octal2Int( const Value: String ) : Integer;\r
9682 {* Converts octal number to integer. Scanning is stopped on first\r
9683    non-octal digit (any char except 0..7). There are no checking if\r
9684    there octal numer in the parameter. If the first char is not octal\r
9685    digit, 0 is returned. }\r
9686 function Binary2Int( const Value: String ) : Integer;\r
9687 {* Converts binary number to integer. Like Octal2Int, but only digits\r
9688    0 and 1 are allowed. }\r
9689 {$IFNDEF _FPC}\r
9690 function Format( const fmt: string; params: array of const ): String;\r
9691 {* Uses API call to wvsprintf, so does not understand extra formats,\r
9692    such as floating point, date/time, currency conversions. See list of\r
9693    available formats in win32.hlp (topic wsprintf).\r
9694 |<hr>\r
9698    <R Working with null-terminated and ansi strings>\r
9700 {$ENDIF _FPC}\r
9701 //[String FUNCTIONS DECLARATIONS]\r
9702 function StrComp(const Str1, Str2: PChar): Integer;\r
9703 {* Compares two strings fast. -1: Str1<Str2; 0: Str1=Str2; +1: Str1>Str2 }\r
9704 function StrComp_NoCase(const Str1, Str2: PChar): Integer;\r
9705 {* Compares two strings fast without case sensitivity.\r
9706    Returns: -1 when Str1<Str2; 0 when Str1=Str2; +1 when Str1>Str2 }\r
9707 function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;\r
9708 {* Compare two strings (fast). Terminating 0 is not considered, so if\r
9709    strings are equal, comparing is continued up to MaxLen bytes.\r
9710    Since this, pass minimum of lengths as MaxLen. }\r
9711 function StrLComp_NoCase(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;\r
9712 {* Compare two strings fast without case sensitivity.\r
9713    Terminating 0 is not considered, so if strings are equal,\r
9714    comparing is continued up to MaxLen bytes.\r
9715    Since this, pass minimum of lengths as MaxLen. }\r
9716 function StrCopy( Dest, Source: PChar ): PChar;\r
9717 {* Copy source string to destination (fast). Pointer to Dest is returned. }\r
9718 function StrCat( Dest, Source: PChar ): PChar;\r
9719 {* Append source string to destination (fast). Pointer to Dest is returned. }\r
9720 function StrLen(const Str: PChar): Cardinal;\r
9721 {* StrLen returns the number of characters in Str, not counting the null\r
9722   terminator. }\r
9723 function StrScanLen(Str: PChar; Chr: Char; Len: Integer): PChar;\r
9724 {* Fast scans string Str of length Len searching character Chr.\r
9725    Pointer to a character next to found or to Str[Len] (if no one found)\r
9726    is returned. }\r
9727 function StrScan(Str: PChar; Chr: Char): PChar;\r
9728 {* Fast search of given character in a string. Pointer to found character\r
9729    (or nil) is returned. }\r
9730 function StrRScan(const Str: PChar; Chr: Char): PChar;\r
9731 {* StrRScan returns a pointer to the last occurrence of Chr in Str. If Chr\r
9732   does not occur in Str, StrRScan returns NIL. The null terminator is\r
9733   considered to be part of the string. }\r
9734 function StrIsStartingFrom( Str, Pattern: PChar ): Boolean;\r
9735 {* Returns True, if string Str is starting from Pattern, i.e. if\r
9736    Copy( Str, 1, StrLen( Pattern ) ) = Pattern. Str must not be nil! }\r
9737 function StrIsStartingFromNoCase( Str, Pattern: PChar ): Boolean;\r
9738 {* Like StrIsStartingFrom above, but without case sensitivity. }\r
9739 function TrimLeft(const S: string): string;\r
9740 {* Removes spaces, tabulations and control characters from the starting\r
9741    of string S. }\r
9742 function TrimRight(const S: string): string;\r
9743 {* Removes spaces, tabulates and other control characters from the\r
9744    end of string S. }\r
9745 function Trim( const S : string): string;\r
9746 {* Makes TrimLeft and TrimRight for given string. }\r
9747 function RemoveSpaces( const S: String ): String;\r
9748 {* Removes all characters less or equal to ' ' in S and returns it. }\r
9749 procedure Str2LowerCase( S: PChar );\r
9750 {* Converts null-terminated string to lowercase (inplace). }\r
9751 function LowerCase(const S: string): string;\r
9752 {* Obvious. }\r
9753 function UpperCase(const S: string): string;\r
9754 {* Obvious. }\r
9755 function AnsiUpperCase(const S: string): string;\r
9756 {* Obvious. }\r
9757 function AnsiLowerCase(const S: string): string;\r
9758 {* Obvious. }\r
9759 {$IFNDEF _D2}\r
9760 {$IFNDEF _FPC}\r
9761 function WAnsiUpperCase(const S: WideString): WideString;\r
9762 {* Obvious. }\r
9763 function WAnsiLowerCase(const S: WideString): WideString;\r
9764 {* Obvious. }\r
9765 {$ENDIF _FPC}\r
9766 {$ENDIF _D2}\r
9767 function AnsiCompareStr(const S1, S2: string): Integer;\r
9768 {* AnsiCompareStr compares S1 to S2, with case-sensitivity. The compare\r
9769   operation is controlled by the current Windows locale. The return value\r
9770   is the same as for CompareStr. }\r
9771 function _AnsiCompareStr(S1, S2: PChar): Integer;\r
9772 {* The same, but for PChar ANSI strings }\r
9773 function AnsiCompareStrNoCase(const S1, S2: string): Integer;\r
9774 {* AnsiCompareStr compares S1 to S2, with case-sensitivity. The compare\r
9775   operation is controlled by the current Windows locale. The return value\r
9776   is the same as for CompareStr. }\r
9777 function _AnsiCompareStrNoCase(S1, S2: PChar): Integer;\r
9778 {* The same, but for PChar ANSI strings }\r
9779 function AnsiCompareText( const S1, S2: String ): Integer;\r
9780 {* }\r
9782 {$IFNDEF _FPC}\r
9783 function LStrFromPWCharLen(Source: PWideChar; Length: Integer): String;\r
9784 {* from Delphi5 - because D2 does not contain it. }\r
9785 function LStrFromPWChar(Source: PWideChar): String;\r
9786 {* from Delphi5 - because D2 does not contain it. }\r
9787 {$ENDIF _FPC}\r
9789 function CopyEnd( const S : String; Idx : Integer ) : String;\r
9790 {* Returns copy of source string S starting from Idx up to the end of\r
9791    string S. Works correctly for case, when Idx > Length( S ) (returns\r
9792    empty string for such case). }\r
9793 function CopyTail( const S : String; Len : Integer ) : String;\r
9794 {* Returns last Len characters of the source string. If Len > Length( S ),\r
9795    entire string S is returned. }\r
9796 procedure DeleteTail( var S : String; Len : Integer );\r
9797 {* Deletes last Len characters from string. }\r
9798 function IndexOfChar( const S : String; Chr : Char ) : Integer;\r
9799 {* Returns index of given character (1..Length(S)), or\r
9800    -1 if a character not found. }\r
9801 function IndexOfCharsMin( const S, Chars : String ) : Integer;\r
9802 {* Returns index (in string S) of those character, what is taking place\r
9803    in Chars string and located nearest to start of S. If no such\r
9804    characters in string S found, -1 is returned. }\r
9805 {$IFNDEF _D2}\r
9806 {$IFNDEF _FPC}\r
9807 function IndexOfWideCharsMin( const S, Chars : WideString ) : Integer;\r
9808 {* Returns index (in wide string S) of those wide character, what\r
9809    is taking place in Chars wide string and located nearest to start of S.\r
9810    If no such characters in string S found, -1 is returned. }\r
9811 {$ENDIF _FPC}\r
9812 {$ENDIF _D2}\r
9814 function IndexOfStr( const S, Sub : String ) : Integer;\r
9815 {* Returns index of given substring in source string S. If found,\r
9816    1..Length(S)-Length(Sub), if not found, -1. }\r
9817 function Parse( var S : String; const Separators : String ) : String;\r
9818 {* Returns first characters of string S, separated from others by\r
9819    one of characters, taking place in Separators string, assigning\r
9820    a tail of string (after found separator) to source string. If\r
9821    no separator characters found, source string S is returned, and\r
9822    source string itself becomes empty. }\r
9823 {$IFNDEF _FPC}\r
9824 {$IFNDEF _D2}\r
9825 function WParse( var S : WideString; const Separators : WideString ) : WideString;\r
9826 {* Returns first wide characters of wide string S, separated from others\r
9827    by one of wide characters, taking place in Separators wide string,\r
9828    assigning a tail of wide string (following found separator) to the\r
9829    source one. If there are no separator characters found, source wide\r
9830    string S is returned, and source wide string itself becomes empty. }\r
9831 {$ENDIF _D2}\r
9832 {$ENDIF _FPC}\r
9833 function ParsePascalString( var S : String; const Separators : String ) : String;\r
9834 {* Returns first characters of string S, separated from others by\r
9835    one of characters, taking place in Separators string, assigning\r
9836    a tail of string (after the found separator) to source string. If\r
9837    there are no separator characters found, the source string S is returned,\r
9838    and the source string itself becomes empty. Additionally: if the first (after\r
9839    a blank space) is the quote "'" or '#', pascal string is assumung first\r
9840    and is converted to usual string (without quotas) before analizing\r
9841    of other separators. }\r
9842 function String2PascalStrExpr( const S : String ) : String;\r
9843 {* Converts string to Pascal-like string expression (concatenation of\r
9844    strings with quotas and characters with leading '#'). }\r
9845 function StrEq( const S1, S2 : String ) : Boolean;\r
9846 {* Returns True, if LowerCase(S1) = LowerCase(S2). I.e., if strings\r
9847    are equal to each other without caring of characters case sensitivity\r
9848    (ASCII only). }\r
9849 function AnsiEq( const S1, S2 : String ) : Boolean;\r
9850 {* Returns True, if AnsiLowerCase(S1) = AnsiLowerCase(S2). I.e., if ANSI\r
9851    stringsare equal to each other without caring of characters case\r
9852    sensitivity. }\r
9853 {$IFNDEF _D2}\r
9854 {$IFNDEF _FPC}\r
9855 function WAnsiEq( const S1, S2 : WideString ) : Boolean;\r
9856 {* Returns True, if AnsiLowerCase(S1) = AnsiLowerCase(S2). I.e., if ANSI\r
9857    stringsare equal to each other without caring of characters case\r
9858    sensitivity. }\r
9859 {$ENDIF _FPC}\r
9860 {$ENDIF _D2}\r
9862 function StrIn( const S : String; const A : array of String ) : Boolean;\r
9863 {* Returns True, if S is "equal" to one of strings, taking place\r
9864    in A array. To check equality, StrEq function is used, i.e.\r
9865    comaprison is taking place without case sensitivity. }\r
9866 {$IFNDEF _FPC}\r
9867 {$IFNDEF _D2}\r
9868 function WStrIn( const S : WideString; const A : array of WideString ) : Boolean;\r
9869 {* Returns True, if S is "equal" to one of strings, taking place\r
9870    in A array. To check equality, WAnsiEq function is used, i.e.\r
9871    comaprison is taking place without case sensitivity. }\r
9872 {$ENDIF _D2}\r
9873 {$ENDIF _FPC}\r
9874 function StrIs( const S : String; const A : array of String; var Idx: Integer ) : Boolean;\r
9875 {* Returns True, if S is "equal" to one of strings, taking place\r
9876    in A array, and in such Case Idx also is assigned to an index of A element\r
9877    equal to S. To check equality, StrEq function is used, i.e.\r
9878    comaprison is taking place without case sensitivity. }\r
9879 function IntIn( Value: Integer; const List: array of Integer ): Boolean;\r
9880 {* Returns TRUE, if Value is found in a List. }\r
9881 function _StrSatisfy( S, Mask : PChar ) : Boolean;\r
9882 {* }\r
9883 function _2StrSatisfy( S, Mask: PChar ): Boolean;\r
9884 {* }\r
9885 function StrSatisfy( const S, Mask : String ) : Boolean;\r
9886 {* Returns True, if S is satisfying to a given Mask (which can contain\r
9887    wildcard symbols '*' and '?' interpeted correspondently as 'any\r
9888    set of characters' and 'single any character'. If there are no\r
9889    such wildcard symbols in a Mask, result is True only if S is maching\r
9890    to Mask string.) }\r
9891 function StrReplace( var S: String; const From, ReplTo: String ): Boolean;\r
9892 {* Replaces first occurance of From to ReplTo in S, returns True,\r
9893    if pattern From was found and replaced. }\r
9894 {$IFNDEF _FPC}\r
9895 {$IFNDEF _D2}\r
9896 function WStrReplace( var S: WideString; const From, ReplTo: WideString ): Boolean;\r
9897 {* Replaces first occurance of From to ReplTo in S, returns True,\r
9898    if pattern From was found and replaced. See also function StrReplace.\r
9899    This function is not available in Delphi2 (this version of Delphi\r
9900    does not support WideString type). }\r
9901 {$ENDIF _D2}\r
9902 {$ENDIF _FPC}\r
9904 function StrRepeat( const S: String; Count: Integer ): String;\r
9905 {* Repeats given string Count times. E.g., StrRepeat( 'A', 5 ) gives 'AAAAA'. }\r
9906 {$IFNDEF _FPC}\r
9907 {$IFNDEF _D2}\r
9908 function WStrRepeat( const S: WideString; Count: Integer ): WideString;\r
9909 {* Repeats given wide string Count times. E.g., StrRepeat( 'A', 5 ) gives 'AAAAA'. }\r
9910 {$ENDIF _D2}\r
9911 {$ENDIF _FPC}\r
9913 procedure NormalizeUnixText( var S: String );\r
9914 {* In the string S, replaces all occurances of character #10 (without leading #13)\r
9915    to the character #13. }\r
9917 {$IFNDEF _FPC}\r
9918 function WStrLen( W: PWideChar ): Integer;\r
9919 {* Returns Length of null-terminated Unicode string. }\r
9920 procedure WStrCopy( Dest, Src: PWideChar );\r
9921 {* Copies null-terminated Unicode string (terminated null also copied). }\r
9922 function WStrCmp( W1, W2: PWideChar ): Integer;\r
9923 {* Compares two null-terminated Unicode strings. }\r
9924 {$ENDIF _FPC}\r
9926 function StrPCopy(Dest: PChar; const Source: string): PChar;\r
9927 {* Copyes Pascal-style string into null-terminaed one. }\r
9928 function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar;\r
9929 {* Copyes first MaxLen characters of Pascal-style string into\r
9930    null-terminated one. }\r
9932 function DelimiterLast( const Str, Delimiters: String ): Integer;\r
9933 {* Returns index of the last of delimiters given by same named parameter\r
9934    among characters of Str. If there are no delimiters found, length of\r
9935    Str is returned. This function is intended mainly to use in filename\r
9936    parsing functions. }\r
9937 function __DelimiterLast( Str, Delimiters: PChar ): PChar;\r
9938 {* Returns address of the last of delimiters given by Delimiters parameter\r
9939    among characters of Str. If there are no delimeters found, position of\r
9940    the null terminator in Str is returned. This function is intended\r
9941    mainly to use in filename parsing functions. }\r
9942 function SkipSpaces( P: PChar ): PChar;\r
9943 {* Skips all characters #1..' ' in a string.\r
9945 {$IFDEF F_P}\r
9946 function DummyStrFun( const S: String ): String;\r
9947 {$ENDIF}\r
9950 //[Memory FUNCTIONS DECLARATIONS]\r
9951 function CompareMem(P1, P2: Pointer; Length: Integer): Boolean;\r
9952 {* Fast compare of two memory blocks. }\r
9953 function AllocMem( Size : Integer ) : Pointer;\r
9954 {* Allocates global memory and unlocks it. }\r
9955 procedure DisposeMem( var Addr : Pointer );\r
9956 {* Locks global memory block given by pointer, and frees it.\r
9957    Does nothing, if the pointer is nil.\r
9958    |<hr>\r
9960   <R Text in clipboard operations>\r
9963 //[clipboard FUNCTIONS DECLARATIONS]\r
9964 function Clipboard2Text: String;\r
9965 {* If clipboard contains text, this function returns it for You. }\r
9966 {$IFNDEF _FPC}\r
9967 {$IFNDEF _D2}\r
9968 function Clipboard2WText: WideString;\r
9969 {* If clipboard contains text, this function returns it for You (as Unicode string). }\r
9970 {$ENDIF _D2}\r
9971 {$ENDIF _FPC}\r
9972 function Text2Clipboard( const S: String ): Boolean;\r
9973 {* Puts given string to a clipboard. }\r
9974 {$IFNDEF _FPC}\r
9975 {$IFNDEF _D2}\r
9976 function WText2Clipboard( const WS: WideString ): Boolean;\r
9977 {* Puts given Unicode string to a clipboard.\r
9978 |<hr>\r
9980 {$ENDIF _D2}\r
9981 {$ENDIF _FPC}\r
9985 //[Mnemonics FUNCTIONS DECLARATIONS]\r
9986 var SearchMnemonics: function ( const S: String ): String\r
9987     = {$IFDEF F_P} DummyStrFun {$ELSE} UpperCase {$ENDIF};\r
9988     MnemonicsLocale: Integer;\r
9990 procedure SupportAnsiMnemonics( LocaleID: Integer );\r
9991 {* Provides encoding to work with given locale. Call this global function to\r
9992    extend TControl.SupportMnemonics capability (also should be called for a form\r
9993    or for Applet variable).\r
9999    <R Date and time handling>\r
10001 //[TDateTime TYPE DEFINITION]\r
10002 type\r
10003   //TDateTime = Double; // well, it is already defined so in System.pas\r
10004   {* Basic date and time type. Integer part represents year and days (as is,\r
10005      i.e. 1-Jan-2000 is representing by value 730141, which is a number of\r
10006      days from 1-Jan-0001 to 1-Jan-2000 inclusively). Fractional part is\r
10007      representing hours, minutes, seconds and milliseconds of a day\r
10008      proportionally (like in VCL TDateTime type, e.g. 0.5 = 12:00, 0.25 = 6:00,\r
10009      etc.). }\r
10011   PDayTable = ^TDayTable;\r
10012   TDayTable = array[1..12] of Word;\r
10014   TDateFormat = ( dfShortDate, dfLongDate );\r
10015   {* Date formats available to use in formatting date/time to string. }\r
10016   TTimeFormatFlag = ( tffNoMinutes, tffNoSeconds, tffNoMarker, tffForce24 );\r
10017   {* Additional flags, used for formatting time. }\r
10018   TTimeFormatFlags = Set of TTimeFormatFlag;\r
10019   {* Set of flags, used for formatting time. }\r
10021 const\r
10022   MonthDays: array [Boolean] of TDayTable =\r
10023     ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),\r
10024      (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));\r
10025   {* The MonthDays array can be used to quickly find the number of\r
10026     days in a month:  MonthDays[IsLeapYear(Y), M].      }\r
10028   SecsPerDay = 24 * 60 * 60;\r
10029   {* Seconds per day. }\r
10030   MSecsPerDay = SecsPerDay * 1000;\r
10031   {* Milliseconds per day. }\r
10033   VCLDate0 = 693594;\r
10034   {* Value to convert VCL "date 0" to KOL "date 0" and back.\r
10035      This value corresponds to 30-Dec-1899, 0:00:00. So,\r
10036      to convert VCL date to KOL date, just subtract this\r
10037      value from VCL date. And to convert back from KOL date\r
10038      to VCL date, add this value to KOL date.}\r
10040 {++}(*\r
10041 procedure GetLocalTime(var lpSystemTime: TSystemTime); stdcall;\r
10042 procedure GetSystemTime(var lpSystemTime: TSystemTime); stdcall;\r
10043 *){--}\r
10045 //[Date&Time FUNCTIONS DECLARATIONS]\r
10046 function Now : TDateTime;\r
10047 {* Returns local date and time on running PC. }\r
10048 function Date: TDateTime;\r
10049 {* Returns todaylocal date. }\r
10050 procedure DecodeDateFully( DateTime: TDateTime; var Year, Month, Day, DayOfWeek: WORD );\r
10051 {* Decodes date. }\r
10052 procedure DecodeDate( DateTime: TDateTime; var Year, Month, Day: WORD );\r
10053 {* Decodes date. }\r
10054 function EncodeDate( Year, Month, Day: WORD; var DateTime: TDateTime ): Boolean;\r
10055 {* Encodes date. }\r
10056 function CompareSystemTime(const D1, D2 : TSystemTime) : Integer;\r
10057 {* Compares to TSystemTime records. Returns -1, 0, or 1 if, correspondantly,\r
10058    D1 < D2, D1 = D2 and D1 > D2. }\r
10059 procedure IncDays( var SystemTime : TSystemTime; DaysNum : Integer );\r
10060 {* Increases/decreases day in TSystemTime record onto given days count\r
10061    (can be negative). }\r
10062 procedure IncMonths( var SystemTime : TSystemTime; MonthsNum : Integer );\r
10063 {* Increases/decreases month number in TSystemTime record onto given\r
10064    months count (can be negative). Correct result is not garantee if\r
10065    day number is incorrect for newly obtained month. }\r
10066 function IsLeapYear(Year: Word): Boolean;\r
10067 {* Returns True, if given year is "leap" (i.e. has 29 days in the February). }\r
10068 function DayOfWeek(Date: TDateTime): Integer;\r
10069 {* Returns day of week (0..6) for given date. }\r
10070 function SystemTime2DateTime(const SystemTime : TSystemTime; var DateTime : TDateTime ) : Boolean;\r
10071 {* Converts TSystemTime record to XDateTime variable. }\r
10072 function DateTime2SystemTime(const DateTime : TDateTime; var SystemTime : TSystemTime ) : Boolean;\r
10073 {* Converts TDateTime variable to TSystemTime record. }\r
10074 function DateTime_System2Local( DTSys: TDateTime ): TDateTime;\r
10075 {* Converts DTSys representing system time (+0 Grinvich) to local time. }\r
10076 function DateTime_Local2System( DTLoc: TDateTime ): TDateTime;\r
10077 {* Converts DTLoc representing local time to system time (+0 Grinvich) }\r
10078 function CatholicEaster( nYear: Integer ): TDateTime;\r
10079 {* Returns date of catholic easter for given year. }\r
10081 procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);\r
10082 {* Dividing of integer onto divisor with obtaining both result of division\r
10083    and remainder. }\r
10085 function SystemDate2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;\r
10086                          const DfltDateFormat : TDateFormat; const DateFormat : PChar ) : String;\r
10087 {* Formats date, stored in TSystemTime record into string, using given locale\r
10088    and date/time formatting flags. }\r
10089 function SystemTime2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;\r
10090                          const Flags : TTimeFormatFlags; const TimeFormat : PChar ) : String;\r
10091 {* Formats time, stored in TSystemTime record into string, using given locale\r
10092    and date/time formatting flags. }\r
10094 function Date2StrFmt( const Fmt: String; D: TDateTime ): String;\r
10095 {* Represents date as a string correspondently to Fmt formatting string.\r
10096    See possible pictures in definition of the function Str2DateTimeFmt\r
10097    (the first part). If Fmt string is empty, default system date format\r
10098    for short date string used. }\r
10099 function Time2StrFmt( const Fmt: String; D: TDateTime ): String;\r
10100 {* Represents time as a string correspondently to Fmt formatting string.\r
10101    See possible pictures in definition of the function Str2DateTimeFmt\r
10102    (the second part). If Fmt string is empty, default system time format\r
10103    for short date string used. }\r
10104 function DateTime2StrShort( D: TDateTime ): String;\r
10105 {* Formats date and time to string in short date format using current user\r
10106    locale. }\r
10107 function Str2DateTimeFmt( const sFmtStr, sS: String ): TDateTime;\r
10108 {* Restores date or/and time from string correspondently to a format string.\r
10109    Date and time formatting string can contain following pictures (case\r
10110    sensitive):\r
10111    |<pre>\r
10112         DATE PICTURES\r
10113    d    Day of the month as digits without leading zeros for single digit days.\r
10114    dd   Day of the month as digits with leading zeros for single digit days\r
10115    ddd  Day of the week as a 3-letter abbreviation as specified by a\r
10116         LOCALE_SABBREVDAYNAME value.\r
10117    dddd Day of the week as specified by a LOCALE_SDAYNAME value.\r
10118    M    Month as digits without leading zeros for single digit months.\r
10119    MM   Month as digits with leading zeros for single digit months\r
10120    MMM  Month as a three letter abbreviation as specified by a LOCALE_SABBREVMONTHNAME value.\r
10121    MMMM Month as specified by a LOCALE_SMONTHNAME value.\r
10122    y    Year represented only be the last digit.\r
10123    yy   Year represented only be the last two digits.\r
10124    yyyy Year represented by the full 4 digits.\r
10125    gg   Period/era string as specified by the CAL_SERASTRING value. The gg\r
10126         format picture in a date string is ignored if there is no associated era\r
10127         string. In Enlish locales, usual values are BC or AD.\r
10129         TIME PICTURES\r
10130    h    Hours without leading zeros for single-digit hours (12-hour clock).\r
10131    hh   Hours with leading zeros for single-digit hours (12-hour clock).\r
10132    H    Hours without leading zeros for single-digit hours (24-hour clock).\r
10133    HH   Hours with leading zeros for single-digit hours (24-hour clock).\r
10134    m    Minutes without leading zeros for single-digit minutes.\r
10135    mm   Minutes with leading zeros for single-digit minutes.\r
10136    s    Seconds without leading zeros for single-digit seconds.\r
10137    ss   Seconds with leading zeros for single-digit seconds.\r
10138    t    One character–time marker string (usually P or A, in English locales).\r
10139    tt   Multicharacter–time marker string (usually PM or AM, in English locales).\r
10140    |</pre>\r
10141    E.g., 'D, yyyy/MM/dd h:mm:ss'.\r
10142    See also Str2DateTimeShort function.\r
10143   }\r
10144 function Str2DateTimeShort( const S: String ): TDateTime;\r
10145 {* Restores date and time from string correspondently to current user locale. }\r
10146 function Str2DateTimeShortEx( const S: String ): TDateTime;\r
10147 {* Like Str2DateTimeShort above, but uses locale defined date and time\r
10148    separators to avoid recognizing time as a date in some cases.\r
10149 |<hr>\r
10152   <R File and directory routines>\r
10155 //[OpenFile CONSTANTS]\r
10156 const\r
10157   ofOpenRead          = $80000000;\r
10158   {* Use this flag (in combination with others) to open file for "read" only. }\r
10159   ofOpenWrite         = $40000000;\r
10160   {* Use this flag (in combination with others) to open file for "write" only. }\r
10161   ofOpenReadWrite     = $C0000000;\r
10162   {* Use this flag (in combination with others) to open file for "read" and "write". }\r
10163   ofShareExclusive    = $00;\r
10164   {* Use this flag (in combination with others) to open file for exclusive use. }\r
10165   ofShareDenyWrite    = $01;\r
10166   {* Use this flag (in combination with others) to open file in share mode, when\r
10167      only attempts to open it in other process for "write" will be impossible.\r
10168      I.e., other processes could open this file simultaneously for read only\r
10169      access. }\r
10170   ofShareDenyRead     = $02;\r
10171   {* Use this flag (in combination with others) to open file in share mode, when\r
10172      only attempts to open it for "read" in other processes will be disabled.\r
10173      I.e., other processes could open it for "write" only access. }\r
10174   ofShareDenyNone     = $03;\r
10175   {* Use this flag (in combination with others) to open file in full sharing mode.\r
10176      I.e. any process will be able open this file using the same share flag. }\r
10177   ofCreateNew         = $100;\r
10178   {* Default creation disposition. Use this flag for creating new file (usually\r
10179      for write access. }\r
10180   ofCreateAlways      = $200;\r
10181   {* Use this flag (in combination with others) to open existing or creating new\r
10182      file. If existing file is opened, it is truncated to size 0. }\r
10183   ofOpenExisting      = $300;\r
10184   {* Use this flag (in combination with others) to open existing file only. }\r
10185   ofOpenAlways        = $400;\r
10186   {* Use this flag (in combination with others) to open existing or create new\r
10187      (if such file is not yet exists). }\r
10188   ofTruncateExisting  = $500;\r
10189   {* Use this flag (in combination with others) to open existing file and truncate\r
10190      it to size 0. }\r
10192   ofAttrReadOnly = $10000;\r
10193   {* Use this flag to create Read-Only file (?). }\r
10194   ofAttrHidden   = $20000;\r
10195   {* Use this flag to create hidden file. }\r
10196   ofAttrSystem   = $40000;\r
10197   {* Use this flag to create system file. }\r
10198   ofAttrTemp       = $1000000;\r
10199   {* Use this flag to create temp file. }\r
10200   ofAttrArchive  = $200000;\r
10201   {* Use this flag to create archive file. }\r
10202   ofAttrCompressed = $8000000;\r
10203   {* Use this flag to create compressed file. Has effect only on NTFS, and\r
10204      only if ofAttrCompressed is not specified also. }\r
10205   ofAttrOffline    = $10000000;\r
10206   {* Use this flag to create offline file. }\r
10207 //[END OF OpenFileConstants]\r
10209 //[File FUNCTIONS DECLARATIONS]\r
10210 function FileCreate(const FileName: string; OpenFlags: DWord): THandle;\r
10211 {* Call this function to open existing or create new file. OpenFlags\r
10212    parameter can be a combination of up to three flags (by one from\r
10213    each group:\r
10214    |<table border=0>\r
10215    |&L=<tr><td valign=top>%0</td><td valign=top>\r
10216    |&E=</td></tr>\r
10217    <L ofOpenRead, ofOpenWrite, ofOpenReadWrite> - 1st group. Here You decide\r
10218       wish You open file for read, write or read-and-write operations; <E>\r
10219    <L ofShareExclusive, ofShareDenyWrite, ofShareDenyRead, ofShareDenyNone> -2nd\r
10220       group - sharing. Here You can mark out sharing mode, which is used to\r
10221       open file. <E>\r
10222    <L ofCreateNew, ofCreateAlways, ofOpenExisting, ofOpenAlways, ofTruncateExisting>\r
10223       - 3rd group - creation disposition. Here You determine, either to create new\r
10224       or open existing file and if to truncate existing or not.\r
10225    |</table> }\r
10226 function FileClose(Handle: THandle): Boolean;\r
10227 {* Call it to close opened earlier file. }\r
10228 function FileExists( const FileName: String ) : Boolean;\r
10229 {* Returns True, if given file exists.\r
10230    |<br>Note (by Dod):\r
10231    It is not documented in a help for GetFileAttributes, but it seems that\r
10232    under NT-based Windows systems, FALSE is always returned for files\r
10233    opened for excluseve use like pagefile.sys. }\r
10234 function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;\r
10235 {* Reads bytes from current position in file to buffer. Returns number of\r
10236    read bytes. }\r
10237 function File2Str(Handle: THandle): String;\r
10238 {* Reads file from current position to the end and returns result as ansi string. }\r
10240 function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;\r
10241 {* Changes current position in file. }\r
10242 function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;\r
10243 {* Writes bytes from buffer to file from current position, extending its\r
10244    size if needed. }\r
10245 function FileEOF( Handle: THandle ) : Boolean;\r
10246 {* Returns True, if EOF is achieved during read operations or last byte is\r
10247    overwritten or append made to extend file during last write operation. }\r
10248 function FileFullPath( const FileName : String ) : String;\r
10249 {* Returns full path name for given file. Validness of source FileName path\r
10250    is not checked at all. }\r
10251 function FileShortPath( const FileName: String ): String;\r
10252 {* Returns short path to the file or directory. }\r
10253 function FileIconSystemIdx( const Path: String ): Integer;\r
10254 {* Returns index of the index of the system icon correspondent to the file or\r
10255    directory in system icon image list. }\r
10256 function FileIconSysIdxOffline( const Path: String ): Integer;\r
10257 {* The same as FileIconSystemIdx, but an icon is calculated for the file\r
10258    as it were offline (it is possible to get an icon for file even if\r
10259    it is not existing, on base of its extension only). }\r
10260 procedure LogFileOutput( const filepath, str: String );\r
10261 {* Debug function. Use it to append given string to the end of the given file. }\r
10263 function StrSaveToFile( const Filename, Str: String ): Boolean;\r
10264 {* Saves a string to a file without any changes. If file does not exists, it is\r
10265    created. If it exists, it is overriden. If operation failed, FALSE is returned. }\r
10266 function StrLoadFromFile( const Filename: String ): String;\r
10267 {* Reads entire file and returns its content as a string. If operation failed,\r
10268    an empty strinng is returned. }\r
10270 function Mem2File( Filename: PChar; Mem: Pointer; Len: Integer ): Integer;\r
10271 {* Saves memory block to a file (if file exists it is overriden, created new if\r
10272    not exists). }\r
10273 function File2Mem( Filename: PChar; Mem: Pointer; MaxLen: Integer ): Integer;\r
10274 {* Loads file content to memory. }\r
10276 function FileSize( const Path: String ) : Integer;\r
10277 {* Returns file size in bytes without opening it. If file too large\r
10278    to represent its size as Integer, -1 is returned. }\r
10279 function GetUniqueFilename( PathName: string ) : String;\r
10280 {* If file given by PathName exists, modifies it to create unique\r
10281    filename in target folder and returns it. Modification is performed\r
10282    by incrementing last number in name (if name part of file does not\r
10283    represent a number, such number is generated and concatenated to\r
10284    it). E.g., if file aaa.aaa is already exist, the function checks\r
10285    names aaa1.aaa, aaa2.aaa, ..., aaa10.aaa, etc. For name abc123.ext,\r
10286    names abc124.ext, abc125.ext, etc. will be checked. }\r
10288 function FileTimeCompare( const FT1, FT2 : TFileTime ) : Integer;\r
10289 {* Compares time of file (createing, writing, accessing. Returns\r
10290    -1, 0, 1 if correspondantly FT1<FT2, FT1=FT2, FT1>FT2. }\r
10292 //[Directory FUNCTIONS DECLARATIONS]\r
10293 function GetStartDir: String;\r
10294 {* Returns path to directory where executable is located (regardless\r
10295    of current directory). }\r
10296 function DirectoryExists(const Name: string): Boolean;\r
10297 {* Returns True if given directory (folder) exists. }\r
10298 function DirectoryEmpty(const Name: String): Boolean;\r
10299 {* Returns True if given directory is not exists or empty. }\r
10301 function DirectorySize( const Path: String ): I64;\r
10302 -- moved after PDirList\r
10304 function DirectoryHasSubdirs( const Path: String ): Boolean;\r
10305 {* Returns TRUE if given directory exists and has subdirectories. }\r
10306 function CheckDirectoryContent( const Name: String; SubDirsOnly: Boolean; const Mask: String ): Boolean;\r
10307 {* Returns TRUE if directory does not contain files (or directories only)\r
10308    satisfying given mask. }\r
10310 //---------------------------------------------------------\r
10311 // Following functions/procedures are created by Edward Aretino:\r
10312 // IncludeTrailingPathDelimiter, ExcludeTrailingPathDelimiter,\r
10313 // ForceDirectories, CreateDir, ChangeFileExt\r
10314 //---------------------------------------------------------\r
10315 function IncludeTrailingPathDelimiter(const S: string): string;\r
10316 {* by Edward Aretino. Adds '\' to the end if it is not present. }\r
10317 function ExcludeTrailingPathDelimiter(const S: string): string;\r
10318 {* by Edward Aretino. Removes '\' at the end if it is present. }\r
10319 function ForceDirectories(Dir: String): Boolean;\r
10320 {* by Edward Aretino. Creates given directory if not present. All needed\r
10321    subdirectories are created if necessary. }\r
10322 function CreateDir(const Dir: string): Boolean;\r
10323 {* by Edward Aretino. Creates given directory. }\r
10324 function ChangeFileExt(FileName: String; const Extension: string): string;\r
10325 {* by Edward Aretino. Changes file extention. }\r
10327 function ExcludeTrailingChar( const S: String; C: Char ): String;\r
10328 {* If S is finished with character C, it is excluded. }\r
10329 function IncludeTrailingChar( const S: String; C: Char ): String;\r
10330 {* If S is not finished with character C, it is added. }\r
10332 function ExtractFilePath( const Path: String ) : String;\r
10333 {* Returns only path part from exact path to file. }\r
10334 function ExtractFileName( const Path: String ) : String;\r
10335 {* Extracts file name from exact path to file. }\r
10336 function ExtractFileNameWOext( const Path: String ) : String;\r
10337 {* Extracts file name from path to file or from filename. }\r
10338 function ExtractFileExt( const Path: String ) : String;\r
10339 {* Extracts extention from file name (returns it with dot '.' first) }\r
10340 function ReplaceFileExt( const Path, NewExt: String ): String;\r
10341 {* Returns a path with extension replaced to a given one. }\r
10342 function ExtractShortPathName( const Path: String ): String;\r
10343 {* }\r
10344 function FilePathShortened( const Path: String; MaxLen: Integer ): String;\r
10345 {* Returns shortened file path to fit MaxLen characters. }\r
10346 function FilePathShortenPixels( const Path: String; DC: HDC; MaxPixels: Integer ): String;\r
10347 {* Returns shortened file path to fit MaxPixels for a given DC. If you pass\r
10348    Canvas.Handle of any control or bitmap object, ensure that font is valid\r
10349    for it (or call TCanvas.RequiredState( FontValid ) method before. If DC passed\r
10350    = 0, call is equivalent to call FilePathShortened, and MaxPixels means in such\r
10351    case maximum number of characters. }\r
10352 function MinimizeName( const Path: String; DC: HDC; MaxPixels: Integer ): String;\r
10353 {* Exactly the same as MinimizeName in FileCtrl.pas (VCL). }\r
10355 function GetSystemDir: String;\r
10356 {* Returns path to windows system directory. }\r
10357 function GetWindowsDir : string;\r
10358 {* Returns path to Windows directory. }\r
10359 function GetWorkDir : string;\r
10360 {* Returns path to application's working directory. }\r
10361 function GetTempDir : string;\r
10362 {* Returns path to default temp folder (directory to place temporary files). }\r
10363 function CreateTempFile( const DirPath, Prefix: String ): String;\r
10364 {* Returns path to just created temporary file. }\r
10365 function  GetFileListStr(FPath{e.g.'c:\tmp\'}, FMask{e.g.'*.*'}: string): string;\r
10366 {* List of files in string, separating each path from others with semicolon (';').\r
10367    E.g.: 'c:\tmp\unit1.dcu;c:\tmp\unit1.~pa' (for use with DeleteFile2Recycle())}\r
10368 function DeleteFiles( const DirPath: String ): Boolean;\r
10369 {* Deletes files by file mask (given with wildcards '*' and '?'). }\r
10370 function DeleteFile2Recycle( const Filename : String ) : Boolean;\r
10371 {* Deletes file to recycle bin. This operation can be very slow, when\r
10372    called for a single file. To delete group of files at once (fast),\r
10373    pass a list of paths to files to be deleted, separating each path\r
10374    from others with semicolon (';'). E.g.: 'unit1.dcu;unit1.~pa'\r
10375    |<br>\r
10376    FALSE is returned only in case when at least one file was not deleted\r
10377    successfully.\r
10378    |<br>\r
10379    Note, that files are deleted not to recycle bin, if wildcards are\r
10380    used or not fully qualified paths to files. }\r
10381 function CopyMoveFiles( const FromList, ToList: String; Move: Boolean ): Boolean;\r
10382 {* }\r
10383 {-}\r
10384 function DiskFreeSpace( const Path: String ): I64; {+}\r
10385 {* Returns disk free space in bytes. Pass a path to root directory,\r
10386    e.g. 'C:\'.\r
10387 |<hr>\r
10398   <R Wrappers to registry API functions>\r
10400   These functions can be used independently to simplify access to Windows\r
10401   registry. }\r
10403 //[Registry FUNCTIONS DECLARATIONS]\r
10404 {++}(*\r
10405 function RegSetValueEx(hKey: HKEY; lpValueName: PChar;\r
10406   Reserved: DWORD; dwType: DWORD; lpData: Pointer; cbData: DWORD): Longint; stdcall;\r
10407 *){--}\r
10408 function RegKeyOpenRead( Key: HKey; const SubKey: String ): HKey;\r
10409 {* Opens registry key for read operations (including enumerating of subkeys).\r
10410    Pass either handle of opened earlier key or one of constans\r
10411    HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS\r
10412    as a first parameter. If not successful, 0 is returned. }\r
10413 function RegKeyOpenWrite( Key: HKey; const SubKey: String ): HKey;\r
10414 {* Opens registry key for write operations (including adding new values or\r
10415    subkeys), as well as for read operations too. See also RegKeyOpenRead. }\r
10416 function RegKeyOpenCreate( Key: HKey; const SubKey: String ): HKey;\r
10417 {* Creates and opens key. }\r
10418 function RegKeyGetStr( Key: HKey; const ValueName: String ): String;\r
10419 {* Reads key, which must have type REG_SZ (null-terminated string). If\r
10420    not successful, empty string is returned. This function as well as all\r
10421    other registry manipulation functions, does nothing, if Key passed is 0\r
10422    (without producing any error). }\r
10423 function RegKeyGetStrEx( Key: HKey; const ValueName: String ): String;\r
10424 {* Like RegKeyGetStr, but accepts REG_EXPAND_SZ type, expanding all\r
10425    environment variables in resulting string.\r
10426    |<br>\r
10427    Code provided by neuron, e-mailto:neuron@hollowtube.mine.nu }\r
10428 function RegKeyGetDw( Key: HKey; const ValueName: String ): DWORD;\r
10429 {* Reads key value, which must have type REG_DWORD. If ValueName passed\r
10430    is '' (empty string), unnamed (default) value is reading. If not\r
10431    successful, 0 is returned. }\r
10432 function RegKeySetStr(Key: HKey; const ValueName: String; const Value: String ): Boolean;\r
10433 {* Writes new key value as null-terminated string (type REG_SZ). If not\r
10434    successful, returns False. }\r
10435 function RegKeySetStrEx( Key: HKey; const ValueName: string; const Value: string;\r
10436                          expand: boolean): Boolean;\r
10437 {* Writes new key value as REG_SZ or REG_EXPAND_SZ. - by neuron, e-mailto:neuron@hollowtube.mine.nu }\r
10438 function RegKeySetDw( Key: HKey; const ValueName: String; Value: DWORD ): Boolean;\r
10439 {* Writes new key value as dword (with type REG_DWORD). Returns False,\r
10440    if not successful. }\r
10441 procedure RegKeyClose( Key: HKey );\r
10442 {* Closes key, opened using RegKeyOpenRead or RegKeyOpenWrite. (But does\r
10443    nothing, if Key passed is 0). }\r
10444 function RegKeyDelete( Key: HKey; const SubKey: String ): Boolean;\r
10445 {* Deletes key. Does nothing if key passed is 0 (returns FALSE). }\r
10446 function RegKeyDeleteValue( Key: HKey; const SubKey: String ): Boolean;\r
10447 {* Deletes value. - by neuron, e-mailto:neuron@hollowtube.mine.nu }\r
10448 function RegKeyExists( Key: HKey; const SubKey: String ): Boolean;\r
10449 {* Returns TRUE, if given subkey exists under given Key. }\r
10450 function RegKeyValExists( Key: HKey; const ValueName: String ): Boolean;\r
10451 {* Returns TRUE, if given value exists under the Key.\r
10453 function RegKeyValueSize( Key: HKey; const ValueName: String ): Integer;\r
10454 {* Returns a size of value. This is a size of buffer needed to store\r
10455    registry key value. For string value, size returned is equal to a\r
10456    length of string plus 1 for terminated null character. }\r
10457 function RegKeyGetBinary( Key: HKey; const ValueName: String; var Buffer; Count: Integer ): Integer;\r
10458 {* Reads binary data from a registry, writing it to the Buffer.\r
10459    It is supposed that size of Buffer provided is at least Count bytes.\r
10460    Returned value is actul count of bytes read from the registry and written\r
10461    to the Buffer.\r
10462    |<br>\r
10463    This function can be used to get data of any type from the registry, not\r
10464    only REG_BINARY. }\r
10465 function RegKeySetBinary( Key: HKey; const ValueName: String; const Buffer; Count: Integer ): Boolean;\r
10466 {* Stores binary data in the registry. }\r
10467 function RegKeyGetDateTime(Key: HKey; const ValueName: String): TDateTime;\r
10468 {* Returns datetime variable stored in registry in binary format. }\r
10469 function RegKeySetDateTime(Key: HKey; const ValueName: String; DateTime: TDateTime): Boolean;\r
10470 {* Stores DateTime variable in the registry. }\r
10473 //-------------------------------------------------------\r
10474 // registry functions by Valerian Luft <luft@valerian.de>\r
10475 //-------------------------------------------------------\r
10476 function RegKeyGetSubKeys( const Key: HKEY; List: PStrList): Boolean;\r
10477 {* The function enumerates subkeys of the specified open registry key.\r
10478    True is returned, if successful.\r
10480 function RegKeyGetValueNames(const Key: HKEY; List: PStrList): Boolean;\r
10481 {* The function enumerates value names of the specified open registry key.\r
10482    True is returned, if successful.\r
10484 function RegKeyGetValueTyp (const Key:HKEY; const ValueName: String) : DWORD;\r
10485 {* The function receives the type of data stored in the specified value.\r
10486    |<br>\r
10487    If the function fails, the return value is the Key value.\r
10488    |<br>\r
10489    If the function succeeds, the return value return will be one of the following:\r
10490    |<br>\r
10491    REG_BINARY , REG_DWORD, REG_DWORD_LITTLE_ENDIAN,\r
10492    REG_DWORD_BIG_ENDIAN, REG_EXPAND_SZ, REG_LINK , REG_MULTI_SZ,\r
10493    REG_NONE, REG_RESOURCE_LIST, REG_SZ\r
10496 |<hr>\r
10516   <R Data sorting (quicksort implementation)>\r
10517   This part contains implementation of 'quick sort' algorithm,\r
10518    based on following code:\r
10520 |<pre>\r
10521 | TQSort by Mike Junkin 10/19/95.\r
10522 | DoQSort routine adapted from Peter Szymiczek's QSort procedure which\r
10523 | was presented in issue#8 of The Unofficial Delphi Newsletter.\r
10525 | TQSort changed by Vladimir Kladov (Mr.Bonanzas) to allow 32-bit\r
10526 | sorting (of big arrays with more than 64K elements).\r
10527 |</pre>\r
10529   Finally, this sort procedure is adapted to XCL (and then to KOL)\r
10530   requirements (no references to SysUtils, Classes etc. TQSort object\r
10531   is transferred to a single procedure call and DoQSort method is\r
10532   renamed to SortData - which is a regular procedure now). }\r
10534 //[Sorting TYPES]\r
10535 type\r
10536   TCompareEvent = function (const Data: Pointer; const e1,e2 : Dword) : Integer;\r
10537   {* Event type to define comparison function between two elements of an array.\r
10538      This event handler must return -1 or +1 (correspondently for cases e1<e2\r
10539      and e2>e2). Items are enumerated from 0 to uNElem. }\r
10540   TSwapEvent = procedure (const Data : Pointer; const e1,e2 : Dword);\r
10541   {* Event type to define swap procedure which is swapping two elements of an\r
10542      array. }\r
10544 //[SortData FUNCTIONS DECLARATIONS]\r
10545 procedure SortData( const Data: Pointer; const uNElem: Dword;\r
10546                     const CompareFun: TCompareEvent;\r
10547                     const SwapProc: TSwapEvent );\r
10548 {* Call it to sort any array of data of any kind, passing total\r
10549    number of items in an array and two defined (regular) function\r
10550    and procedure to perform custom compare and swap operations.\r
10551    First procedure parameter is to pass it to callback function\r
10552    CompareFun and procedure SwapProc. Items are enumerated from\r
10553    0 to uNElem-1. }\r
10555 procedure SortIntegerArray( var A : array of Integer );\r
10556 {* procedure to sort array of integers. }\r
10558 procedure SortDwordArray( var A : array of DWORD );\r
10559 {* Procedure to sort array of unsigned 32-bit integers.\r
10560 |<hr>\r
10575 { -- directory list object -- }\r
10576 //[DirList Object]\r
10578 type\r
10579   TDirItemAction = ( diSkip, diAccept, diCancel );\r
10580   TOnDirItem = procedure( Sender: PObj; var DirItem: TWin32FindData; var Accept: TDirItemAction )\r
10581              of object;\r
10582   TSortDirRules = ( sdrNone, sdrFoldersFirst, sdrCaseSensitive, sdrByName, sdrByExt,\r
10583                     sdrBySize, sdrBySizeDescending, sdrByDateCreate, sdrByDateChanged,\r
10584                     sdrByDateAccessed );\r
10585   {* List of rules (options) to sort directories. Rules are passed to Sort\r
10586      method in an array, and first placed rules are applied first. }\r
10588   {++}(*TDirList = class;*){--}\r
10589   PDirList = {-}^{+}TDirList;\r
10590 { ----------------------------------------------------------------------\r
10592                 TDirList - Directory scanning\r
10594 ----------------------------------------------------------------------- }\r
10595 //[TDirList DEFINITION]\r
10596   TDirList = object( TObj )\r
10597   {* Allows easy directory scanning. This is not visual object, but\r
10598      storage to simplify working with directory content. }\r
10599   protected\r
10600     FList : PList;\r
10601     FPath: string;\r
10602     fFilters: PStrList;\r
10603     fOnItem: TOnDirItem;\r
10604     function Get(Idx: Integer): PWin32FindData;\r
10605     function GetCount: Integer;\r
10606     function GetNames(Idx: Integer): string;\r
10607     function GetIsDirectory(Idx: Integer): Boolean;\r
10608   protected\r
10609     function SatisfyFilter( FileName : PChar; FileAttr, FindAttr : DWord ) : Boolean;\r
10610   {++}(*public*){--}\r
10611     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
10612     {* Destructor. As usual, call Free method to destroy an object. }\r
10613   public\r
10614     property Items[ Idx : Integer ] : PWin32FindData read Get; default;\r
10615     {* Full access to scanned items (files and subdirectories). }\r
10616     property IsDirectory[ Idx: Integer ]: Boolean read GetIsDirectory;\r
10617     {* Returns TRUE, if specified item represents a directory, not a file. }\r
10618     property Count : Integer read GetCount;\r
10619     {* Number of items. }\r
10620     property Names[ Idx : Integer ] : string read GetNames;\r
10621     {* Full long names of directory items. }\r
10622     property Path : string read FPath;\r
10623     {* Path of scanned directory. }\r
10624     procedure Clear;\r
10625     {* Call it to clear list of files. }\r
10626     procedure ScanDirectory( const DirPath, Filter : String; Attr : DWord );\r
10627     {* Call it to rescan directory or to scan another directory content\r
10628        (method Clear is called first). Pass path to directory, file filter\r
10629        and attributes to scan directory immediately.\r
10630        |<br>&nbsp;&nbsp;&nbsp;\r
10631        Note: Pass FILE_ATTRIBUTE_... constants or-combination as Attr\r
10632        parameter. If 0 passed, both files and directories are listed. }\r
10633     procedure ScanDirectoryEx( const DirPath, Filters : String; Attr : DWord );\r
10634     {* Call it to rescan directory or to scan another directory content\r
10635        (method Clear is called first). Pass path to directory, file filter\r
10636        and attributes to scan directory immediately.\r
10637        |<br>&nbsp;&nbsp;&nbsp;\r
10638        Note: Pass FILE_ATTRIBUTE_... constants or-combination as Attr\r
10639        parameter. }\r
10640     procedure Sort( Rules : array of TSortDirRules );\r
10641    {* Sorts directory entries. If empty rules array passed, default rules\r
10642       array DefSortDirRules is used. }\r
10643    function FileList( const Separator {e.g.: ';', or #13}: String;\r
10644             Dirs, FullPaths: Boolean ): String;\r
10645    {* Returns a string containing all names separated with Separator.\r
10646       If Dirs=FALSE, only files are returned. }\r
10647    property OnItem: TOnDirItem read fOnItem write fOnItem;\r
10648    {* This event is called on reading each item while scanning directory.\r
10649       To use it, first create PDirList object with empty path to scan, then\r
10650       assign OnItem event and call ScanDirectory with correct path. }\r
10651   end;\r
10652 //[END OF TDirList DEFINITION]\r
10654 //[NewDirList DECLARATIONS]\r
10655 function NewDirList( const DirPath, Filter: String; Attr: DWORD ): PDirList;\r
10656 {* Creates directory list object using easy one-string filter. If Attr = FILE_ATTRIBUTE_NORMAL,\r
10657    only files are scanned without directories. If Attr = 0, both files and\r
10658    directories are listed. }\r
10660 function NewDirListEx( const DirPath, Filters: String; Attr: DWORD ): PDirList;\r
10661 {* Creates directory list object using several filters, separated by ';'.\r
10662    Filters starting from '^' consider to be anti-filters, i.e. files,\r
10663    satisfying to those masks, are skept during scanning. }\r
10665 const DefSortDirRules : array[ 0..3 ] of TSortDirRules = ( sdrFoldersFirst,\r
10666       sdrByName, sdrBySize, sdrByDateCreate );\r
10667 {* Default rules to sort directory entries. }\r
10669 //[DirectorySize DECLARATION]\r
10670 {-}\r
10671 function DirectorySize( const Path: String ): I64;\r
10672 {* Returns directory size in bytes as large 64 bit integer. }\r
10673 {+}\r
10676 //[OpenSaveDialog OPTIONS]\r
10677 type\r
10678   TOpenSaveOption = ( OSCreatePrompt,\r
10679                       OSExtensionDiffent,\r
10680                       OSFileMustExist,\r
10681                       OSHideReadonly,\r
10682                       OSNoChangedir,\r
10683                       OSNoReferenceLinks,\r
10684                       OSAllowMultiSelect,\r
10685                       OSNoNetworkButton,\r
10686                       OSNoReadonlyReturn,\r
10687                       OSOverwritePrompt,\r
10688                       OSPathMustExist,\r
10689                       OSReadonly,\r
10690                       OSNoValidate\r
10691   //{$IFDEF OpenSaveDialog_Extended}\r
10692                       ,\r
10693                       OSTemplate,\r
10694                       OSHook\r
10695   //{$ENDIF}\r
10696                     );\r
10697   TOpenSaveOptions = set of TOpenSaveOption;\r
10698   {* Options available for TOpenSaveDialog. }\r
10700   {++}(*TOpenSaveDialog = class;*){--}\r
10701   POpenSaveDialog = {-}^{+}TOpenSaveDialog;\r
10702 { ----------------------------------------------------------------------\r
10704                               TOpenSaveDialog\r
10706 ----------------------------------------------------------------------- }\r
10707 //[TOpenSaveDialog DEFINITION]\r
10708   TOpenSaveDialog = object( TObj )\r
10709   {* Object to show standard Open/Save dialog. Initially provided\r
10710      for XCL by Carlo Kok. }\r
10711   protected\r
10712     FFilter : String;\r
10713     fFilterIndex : Integer;\r
10714     fOpenDialog : Boolean;\r
10715     FInitialDir : String;\r
10716     FDefExtension : String;\r
10717     FFilename : string;\r
10718     FTitle : string;\r
10719     FOptions : TOpenSaveOptions;\r
10720     fWnd: THandle;\r
10721   public\r
10722     {$IFDEF OpenSaveDialog_Extended}\r
10723     TemplateName: String;\r
10724     HookProc: Pointer;\r
10725     {$ENDIF}\r
10726     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
10727     {* destructor }\r
10728     Function Execute : Boolean;\r
10729     {* Call it after creating to perform selecting of file by user. }\r
10730     property Filename : String read FFilename write FFileName;\r
10731     {*\r
10732     Filename is seperated by #13 when multiselect is true and the first\r
10733     file, is the path of the files selected.\r
10734     |<pre>\r
10735     |  C:\Projects\r
10736     |  Test1.Dpr\r
10737     |  Test2.Dpr\r
10738     |</pre>\r
10739     If only one file is selected, it is provided as (e.g.)\r
10740     C:\Projects\Test1.dpr\r
10741     |<br> For case when OSAllowMultiselect option used, after each\r
10742     call initial value for a Filename containing several files prevents\r
10743     system from opening the dialog. To fix this, assign another initial\r
10744     value to Filename property in your code, when you use multiselect.\r
10745     }\r
10746     property InitialDir : string read FInitialDir write FInitialDir;\r
10747     {* Initial directory path. If not set, current directory (usually\r
10748        directory when program is started) is used. }\r
10749     property Filter : String read FFilter write FFilter;\r
10750     {* A list of pairs of filter names and filter masks, separated with '|'.\r
10751        If a mask contains more than one mask, it should be separated with ';'.\r
10752        E.g.:\r
10753        ! 'All files|*.*|Text files|*.txt;*.1st;*.diz' }\r
10754     property FilterIndex : Integer read FFilterIndex write FFilterIndex;\r
10755     {* Index of default filter mask (0 by default, which means "first"). }\r
10756     property OpenDialog : Boolean read FOpenDialog write FOpenDialog;\r
10757     {* True, if "Open" dialog. False, if "Save" dialog. True is default. }\r
10758     property Title : String read Ftitle write Ftitle;\r
10759     {* Title for dialog. }\r
10760     property Options : TOpenSaveOptions read FOptions write FOptions;\r
10761     {* Options. }\r
10762     property DefExtension : String read FDefExtension write FDefExtension;\r
10763     {* Default extention. Set it to desired extension without leading period,\r
10764        e.g. 'txt', but not '.txt'. }\r
10765     property WndOwner: THandle read fWnd write fWnd;\r
10766     {* Owner window handle. If not assigned, Applet.Handle is used (whenever\r
10767        possible). Assign it, if your application has stay-on-top forms, and\r
10768        a separate Applet object is used. }\r
10769   end;\r
10770 //[END OF TOpenSaveDialog DEFINITION]\r
10772 //[Default OpenSaveDialog OPTIONS]\r
10773 const DefOpenSaveDlgOptions: TOpenSaveOptions = [ OSHideReadonly,\r
10774   OSOverwritePrompt, OSFileMustExist, OSPathMustExist ];\r
10776 //[NewOpenSaveDialog DECLARATION]\r
10777 function NewOpenSaveDialog( const Title, StrtDir: String;\r
10778          Options: TOpenSaveOptions ): POpenSaveDialog;\r
10779 {* Creates object, which can be used (several times) to open file(s)\r
10780    selecting dialog. }\r
10784 //[OpenDirectory Object]\r
10785 type\r
10786   {++}(*TOpenDirDialog = class;*){--}\r
10787   POpenDirDialog = {-}^{+}TOpenDirDialog;\r
10789   TOpenDirOption = ( odBrowseForComputer, odBrowseForPrinter, odDontGoBelowDomain,\r
10790                    odOnlyFileSystemAncestors, odOnlySystemDirs, odStatusText,\r
10791                    odBrowseIncludeFiles );\r
10792   {* Flags available for TOpenDirDialog object. }\r
10793                    // odfStatusText - do not support status callback\r
10794   TOpenDirOptions = set of TOpenDirOption;\r
10795   {* Set of all flags used to control ZOpenDirDialog class. }\r
10797   TOnODSelChange = procedure( Sender: POpenDirDialog; NewSelDir: PChar;\r
10798                               var EnableOK: Integer; var StatusText: String )\r
10799                               of object;\r
10800   {* Event type to be called when user select another directory in OpenDirDialog.\r
10801      Set EnableOK to -1 to disable OK button, or to +1 to enable it.\r
10802      It is also possible to set new StatusText string. }\r
10804 { ----------------------------------------------------------------------\r
10806                                TOpenDirDialog\r
10808 ----------------------------------------------------------------------- }\r
10809 //[TOpenDirDialog DEFINITION]\r
10810   TOpenDirDialog = object( TObj )\r
10811   {* Dialog for open directories, uses SHBrowseForFolder. }\r
10812   protected\r
10813     FTitle: String;\r
10814     FOptions: TOpenDirOptions;\r
10815     FCallBack: Pointer;\r
10816     FCenterProc: procedure( Wnd: HWnd );\r
10817     FBuf : array[ 0..MAX_PATH ] of Char;\r
10818     FInitialPath: String;\r
10819     FCenterOnScreen: Boolean;\r
10820     FDoSelChanged: procedure( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ); stdcall;\r
10821     FOnSelChanged: TOnODSelChange;\r
10822     FStatusText: String;\r
10823     FWnd: HWnd;\r
10824     function GetPath: String;\r
10825     procedure SetInitialPath(const Value: String);\r
10826     procedure SetCenterOnScreen(const Value: Boolean);\r
10827     procedure SetOnSelChanged(const Value: TOnODSelChange);\r
10828     function GetInitialPath: String;\r
10829   public\r
10830     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
10831     {* destructor }\r
10832     function Execute : Boolean;\r
10833     {* Call it to select directory by user. Returns True, if operation was\r
10834        not cancelled by user. }\r
10835     property Title : String read FTitle write FTitle;\r
10836     {* Title for a dialog. }\r
10837     property Options : TOpenDirOptions read FOptions write FOptions;\r
10838     {* Option flags. }\r
10839     property Path : String read GetPath;\r
10840     {* Resulting (selected by user) path. }\r
10841     property InitialPath: String read GetInitialPath write SetInitialPath;\r
10842     {* Set this property to a path of directory to be selected initially\r
10843        in a dialog. }\r
10844     property CenterOnScreen: Boolean read FCenterOnScreen write SetCenterOnScreen;\r
10845     {* Set it to True to center dialog on screen. }\r
10846     property OnSelChanged: TOnODSelChange read FOnSelChanged write SetOnSelChanged;\r
10847     {* This event is called every time, when user selects another directory.\r
10848        It is possible to eneble/disable OK button in dialog and/or change\r
10849        dialog status text in responce to event. }\r
10850     property WndOwner: HWnd read FWnd write FWnd;\r
10851     {* Owner window. If you want to provide your dialog visible over stay-on-top\r
10852        form, fire it as a child of the form, assigning the handle of form window\r
10853        to this property first. }\r
10854   end;\r
10855 //[END OF TOpenDirDialog DEFINITION]\r
10857 //[NewOpenSaveDialog DECLARATION]\r
10858 function NewOpenDirDialog( const Title: String; Options: TOpenDirOptions ):\r
10859          POpenDirDialog;\r
10860 {* Creates object, which can be used (several times) to open directory\r
10861    selecting dialog (using SHBrowseForFolder API call). }\r
10871 //[Color Dialog Object]\r
10872 type\r
10873   TColorCustomOption = ( ccoFullOpen, ccoShortOpen, ccoPreventFullOpen );\r
10875   {++}(*TColorDialog = class;*){--}\r
10876   PColorDialog = {-}^{+}TColorDialog;\r
10877 { ----------------------------------------------------------------------\r
10879                                TColorDialog\r
10881 ----------------------------------------------------------------------- }\r
10882 //[TColorDialog DEFINITION]\r
10883   TColorDialog = object( TObj )\r
10884   {* Color choosing dialog. }\r
10885   protected\r
10886   public\r
10887     OwnerWindow: HWnd;\r
10888     {* Owner window (can be 0). }\r
10889     CustomColors: array[ 1..16 ] of TColor;\r
10890     {* Array of stored custom colors. }\r
10891     ColorCustomOption: TColorCustomOption;\r
10892     {* Options (how to open a dialog). }\r
10893     Color: TColor;\r
10894     {* Returned color (if the result of Execute is True). }\r
10895     function Execute: Boolean;\r
10896     {* Call this method to open a dialog and wait its result. }\r
10897   end;\r
10898 //[END OF TColorDialog DEFINITION]\r
10900 //[NewColorDialog DECLARATION]\r
10901 function NewColorDialog( FullOpen: TColorCustomOption ): PColorDialog;\r
10902 {* Creates color choosing dialog object. }\r
10912 //[Ini files]\r
10913 type\r
10914   TIniFileMode = ( ifmRead, ifmWrite );\r
10915   {* ifmRead is default mode (means "read" data from ini-file.\r
10916      Set mode to ifmWrite to write data to ini-file, correspondent to\r
10917      TIniFile. }\r
10919   {++}(*TIniFile = class;*){--}\r
10920   PIniFile = {-}^{+}TIniFile;\r
10921 { ----------------------------------------------------------------------\r
10923                 TIniFile - store/load data to ini-files\r
10925 ----------------------------------------------------------------------- }\r
10926 //[TIniFile DEFINITION]\r
10927   TIniFile = object( TObj )\r
10928   {* Ini file incapsulation. The main feature is what the same block of\r
10929      read-write operations could be defined (difference must be only in\r
10930      Mode value).\r
10931      |*Ini file sample.\r
10932      This sample shows how the same Pascal operators can be used both\r
10933      for read and write for the same variables, when working with TIniFile:\r
10934      !    procedure ReadWriteIni( Write: Boolean );\r
10935      !    var Ini: PIniFile;\r
10936      !    begin\r
10937      !      Ini := OpenIniFile( 'MyIniFile.ini' );\r
10938      !      Ini.Section := 'Main';\r
10939      !      if Write then            // if Write, the same operators will save\r
10940      !         Ini.Mode := ifmWrite; // data rather then load.\r
10941      !      MyForm.Left := Ini.ValueInteger( 'Left', MyForm.Left );\r
10942      !      MyForm.Top  := Ini.ValueInteger( 'Top',  MyForm.Top );\r
10943      !      Ini.Free;\r
10944      !    end;\r
10945      !\r
10946      |*  }\r
10947   protected\r
10948     fMode: TIniFileMode;\r
10949     fFileName: String;\r
10950     fSection: String;\r
10951   protected\r
10952   public\r
10953     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
10954     {* destructor }\r
10955     property Mode: TIniFileMode read fMode write fMode;\r
10956     {* ifmWrite, if write data to ini-file rather than read it. }\r
10957     property FileName: String read fFileName;\r
10958     {* Ini file name. }\r
10959     property Section: String read fSection write fSection;\r
10960     {* Current ini section. }\r
10961     function ValueInteger( const Key: String; Value: Integer ): Integer;\r
10962     {* Reads or writes integer data value. }\r
10963     function ValueString( const Key: String; const Value: String ): String;\r
10964     {* Reads or writes string data value. }\r
10965     function ValueBoolean( const Key: String; Value: Boolean ): Boolean;\r
10966     {* Reads or writes boolean data value. }\r
10967     function ValueData( const Key: String; Value: Pointer; Count: Integer ): Boolean;\r
10968     {* Reads or writes data from/to buffer. Returns True, if success. }\r
10969     procedure ClearAll;\r
10970     {* Clears all sections of ini-file. }\r
10971     procedure ClearSection;\r
10972     {* Clears current Section of ini-file. }\r
10973     procedure ClearKey( const Key: String );\r
10974     {* Clears given key in current section. }\r
10976     /////////////// + by Vyacheslav A. Gavrik:\r
10977     procedure GetSectionNames(Names:PStrList);\r
10978     {* Retrieves section names, storing it in string list passed as a parameter.\r
10979        String list does not cleared before processing. Section names are added\r
10980        to the end of the string list. }\r
10981     procedure SectionData(Names:PStrList);\r
10982     {* Read/write current section content to/from string list. (Depending on\r
10983        current Mode value). }\r
10984     ///////////////\r
10986   end;\r
10987 //[END OF TIniFile DEFINITION]\r
10989 //[OpenIniFile DECLARATION]\r
10990 function OpenIniFile( const FileName: String ): PIniFile;\r
10991 {* Opens ini file, creating TIniFile object instance to work with it. }\r
10997 //[CABINET FILES OBJECT]\r
10998 type\r
10999   {++}(*TCabFile = class;*){--}\r
11000   PCABFile = {-}^{+}TCABFile;\r
11002   TOnNextCAB = function( Sender: PCABFile ): String of object;\r
11003   TOnCABFile = function( Sender: PCABFile; var FileName: String ): Boolean of object;\r
11005 { ----------------------------------------------------------------------\r
11007                 TCabFile - windows cabinet files\r
11009 ----------------------------------------------------------------------- }\r
11010 //[TCabFile DEFINITION]\r
11011   TCABFile = object( TObj )\r
11012   {* An object to simplify extracting files from a cabinet (.CAB) files.\r
11013      The only what need to use this object, setupapi.dll. It is provided\r
11014      with all latest versions of Windows. }\r
11015   protected\r
11016     FPaths: PStrList;\r
11017     FNames: PStrList;\r
11018     FOnNextCAB: TOnNextCAB;\r
11019     FOnFile: TOnCABFile;\r
11020     FTargetPath: String;\r
11021     FSetupapi: THandle;\r
11022     function GetNames(Idx: Integer): String;\r
11023     function GetCount: Integer;\r
11024     function GetPaths(Idx: Integer): String;\r
11025     function GetTargetPath: String;\r
11026   protected\r
11027     FGettingNames: Boolean;\r
11028     FCurCAB: Integer;\r
11029   public\r
11030     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
11031     {* }\r
11032     property Paths[ Idx: Integer ]: String read GetPaths;\r
11033     {* A list of CAB-files. It is stored, when constructing function\r
11034        OpenCABFile called. }\r
11035     property Names[ Idx: Integer ]: String read GetNames;\r
11036     {* A list of file names, stored in a sequence of CAB files. To get know,\r
11037        how many files are there, check Count property. }\r
11038     property Count: Integer read GetCount;\r
11039     {* Number of files stored in a sequence of CAB files. }\r
11040     function Execute: Boolean;\r
11041     {* Call this method to extract or enumerate files in CAB. For every\r
11042        file, found during executing, event OnFile is alled (if assigned).\r
11043        If the event handler (if any) does not provide full target path for\r
11044        a file to extract to, property TargetPath is applyed (also if it\r
11045        is assigned), or file is extracted to the default directory (usually\r
11046        the same directory there CAB file is located, or current directory\r
11047        - by a decision of the system).\r
11048        |<br>\r
11049        If a sequence of CAB files is used, and not all names for CAB files\r
11050        are provided (absent or represented by a string '?' ), an event\r
11051        OnNextCAB is called to obtain the name of the next CAB file.}\r
11052     property CurCAB: Integer read FCurCAB;\r
11053     {* Index of current CAB file in a sequence of CAB files. When OnNextCAB\r
11054        event is called (if any), CurCAB property is already set to the\r
11055        index of path, what should be provided. }\r
11056     property OnNextCAB: TOnNextCAB read FOnNextCAB write FOnNextCAB;\r
11057     {* This event is called, when a series of CAB files is needed and not\r
11058        all CAB file names are provided (absent or represented by '?' string).\r
11059        If this event is not assigned, the user is prompted to browse file. }\r
11060     property OnFile: TOnCABFile read FOnFile write FOnFile;\r
11061     {* This event is called for every file found during Execute method.\r
11062        In an event handler (if any assigned), it is possible to return\r
11063        False to skip file, or to provide another full target path for\r
11064        file to extract it to, then default. If the event is not assigned,\r
11065        all files are extracted either to default directory, or to the\r
11066        directory TargetPath, if it is provided. }\r
11067     property TargetPath: String read GetTargetPath write FTargetPath;\r
11068     {* Optional target directory to place there extracted files. }\r
11069   end;\r
11070 //[END OF TCABFile DEFINITION]\r
11072 //[OpenCABFile DECLARATION]\r
11073 function OpenCABFile( const APaths: array of String ): PCABFile;\r
11074 {* This function creates TCABFile object, passing a sequence of CAB file names\r
11075    (fully qualified). It is possible not to provide all names here, or pass '?'\r
11076    string in place of some of those. For such files, either an event OnNextCAB\r
11077    will be called, or (and) user will be prompted to browse file during\r
11078    executing (i.e. Extracting). }\r
11086 //[MENU OBJECT]\r
11088 type\r
11089   TMenuitemInfo = packed record\r
11090     cbSize: UINT;\r
11091     fMask: UINT;\r
11092     fType: UINT;             { used if MIIM_TYPE}\r
11093     fState: UINT;            { used if MIIM_STATE}\r
11094     wID: UINT;               { used if MIIM_ID}\r
11095     hSubMenu: HMENU;         { used if MIIM_SUBMENU}\r
11096     hbmpChecked: HBITMAP;    { used if MIIM_CHECKMARKS}\r
11097     hbmpUnchecked: HBITMAP;  { used if MIIM_CHECKMARKS}\r
11098     dwItemData: DWORD;       { used if MIIM_DATA}\r
11099     dwTypeData: PAnsiChar;   { used if MIIM_TYPE}\r
11100     cch: UINT;               { used if MIIM_TYPE}\r
11101     hbmpItem: HBITMAP;       { used if MIIM_BITMAP - not exists under Windows95 }\r
11102   end;\r
11104 type\r
11105   {++}(*TMenu = class;*){--}\r
11106   PMenu = {-}^{+}TMenu;\r
11108   TOnMenuItem = procedure( Sender : PMenu; Item : Integer ) of object;\r
11109   {* Event type to define OnMenuItem event. }\r
11111   TMenuAccelerator = packed Record\r
11112   {* Menu accelerator record. Use MakeAccelerator function to combine desired\r
11113      attributes into a record, describing the accelerator. }\r
11114     fVirt: Byte; // or-combination of FSHIFT, FCONTROL, FALT, FVIRTKEY, FNOINVERT\r
11115     Key: Word;   // character or virtual key code (FVIRTKEY flag is present above)\r
11116     NotUsed: Byte; // not used\r
11117   end;\r
11119   // by Sergey Shisminzev:\r
11120   TMenuOption = (moDefault, moDisabled, moChecked,\r
11121           moCheckMark, moRadioMark, moSeparator, moBitmap, moSubMenu,\r
11122           moBreak, moBarBreak);\r
11123   {* Options to add menu items dynamically. }\r
11124   TMenuOptions = set of TMenuOption;\r
11125   {* Set of options for menu item to use it in TMenu.AddItem method. }\r
11127   TMenuBreak = ( mbrNone, mbrBreak, mbrBarBreak );\r
11128   {* Possible menu item break types. }\r
11130 { ----------------------------------------------------------------------\r
11132                 TMenu - main, popup menu and menu item\r
11134 ----------------------------------------------------------------------- }\r
11135 //[TMenu DEFINITION]\r
11136   TMenu = object( TObj )\r
11137   {* Dynamic menu incapsulation object. Can play role of form main menu or popup\r
11138      menu, depending on kind of parent window (form or control) and order of\r
11139      creation (created first (for a form) become main menu). Does not allow\r
11140      merging menus, but items can be hidden. Additionally checkmark bitmaps,\r
11141      shortcut key accelerators and other features are available. }\r
11142   protected\r
11143     FHandle: HMenu;\r
11144     FId: Integer;\r
11145     FParent: PMenu;\r
11146     FControl: PControl;\r
11147     fNextMenu : PMenu;\r
11148     FRadioGroup: Integer;\r
11149     FIsCheckItem: Boolean;\r
11150     FIsSeparator: Boolean;\r
11151     FMenuBreak: TMenuBreak;\r
11152     FItems: PList;\r
11153     FOnMenuItem : TOnMenuItem;\r
11154     FOnRadioOff : TOnMenuItem;\r
11155     fOnPopup: TOnEvent;\r
11156     fByAccel: Boolean;\r
11157     FPopupFlags: DWORD;\r
11158     //fAutoPopup: Boolean;\r
11159     FVisible: Boolean;\r
11160     FSavedState: DWORD;\r
11161     FData: Pointer;\r
11162     FOwnerDraw: Boolean;\r
11163     FCaption: String;\r
11164     FBitmap: HBitmap;\r
11165     FBmpChecked: HBitmap;\r
11166     FBmpItem: HBitmap;\r
11167     ClearBitmapsProc: procedure( Sender: PMenu );\r
11168     FClearBitmaps: Boolean;\r
11169     FNotPopup: Boolean;\r
11170     FAccelerator: TMenuAccelerator;\r
11171     FHelpContext: Integer;\r
11172     FOnMeasureItem: TOnMeasureItem;\r
11173     FOnDrawItem: TOnDrawItem;\r
11174     {$IFDEF USE_MENU_CURCTL}\r
11175     fCurCtl: PControl;\r
11176     {$ENDIF USE_MENU_CURCTL}\r
11177     function GetItems( Id: HMenu ): PMenu;\r
11178     function GetCount: Integer;\r
11179     function GetTopParent: PMenu;\r
11180     function GetState( const Index: Integer ): Boolean;\r
11181     procedure SetState( const Index: Integer; Value: Boolean );\r
11182     procedure SetVisible( Value: Boolean );\r
11183     procedure SetData( Value: Pointer );\r
11184     procedure SetMenuItemCaption( const Value: String );\r
11185     function FillMenuItems(AHandle: HMenu; StartIdx: Integer;\r
11186       const Template: array of PChar): Integer;\r
11187     procedure SetMenuBreak( Value: TMenuBreak );\r
11188     function GetControl: PControl;\r
11189     function GetInfo( var MII: TMenuItemInfo ): Boolean;\r
11190     function SetInfo( var MII: TMenuItemInfo ): Boolean;\r
11191     function SetTypeInfo( var MII: TMenuItemInfo ): Boolean;\r
11192     procedure SetBitmap( Value: HBitmap );\r
11193     procedure SetBmpChecked( Value: HBitmap );\r
11194     procedure SetBmpItem( Value: HBitmap );\r
11195     procedure ClearBitmaps;\r
11196     procedure SetAccelerator( const Value: TMenuAccelerator );\r
11197     procedure SetHelpContext( Value: Integer );\r
11198     procedure SetSubmenu( Value: HMenu );\r
11199     procedure SetOnMeasureItem( const Value: TOnMeasureItem );\r
11200     procedure SetOnDrawItem( const Value: TOnDrawItem );\r
11201     procedure SetOwnerDraw( Value: Boolean );\r
11202   protected\r
11203     function GetItemChecked( Item : Integer ) : Boolean;\r
11204     procedure SetItemChecked( Item : Integer; Value : Boolean );\r
11205     function GetItemBitmap(Idx: Integer): HBitmap;\r
11206     procedure SetItemBitmap(Idx: Integer; const Value: HBitmap);\r
11207     function GetItemText(Idx: Integer): String;\r
11208     procedure SetItemText(Idx: Integer; const Value: String);\r
11209     function GetItemEnabled(Idx: Integer): Boolean;\r
11210     procedure SetItemEnabled(Idx: Integer; const Value: Boolean);\r
11211     function GetItemVisible(Idx: Integer): Boolean;\r
11212     procedure SetItemVisible(Idx: Integer; const Value: Boolean);\r
11213     function GetItemAccelerator(Idx: Integer): TMenuAccelerator;\r
11214     procedure SetItemAccelerator(Idx: Integer; const Value: TMenuAccelerator);\r
11215     function GetItemSubMenu( Idx: Integer ): HMenu;\r
11216   public\r
11217     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
11218     {* To release menu dynamically, call Free method instead. All (popup)\r
11219        menus created after this (for the same control) are destroyed in\r
11220        that case too.\r
11221        |<br>\r
11222        It is not necessary to release menu object manually: all menus,\r
11223        created with given form (or control), are automatically released,\r
11224        when owner form (or control) is destroyed.\r
11225     }\r
11226     property Handle : HMenu read FHandle;\r
11227     {* Handle of Windows menu object. }\r
11228     property MenuId: Integer read FId;\r
11229     {* Id of the menu item object. If menu item has subitems, it has\r
11230        also submenu Handle. Top parent menu object itself has no Id.\r
11231        Id-s areassigned automatically starting from 4096. Do not\r
11232        (re)create menu items instantly, because such values are not\r
11233        reused, and maximum possible Id value must not exceed 65535. }\r
11234     property Parent: PMenu read FParent;\r
11235     {* Parent menu item (or parent menu). }\r
11236     property TopParent: PMenu read GetTopParent;\r
11237     {* Top parent menu, owning all nested subitems. }\r
11238     property Owner: PControl read GetControl;\r
11239     {* Parent control or form. }\r
11240     property Caption: String read FCaption write SetMenuItemCaption;\r
11241     {* Menu item caption text (including '&' indicating mnemonic characters,\r
11242        and keyboard accelerator representation string, usually following\r
11243        tabulation character). }\r
11244     property Items[ Id: HMenu ]: PMenu read GetItems;\r
11245     {* Returns menu item object by its index or by menu id. Since menu id\r
11246        values are starting from 4096, values from 0 to 4095 are interpreted\r
11247        as absolute index of menu item. Be careful accessing menu items or\r
11248        submenus by index, if you dynamically insert or delete items or\r
11249        submenus. In this version, separators are enumerating too, like\r
11250        all other items. Use index -1 to access object itself. The first\r
11251        item of a menu (or the first subitem of submenu item) has index 0.\r
11252        Children are enumerating before all siblings. The maximum available\r
11253        index is (Count - 1), when accessing menu items by index. }\r
11254     property Count: Integer read GetCount;\r
11255     {* Count of items together with all its nested subitems. }\r
11256     function IndexOf( Item: PMenu ): Integer;\r
11257     {* Returns index of an item. This index can be used to access\r
11258        menu item. Value -2 is returned, if the Item is not a child for menu\r
11259        or menu item, and has no parents, which are children for it, etc.\r
11260        Menu object itself always has index -1. }\r
11261     property OnMenuItem : TOnMenuItem read FOnMenuItem write FOnMenuItem;\r
11262     {* Is called when menu item is clicked. Absolute index of menu item\r
11263        clicked is passed as the second parameter. TopParent always is\r
11264        passed as a Sender parameter. }\r
11265     property ByAccel: Boolean read fByAccel;\r
11266     {* True, when OnMenuItem is called not by mouse, but by accelerator key.\r
11267        Check this flag for entire menu (TopParent), not for item itself.\r
11268        (Note, that Sender in OnMenuItem always is TopParent menu object). )\r
11269     }\r
11270     property IsSeparator: Boolean read FIsSeparator;\r
11271     {* TRUE, if a separator menu item. }\r
11272     property MenuBreak: TMenuBreak read FMenuBreak write SetMenuBreak;\r
11273     {* Menu item break type. }\r
11274     property OnUncheckRadioItem : TOnMenuItem read FOnRadioOff write FOnRadioOff;\r
11275     {* Is called when radio item becomes unchecked in menu in result of\r
11276        checking another radio item of the same radio group. }\r
11277     property RadioGroup: Integer read FRadioGroup write FRadioGroup;\r
11278     {* Radio group index. Several neighbour items with the same radio group\r
11279        index form radio group. Only single item from the same group can be\r
11280        checked at a time. }\r
11281     property IsCheckItem: Boolean read FIsCheckItem;\r
11282     {* If menu item is defined as check item, it is checked automatically\r
11283        when clicked. }\r
11284     procedure RadioCheckItem;\r
11285     {* Call this method to check radio item. (Calling this method for\r
11286        an item, which is not belonging to a radio group, just sets its\r
11287        Checked state to TRUE). }\r
11288     property Checked: Boolean index MFS_CHECKED read GetState write SetState;\r
11289     {* Checked state of the item. }\r
11290     property Enabled: Boolean\r
11291              {$IFDEF F_P}\r
11292              index $80000000 or MFS_DISABLED\r
11293              {$ELSE DELPHI}\r
11294              index Integer( $80000000 or MFS_DISABLED )\r
11295              {$ENDIF F_P/DELPHI}\r
11296              read GetState write SetState;\r
11297     {* Enabled state of the item. Whaen assigned, Grayed state also is\r
11298        set to arbitrary value (i.e., when Enabled is set to true, Grayed\r
11299        is set to FALSE. }\r
11300     property DefaultItem: Boolean index MFS_DEFAULT read GetState write SetState;\r
11301     {* Set this property to TRUE to make menu item default. Default item\r
11302        is drawn with bold.\r
11303        |<br>If you change DefaultItem at run-time and whant\r
11304        to provide changing its visual state, recreate the item first resetting\r
11305        Visible property, then setting it again. }\r
11306     property Highlight: Boolean index MFS_HILITE read GetState write SetState;\r
11307     {* Highlight state of the item. }\r
11308     property Visible: Boolean read FVisible write SetVisible;\r
11309     {* Visibility of menu item. }\r
11310     property Data: Pointer read FData write SetData;\r
11311     {* Data pointer, associated with the menu item. }\r
11312     property Bitmap: HBitmap read FBitmap write SetBitmap;\r
11313     {* Bitmap used for unchecked state of the menu item. }\r
11314     property BitmapChecked: HBitmap read FBmpChecked write SetBmpChecked;\r
11315     {* Bitmap used for checked state of the menu item. }\r
11316     property BitmapItem: HBitmap read FBmpItem write SetBmpItem;\r
11317     {* Bitmap used for item itself. In addition, following special values\r
11318        are possible:\r
11319        HBMMENU_CALLBACK, HBMMENU_MBAR_CLOSE, HBMMENU_MBAR_CLOSE_D,\r
11320        HBMMENU_MBAR_MINIMIZE, HBMMENU_MBAR_MINIMIZE_D, HBMMENU_MBAR_RESTORE,\r
11321        HBMMENU_POPUP_CLOSE, HBMMENU_POPUP_MAXIMIZE, HBMMENU_POPUP_MINIMIZE,\r
11322        HBMMENU_POPUP_RESTORE, HBMMENU_SYSTEM. }\r
11323     property Accelerator: TMenuAccelerator read FAccelerator write SetAccelerator;\r
11324     {* Accelerator for menu item. }\r
11325     property HelpContext: Integer read FHelpContext write SetHelpContext;\r
11326     {* Help context for entire menu (help context can not be assigned to\r
11327        individual menu items). }\r
11329     procedure AssignEvents( StartIdx: Integer; Events: array of TOnMenuItem );\r
11330     {* It is possible to assign its own event handler to every menu item\r
11331        using this call. This procedure also is called automatically in\r
11332        a constructor NewMenuEx. }\r
11334     procedure Popup( X, Y : Integer );\r
11335     {* Only for popup menu - to popup it at the given position on screen. }\r
11336     procedure PopupEx( X, Y: Integer );\r
11337     {* This version of popup command is very useful, when popup menu is activated\r
11338        when its parent window is not visible (e.g., for a kind of applications,\r
11339        which always are invisible, and can be activated only using tray icon).\r
11340        PopupEx method provides correct tracking of menu disappearing when mouse\r
11341        is clicked anywhere else on screen, fixing strange menu behavior in some\r
11342        Windows versions (NT).\r
11343        |<br>\r
11344        Actually, when PopupEx used, parent form is shown but below of visible\r
11345        screen, and when menu is disappearing, previous state of the form (visibility\r
11346        and position) are restored. If such solvation is not satisfying You,\r
11347        You can do something else (e.g., use region clipping, etc.) }\r
11348     property OnPopup: TOnEvent read fOnPopup write fOnPopup;\r
11349     {* This event occurs before the popup menu is shown. }\r
11350     property NotPopup: Boolean read FNotPopup write FNotPopup;\r
11351     {* Set this property to true to prevent popup of popup menu, e.g. in\r
11352        OnPopup event handler. }\r
11353     property Flags: DWORD read FPopupFlags write FPopupFlags;\r
11354     {* Pop-up flags, which are used to call TrackPopupMenuEx, when Popup or\r
11355        PopupEx method is called. Can be a combination of following values:\r
11356        |<br>\r
11357        TPM_CENTERALIGN or TPM_LEFTALIGN or TPM_RIGHTALIGN\r
11358        |<br>\r
11359        TPM_BOTTOMALIGN or TPM_TOPALIGN or TPM_VCENTERALIGN\r
11360        |<br>\r
11361        TPM_NONOTIFY or TPM_RETURNCMD\r
11362        |<br>\r
11363        TPM_LEFTBUTTON or TPM_RIGHTBUTTON\r
11364        |<br>\r
11365        TPM_HORNEGANIMATION or TPM_HORPOSANIMATION or TPM_NOANIMATION or\r
11366        TPM_VERNEGANIMATION or TPM_VERPOSANIMATION\r
11367        |<br>\r
11368        TPM_HORIZONTAL or TPM_VERTICAL.\r
11369        |<br>\r
11370        By default, a combination TPM_LEFTALIGN or TPM_LEFTBUTTON is used. }\r
11371     function Insert(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;\r
11372              Options: TMenuOptions): PMenu;\r
11373     {* Inserts new menu item before item, given by Id (>=4096) or index\r
11374        value InsertBefore. Pointer to an object created is returned. }\r
11375     property SubMenu: HMenu read FHandle; // write SetSubMenu;\r
11376     {* Submenu associated with the menu item. The same as Handle. It was possible\r
11377        in ealier versions to change this value, replacing (removing, assigning)\r
11378        entire popup menu as a submenu for menu item.\r
11379        But in modern version of TMenu, this is not possible.\r
11380        Instead, entire menu object should be added or removed using\r
11381        InsertSubmenu or RemoveSubmenu methods. }\r
11382     procedure InsertSubMenu( SubMenuToInsert: PMenu; InsertBefore: Integer );\r
11383     {* Inserts existing menu item (together with its subitems if any present)\r
11384        into given position. See also RemoveSubMenu. }\r
11385     function RemoveSubMenu( ItemToRemove: Integer ): PMenu;\r
11386     {* Removes menu item from the menu, returning TMenu object, representing it,\r
11387        if submenu item, having its own children, detached. If an individual menu\r
11388        item is removed, nil is returned.\r
11389        This function can be useful to add or remove dynamically entire submenus\r
11390        (created together with its subitems). }\r
11391     property OnMeasureItem: TOnMeasureItem read FOnMeasureItem write SetOnMeasureItem;\r
11392     {* This event is called for owner-drawn menu items. Event handler should return\r
11393        menu item height in lower word of a result and item width (for menu) in\r
11394        high word of result. If either for height or for width returned value is 0,\r
11395        a default one is used. }\r
11396     property OnDrawItem: TOnDrawItem read FOnDrawItem write SetOnDrawItem;\r
11397     {* This event is called for owner-drawn menu items. }\r
11398     property OwnerDraw: Boolean read FOwnerDraw write SetOwnerDraw;\r
11399     {* Set this property to true for some items to make it owner-draw. }\r
11401     // For compatibility with old code (be sure that item with given index\r
11402     // actually exists):\r
11403     function GetMenuItemHandle( Idx : Integer ): DWORD;\r
11404     {* Returns Id of menu item with given index. }\r
11405     property ItemHandle[ Idx: Integer ]: DWORD read GetMenuItemHandle;\r
11406     {* Returns handle for item given by index. }\r
11407     property ItemChecked[ Idx : Integer ] : Boolean read GetItemChecked write SetItemChecked;\r
11408     {* True, if correspondent menu item is checked. }\r
11409     procedure RadioCheck( Idx : Integer );\r
11410     {* Call this method to check radio item. For radio items, do not\r
11411        use assignment to ItemChecked or Checked properties. }\r
11412     property ItemBitmap[ Idx: Integer ]: HBitmap read GetItemBitmap write SetItemBitmap;\r
11413     {* This property allows to assign bitmap to menu item (for unchecked state\r
11414        only - for checked menu items default checkmark bitmap is used). }\r
11415     procedure AssignBitmaps( StartIdx: Integer; Bitmaps: array of HBitmap );\r
11416     {* Can be used to assign bitmaps to several menu items during one call. }\r
11417     property ItemText[ Idx: Integer ]: String read GetItemText write SetItemText;\r
11418     {* This property allows to get / modify menu item text at run time. }\r
11419     property ItemEnabled[ Idx: Integer ]: Boolean read GetItemEnabled write SetItemEnabled;\r
11420     {* Controls enabling / disabling menu items. Disabled menu items are\r
11421        displayed (grayed) but inaccessible to click. }\r
11422     property ItemVisible[ Idx: Integer ]: Boolean read GetItemVisible write SetItemVisible;\r
11423     {* This property allows to simulate visibility of menu items (implementing\r
11424        it by removing or inserting again if needed. For items of submenu, which\r
11425        is made invisible, True is returned. If such item made Visible, entire\r
11426        submenu with all its parent menu items becomes visible. To release menu\r
11427        properly it is necessary to make before all its items visible again.\r
11428        This does not matter, if menu is released at the end of execution, but\r
11429        can be sensible if owner form is destroyed and re-created at run time\r
11430        dynamically. }\r
11431     function ParentItem( Idx: Integer ): Integer;\r
11432     {* Returns index of parent menu item (for submenu item). If there are no\r
11433        such item (Idx corresponds to root level menu item), -1 is returned. }\r
11434     property ItemAccelerator[ Idx: Integer ]: TMenuAccelerator read GetItemAccelerator write SetItemAccelerator;\r
11435     {* Allows to get / change accelerator key kodes assigned to menu items.\r
11436        Has no effect unless SupportMnemonics called for a form. }\r
11437     property ItemSubmenu[ Idx: Integer ]: HMenu read GetItemSubmenu; // write SetItemSubmenu;\r
11438     {* Retrieves submenu item dynamically. See also SubMenu property. }\r
11440     // by Sergey Shisminzev:\r
11441     function AddItem(ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;\r
11442     {* Adds menu item dynamically. Returns ID of the added item. }\r
11443     function InsertItem(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;\r
11444     {* Inserts menu item before an item with ID, given by InsertBefore parameter. }\r
11445     function InsertItemEx(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions;\r
11446              ByPosition: Boolean): Integer;\r
11447     {* Inserts menu item by command or by position, dependant on ByPosition parameter }\r
11448     procedure RedrawFormMenuBar;\r
11449     {* }\r
11451     {$IFDEF USE_MENU_CURCTL}\r
11452     property CurCtl: PControl read fCurCtl;\r
11453     {* By Alexander Pravdin. This property is assigned to a control which were\r
11454        initiated a pop-up, for popup menu. }\r
11455     {$ENDIF USE_MENU_CURCTL}\r
11457   end;\r
11458 //[END OF TMenu DEFINITION]\r
11460 //[MenuStructSize VARIABLE]\r
11461 function MenuStructSize: Integer;\r
11462 {* Returns 44 under Windows95, and 48 (=sizeof(TMenuItemInfo) under all other\r
11463    Windows versions. }\r
11465 //[NewMenu DECLARATION]\r
11466 function NewMenu( AParent : PControl; MaxCmdReserve: DWORD; const Template : array of PChar;\r
11467                       aOnMenuItem: TOnMenuItem ): PMenu;\r
11468 {* Menu constructor. First created menu becomes main menu of form (if AParent\r
11469    is a form). All other menus becomes popup (can be activated using Popup\r
11470    method). To provide dynamic replacing of main menu, create all popup\r
11471    menus as children of any other control, not form itself.\r
11472    When Menu is created, pass FirstCmd integer value to set it\r
11473    as ID of first menu item (all other ID's obtained by incrementing this value),\r
11474    and Template, which is an array of PChar (usually array of string constants),\r
11475    containing list of menu item identifiers and/or formatting characters.\r
11476 |<br>&nbsp;&nbsp;&nbsp;\r
11477   FirstCmd value is assigned to first menu item created as its ID,\r
11478   all follow menu items are assigned to ID's obtained from FirstCmd incrementing\r
11479   it by 1. It is desirable to provide not intersected ranges of ID's for\r
11480   defferent menus in the applet.\r
11481 |<br>&nbsp;&nbsp;&nbsp;\r
11482   Following formatting characters can be used in menu template strings:\r
11483 |&L=<br><b>%1</b>\r
11484   <L &amp; (in identifier)> - to underline next character and use it as a shortcut character\r
11485            when possible;\r
11486   <L + (in front of identifier)> - to make item checked. If also\r
11487 |<b>!</b> is used before <b>\r
11488   &\r
11489 |</b> than radioitem is defined;\r
11490   <L - (in front of identifier)> - item not checked;\r
11491   <L - (separate)> - separator (between two items);\r
11492   <L ( (separate)> - start of submenu;\r
11493   <L ) (separate)> - end of submenu;\r
11494 |<br>&nbsp;&nbsp;&nbsp;\r
11495   To get access to menu items, use constants 0, 1, etc. It is a good idea\r
11496   to create special enumerated type to index correspondent menu items\r
11497   using Ord( ) operator. Note in that case, that it is necessary only to\r
11498   define constants correspondent to identifiers (positions, correspondent\r
11499   to separators or submenu brackets are not identified by numbers).\r
11500 |<br>&nbsp;&nbsp;&nbsp;\r
11503 function NewMenuEx( AParent : PControl; FirstCmd : Integer; const Template : array of PChar;\r
11504                       aOnMenuItems: array of TOnMenuItem ): PMenu;\r
11505 {* Creates menu, assigning its own event handler for every (enough) menu item. }\r
11507 //[MakeAccelerator DECLARATION]\r
11508 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;\r
11509 {* Creates accelerator item to assign it to TMenu.ItemAccelerator[ ] property\r
11510    easy.}\r
11512 //[GetAcceleratorText DECLARATION]\r
11513 // {YS} added 7 Aug 2004\r
11514 function GetAcceleratorText( const Accelerator: TMenuAccelerator ): string;\r
11515 {* Returns text representation of accelerator. }\r
11517 // NewActionList, TAction - by Yury Sidorov\r
11518 //[ACTIONS OBJECT]\r
11519 { ----------------------------------------------------------------------\r
11521                 TAction and TActionList\r
11523 ----------------------------------------------------------------------- }\r
11524 type\r
11525   PControlRec = ^TControlRec;\r
11526   TOnUpdateCtrlEvent = procedure(Sender: PControlRec) of object;\r
11528   TCtrlKind = (ckControl, ckMenu, ckToolbar);\r
11529   TControlRec = record\r
11530     Ctrl: PObj;\r
11531     CtrlKind: TCtrlKind;\r
11532     ItemID: integer;\r
11533     UpdateProc: TOnUpdateCtrlEvent;\r
11534   end;\r
11536   {++}(* TAction = class;*){--}\r
11537   PAction = {-}^{+}TAction;\r
11539   {++}(* TActionList = class;*){--}\r
11540   PActionList = {-}^{+}TActionList;\r
11542 //[TAction DEFINITION]\r
11543   TAction = {-} object( TObj ) {+}{++}(*class*){--}\r
11544   {*! Use action objects, in conjunction with action lists, to centralize the response\r
11545       to user commands (actions).\r
11546       Use AddControl, AddMenuItem, AddToolbarButton methods to link controls to an action.\r
11547       See also TActionList.\r
11548       }\r
11549   protected\r
11550     FControls: PList;\r
11551     FCaption: string;\r
11552     FChecked: boolean;\r
11553     FVisible: boolean;\r
11554     FEnabled: boolean;\r
11555     FHelpContext: integer;\r
11556     FHint: string;\r
11557     FOnExecute: TOnEvent;\r
11558     FAccelerator: TMenuAccelerator;\r
11559     FShortCut: string;\r
11560     procedure DoOnMenuItem(Sender: PMenu; Item: Integer);\r
11561     procedure DoOnToolbarButtonClick(Sender: PControl; BtnID: Integer);\r
11562     procedure DoOnControlClick(Sender: PObj);\r
11564     procedure SetCaption(const Value: string);\r
11565     procedure SetChecked(const Value: boolean);\r
11566     procedure SetEnabled(const Value: boolean);\r
11567     procedure SetHelpContext(const Value: integer);\r
11568     procedure SetHint(const Value: string);\r
11569     procedure SetVisible(const Value: boolean);\r
11570     procedure SetAccelerator(const Value: TMenuAccelerator);\r
11571     procedure UpdateControls;\r
11573     procedure LinkCtrl(ACtrl: PObj; ACtrlKind: TCtrlKind; AItemID: integer; AUpdateProc: TOnUpdateCtrlEvent);\r
11574     procedure SetOnExecute(const Value: TOnEvent);\r
11576     procedure UpdateCtrl(Sender: PControlRec);\r
11577     procedure UpdateMenu(Sender: PControlRec);\r
11578     procedure UpdateToolbar(Sender: PControlRec);\r
11580   public\r
11581     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
11582     procedure LinkControl(Ctrl: PControl);\r
11583     {* Add a link to a TControl or descendant control. }\r
11584     procedure LinkMenuItem(Menu: PMenu; MenuItemIdx: integer);\r
11585     {* Add a link to a menu item. }\r
11586     procedure LinkToolbarButton(Toolbar: PControl; ButtonIdx: integer);\r
11587     {* Add a link to a toolbar button. }\r
11588     procedure Execute;\r
11589     {* Executes a OnExecute event handler. }\r
11590     property Caption: string read FCaption write SetCaption;\r
11591     {* Text caption. }\r
11592     property Hint: string read FHint write SetHint;\r
11593     {* Hint (tooltip). Currently used for toolbar buttons only. }\r
11594     property Checked: boolean read FChecked write SetChecked;\r
11595     {* Checked state. }\r
11596     property Enabled: boolean read FEnabled write SetEnabled;\r
11597     {* Enabled state. }\r
11598     property Visible: boolean read FVisible write SetVisible;\r
11599     {* Visible state. }\r
11600     property HelpContext: integer read FHelpContext write SetHelpContext;\r
11601     {* Help context. }\r
11602     property Accelerator: TMenuAccelerator read FAccelerator write SetAccelerator;\r
11603     {* Accelerator for menu items. }\r
11604     property OnExecute: TOnEvent read FOnExecute write SetOnExecute;\r
11605     {* This event is executed when user clicks on a linked object or Execute method was called. }\r
11606   end;\r
11607 //[END OF TAction DEFINITION]\r
11609 //[TActionList DEFINITION]\r
11610   TActionList = {-} object( TObj ) {+}{++}(*class*){--}\r
11611   {*! TActionList maintains a list of actions used with components and controls,\r
11612      such as menu items and buttons.\r
11613      Action lists are used, in conjunction with actions, to centralize the response\r
11614      to user commands (actions).\r
11615      Write an OnUpdateActions handler to update actions state.\r
11616      Created using function NewActionList.\r
11617      See also TAction.\r
11618   }\r
11619   protected\r
11620     FOwner: PControl;\r
11621     FActions: PList;\r
11622     FOnUpdateActions: TOnEvent;\r
11623     function GetActions(Idx: integer): PAction;\r
11624     function GetCount: integer;\r
11625   protected\r
11626     procedure DoUpdateActions(Sender: PObj);\r
11627   public\r
11628     destructor Destroy; {-}virtual;{+}{++}(*override;*){--}\r
11629     function Add(const ACaption, AHint: string; OnExecute: TOnEvent): PAction;\r
11630     {* Add a new action to the list. Returns pointer to action object. }\r
11631     procedure Delete(Idx: integer);\r
11632     {* Delete action by index from list. }\r
11633     procedure Clear;\r
11634     {* Clear all actions in the list. }\r
11635     property Actions[Idx: integer]: PAction read GetActions;\r
11636     {* Access to actions in the list. }\r
11637     property Count: integer read GetCount;\r
11638     {* Number of actions in the list.. }\r
11639     property OnUpdateActions: TOnEvent read FOnUpdateActions write FOnUpdateActions;\r
11640     {* Event handler to update actions state. This event is called each time when application\r
11641       goes in the idle state (no messages in the queue). }\r
11642   end;\r
11643 //[END OF TActionList DEFINITION]\r
11645 //[NewActionList DECLARATION]\r
11646 function NewActionList(AOwner: PControl): PActionList;\r
11647 {* Action list constructor. AOwner - owner form.\r
11648 |<hr>\r
11657    <R System functions and working with windows>\r
11659 //[Window FUNCTIONS DECLARATIONS]\r
11660 type\r
11661   TWindowChildKind = ( wcActive, wcFocus, wcCapture, wcMenuOwner,\r
11662                        wcMoveSize, wcCaret );\r
11663   {* Type of window child kind. Used in function GetWindowChild. }\r
11665 function GetWindowChild( Wnd: HWnd; Kind: TWindowChildKind ): HWnd;\r
11666 {* Returns child of given top-level window, having given characteristics.\r
11667    For example, it is possible to get know for foreground window,\r
11668    which of its child window has focus. This function does not work in old\r
11669    Windows 95 (returns Wnd in that case). But for Windows 98, Windows NT/2000\r
11670    this function works fine. To obtain focused child of the window,\r
11671    use GetFocusedWindow, which is independant from Windows version. }\r
11673 function GetFocusedChild( Wnd: HWnd ): HWnd;\r
11674 {* Returns focused child of given window (which should be foreground\r
11675    and active, certainly). 0 is returned either if Wnd is not active\r
11676    or Wnd has no focused child window. }\r
11678 function Stroke2Window( Wnd: HWnd; const S: String ): Boolean;\r
11679 {* Posts characters from string S to those child window of Wnd, which\r
11680    has focus now (top-level window Wnd must be foreground, and have\r
11681    focused edit-aware control to receive the stroke).\r
11682    |<br>\r
11683    This function allows only to post typeable characters (including\r
11684    such special symbols as #13 (Enter), #9 (Tab), #8 (BackSpace), etc.\r
11685    |<br>\r
11686    See also function Stroke2WindowEx, which allows to post any key down\r
11687    and up events, simulating keyboard for given (automated) application. }\r
11689 function Stroke2WindowEx( Wnd: HWnd; const S: String; Wait: Boolean ): Boolean;\r
11690 {* In addition to function Stroke2Window, this one can send special keys\r
11691    to given window, including functional keys and navigation keys. To\r
11692    post special key to target window, place a combination of names of\r
11693    such key together with keys, which should be passed simultaneously,\r
11694    between square or figure brackets. For example, [Ctrl F1], [Alt Shift Home],\r
11695    [Ctrl E]. For letters and usual characters, it is not necessary to\r
11696    simulate pressing it with determining all Shift combinations and it is\r
11697    sufficient to pass characters as is. (E.g., not '[Shift 1]', but '!'). }\r
11699 function FindWindowByThreadID( ThreadID : DWORD ) : HWnd;\r
11700 {* Searches for window, belonging to a given thread. }\r
11702 function GetDesktopRect : TRect;\r
11703 {* Returns rectangle of screen, free of taskbar and other\r
11704    similar app-bars, which reduces size of available desktop\r
11705    when created. }\r
11706 function GetWorkArea: TRect;\r
11707 {* The same as GetDesktopRect, but obtained calling SystemParametersInfo. }\r
11709 function ExecuteWait( const AppPath, CmdLine, DfltDirectory: String;\r
11710          Show: DWORD; TimeOut: DWORD; ProcID: PDWORD ): Boolean;\r
11711 {* Allows to execute an application and wait when it is finished. Pass\r
11712    INFINITE constant as TimeOut, if You sure that application is finished\r
11713    anyway. If another value passed as a TimeOut (in milliseconds), and\r
11714    application was not finished for that time, ExecuteWait is returning\r
11715    FALSE, and if ProcID is not nil, than ProcID^ contains started process\r
11716    handle (it can be used to wait it more, or to terminate it using\r
11717    TerminateProcess API function).\r
11718    |<br>\r
11719    Launching application can be console or GUI - it does not matter.\r
11720    Pass SW_SHOW, SW_HIDE or other SW_XXX constant as Show parameter\r
11721    as appropriate.\r
11722    |<br>\r
11723    Trie is returned only in case when application specified was launched\r
11724    successfully and finished for TimeOut specified. Otherwise, check\r
11725    ProcID^ variable: if it is 0, process could not be launched (and it\r
11726    is possible to get information about error using GetLastError API\r
11727    function in a such case). You can freely pass nil in place of ProcID\r
11728    parameter, but this is acually correct only when TimeOut is INFINITE. }\r
11729 function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: String;\r
11730          Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;\r
11731 {* Executes an application with its console input and output redirection.\r
11732    Terminating of the application is not waiting, but if ProcID pointer\r
11733    is defined, it receives process Id launched, so it is possible to\r
11734    call WaitForSingleObject for it. InPipe is a pointer to THandle variable\r
11735    which receives a handle to input pipe of the console redirected. The same\r
11736    is for OutPipeWr and OutPipeRd, but for output of the console redirected.\r
11737    Before reading from OutPipeRd^, first close OutPipeWr^. If you run\r
11738    simple console application, for which you want to read results after its\r
11739    termination, you can use ExecuteConsoleAppIORedirect instead.\r
11740    |<br>&nbsp;&nbsp;&nbsp;\r
11741    Notes: if your application is not console and it does not create console\r
11742    using AllocConsole, this function will fail to redirect input-output. }\r
11743 function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;\r
11744          Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD )\r
11745          : Boolean;\r
11746 {* Executes an application, redirecting its console input and output.\r
11747    After redirecting input and output and launching the application,\r
11748    content of InStr is written to input stream of the application, then\r
11749    the application is waiting for its termination (WaitTimeout milliseconds\r
11750    or INFINITE, as passed) and console output of the application is read to\r
11751    OutStr. TRUE is returned only in case, when all these tasks are\r
11752    completed successfully.\r
11753    |<br>&nbsp;&nbsp;&nbsp;\r
11754    Notes: if your application is not console and it does not create console\r
11755    using AllocConsole, this function will fail to redirect input-output. }\r
11758 function WindowsShutdown( const Machine : String; Force, Reboot : Boolean ) : Boolean;\r
11759 {* Shut down of Windows NT. Pass Machine = '' to shutdown this PC.\r
11760    Pass Reboot = True to reboot immediatelly after shut down. }\r
11762 type\r
11763   TWindowsVersion = ( wv31, wv95, wv98, wvNT, wvY2K, wvXP, wvLongHorn );\r
11764   {* Windows versions constants. }\r
11765   TWindowsVersions = Set of TWindowsVersion;\r
11766   {* Set of Windows version (e.g. to define a range of versions supported by the\r
11767      application). }\r
11769 function WinVer : TWindowsVersion;\r
11770 {* Returns Windows version. }\r
11771 function IsWinVer( Ver : TWindowsVersions ) : Boolean;\r
11772 {* Returns True if Windows version is in given range of values. }\r
11774 //[Parameters FUNCTIONS DECLARATIONS]\r
11775 function ParamStr( Idx: Integer ): String;\r
11776 {* Returns command-line parameter by index. This function supersides\r
11777    standard ParamStr function. }\r
11778 function ParamCount: Integer;\r
11779 {* Returns number of parameters in command line.\r
11780 |<hr>\r
11784 //{$DEFINE CHK_BITBLT}\r
11785 procedure Chk_BitBlt;\r
11786 {$IFDEF ASM_VERSION}\r
11787 procedure StartDC;\r
11788 procedure FinishDC;\r
11789 {$ENDIF ASM_VERSION}\r
11791 //[WndProcXXX OTHER DECLARATIONS]\r
11792 function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
11793 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
11795 var CreatingWindow: PControl;\r
11796     //ActiveWindow: HWnd;\r
11798 //[Assert OPERATOR DECLARATION]\r
11799 {-}\r
11800 {$IFDEF _D2}\r
11801 // Assert operator was not available in Delphi2. Provide here easy Assert\r
11802 // procedure for Delphi2.\r
11803 procedure Assert( Cond: Boolean; const Msg: String );\r
11805 var AssertErrorProc: procedure( const Message, Filename: AnsiString; LineNumber: Integer );\r
11806 {$ENDIF}\r
11807 {+}\r
11810 //[CUSTOM EXTENSIONS]\r
11811 {$IFDEF USE_CUSTOMEXTENSIONS}\r
11812   {$I CUSTOM_KOL_EXTENSION.inc} // See comments in TControl\r
11813 {$ENDIF}\r
11816 {$IFDEF DEBUG_ENDSESSION}\r
11817 var EndSession_Initiated: Boolean;\r
11818 {$ENDIF}\r
11820 //[FMMNotify VARIABLE]\r
11821 var\r
11822   FMMNotify: procedure( var Msg: TMsg );\r
11824 //[procedure ClearText forward declaration]\r
11825 procedure ClearText( Sender: PControl );\r
11826 //[procedure ClearListbox forward declaration]\r
11827 procedure ClearListbox( Sender: PControl );\r
11828 //[procedure ClearCombobox forward declaration]\r
11829 procedure ClearCombobox( Sender: PControl );\r
11830 //[procedure ClearListView forward declaration]\r
11831 procedure ClearListView( Sender: PControl );\r
11832 //[procedure ClearTreeView forward declaration]\r
11833 procedure ClearTreeView( TV: PControl );\r
11835 //[START OF ACTIONS]\r
11836 const\r
11837   ButtonActions: TCommandActions = (\r
11838     aClear: ClearText;\r
11839     aAddText: nil;\r
11840     aClick: BN_CLICKED;\r
11841     aEnter: BN_SETFOCUS;\r
11842     aLeave: BN_KILLFOCUS;\r
11843     aChange: 0; //BN_CLICKED;\r
11844     aSelChange: 0;\r
11845     aGetCount: 0;\r
11846     aSetCount: 0;\r
11847     aGetItemLength: 0;\r
11848     aGetItemText: 0;\r
11849     aSetItemText: 0;\r
11850     aGetItemData: 0;\r
11851     aSetItemData: 0;\r
11852     aAddItem: 0;\r
11853     aDeleteItem: 0;\r
11854     aInsertItem: 0;\r
11855     aFindItem: 0;\r
11856     aFindPartial: 0;\r
11857     aItem2Pos: 0;\r
11858     aPos2Item: 0;\r
11859     aGetSelCount: 0;\r
11860     aGetSelected: 0;\r
11861     aGetSelRange: 0;\r
11862     aExGetSelRange: 0;\r
11863     aGetCurrent: 0;\r
11864     aSetSelected: 0;\r
11865     aSetCurrent: 0;\r
11866     aSetSelRange: 0;\r
11867     aExSetSelRange: 0;\r
11868     aGetSelection: 0;\r
11869     aReplaceSel: 0;\r
11870     aTextAlignLeft: BS_LEFT;\r
11871     aTextAlignRight: BS_RIGHT;\r
11872     aTextAlignCenter: BS_CENTER;\r
11873     aTextAlignMask: 0;\r
11874     aVertAlignCenter: BS_VCENTER shr 8;\r
11875     aVertAlignTop: BS_TOP shr 8;\r
11876     aVertAlignBottom: BS_BOTTOM shr 8;\r
11877     aDir: 0;\r
11878     aSetLimit: 0;\r
11879     aSetImgList: 0;\r
11880     aAutoSzX: 14;\r
11881     aAutoSzY: 0;\r
11882     aSetBkColor: 0;\r
11883   );\r
11885 const\r
11886   LabelActions: TCommandActions = (\r
11887     aClear: ClearText;\r
11888     aAddText: nil;\r
11889     aClick: 0;\r
11890     aEnter: 0;\r
11891     aLeave: 0;\r
11892     aChange: 0;\r
11893     aSelChange: 0;\r
11894     aGetCount: 0;\r
11895     aSetCount: 0;\r
11896     aGetItemLength: 0;\r
11897     aGetItemText: 0;\r
11898     aSetItemText: 0;\r
11899     aGetItemData: 0;\r
11900     aSetItemData: 0;\r
11901     aAddItem: 0;\r
11902     aDeleteItem: 0;\r
11903     aInsertItem: 0;\r
11904     aFindItem: 0;\r
11905     aFindPartial: 0;\r
11906     aItem2Pos: 0;\r
11907     aPos2Item: 0;\r
11908     aGetSelCount: 0;\r
11909     aGetSelected: 0;\r
11910     aGetSelRange: 0;\r
11911     aExGetSelRange: 0;\r
11912     aGetCurrent: 0;\r
11913     aSetSelected: 0;\r
11914     aSetCurrent: 0;\r
11915     aSetSelRange: 0;\r
11916     aExSetSelRange: 0;\r
11917     aGetSelection: 0;\r
11918     aReplaceSel: 0;\r
11919     aTextAlignLeft: SS_LEFT;\r
11920     aTextAlignRight: SS_RIGHT;\r
11921     aTextAlignCenter: SS_CENTER;\r
11922     aTextAlignMask: SS_LEFTNOWORDWRAP;\r
11923     aVertAlignCenter: SS_CENTERIMAGE shr 8;\r
11924     aVertAlignTop: 0;\r
11925     aVertAlignBottom: 0;\r
11926     aDir: 0;\r
11927     aSetLimit: 0;\r
11928     aSetImgList: 0;\r
11929     aAutoSzX: 1;\r
11930     aAutoSzY: 1;\r
11931     aSetBkColor: 0;\r
11932   );\r
11934 const\r
11935   EN_LINK                             = $070b;\r
11936   EditActions: TCommandActions = (\r
11937     aClear: ClearText;\r
11938     aAddText: nil;\r
11939     aClick: 0;\r
11940     aEnter: EN_SETFOCUS;\r
11941     aLeave: EN_KILLFOCUS;\r
11942     aChange: EN_CHANGE;\r
11943     aSelChange: 0;\r
11944     aGetCount: EM_GETLINECOUNT;\r
11945     aSetCount: 0;\r
11946     aGetItemLength: EM_LINELENGTH;\r
11947     aGetItemText: EM_GETLINE;\r
11948     aSetItemText: EM_REPLACESEL;\r
11949     aGetItemData: 0;\r
11950     aSetItemData: 0;\r
11951     aAddItem: 0;\r
11952     aDeleteItem: 0;\r
11953     aInsertItem: 0;\r
11954     aFindItem: 0;\r
11955     aFindPartial: 0;\r
11956     aItem2Pos: EM_LINEINDEX;\r
11957     aPos2Item: EM_LINEFROMCHAR;\r
11958     aGetSelCount: EM_GETSEL;\r
11959     aGetSelected: 0;\r
11960     aGetSelRange: EM_GETSEL;\r
11961     aExGetSelRange: 0;\r
11962     aGetCurrent: EM_LINEINDEX;\r
11963     aSetSelected: 0;\r
11964     aSetCurrent: 0;\r
11965     aSetSelRange: EM_SETSEL;\r
11966     aExSetSelRange: 0;\r
11967     aGetSelection: 0;\r
11968     aReplaceSel: EM_REPLACESEL;\r
11969     aTextAlignLeft: ES_LEFT;\r
11970     aTextAlignRight: ES_RIGHT;\r
11971     aTextAlignCenter: ES_CENTER;\r
11972     aTextAlignMask: 0;\r
11973     aVertAlignCenter: 0;\r
11974     aVertAlignTop: 0;\r
11975     aVertAlignBottom: 0;\r
11976     aDir: 0;\r
11977     aSetLimit: EM_SETLIMITTEXT;\r
11978     aSetImgList: 0;\r
11979     aAutoSzX: 0;\r
11980     aAutoSzY: 6;\r
11981     aSetBkColor: 0;\r
11982     aItem2XY: EM_POSFROMCHAR;\r
11983   );\r
11985 const\r
11986   ListActions: TCommandActions = (\r
11987     aClear: ClearListbox;\r
11988     aAddText: nil;\r
11989     aClick: LBN_DBLCLK;\r
11990     aEnter: LBN_SETFOCUS;\r
11991     aLeave: LBN_KILLFOCUS;\r
11992     aChange: 0;\r
11993     aSelChange: LBN_SELCHANGE;\r
11994     aGetCount: LB_GETCOUNT;\r
11995     aSetCount: LB_SETCOUNT;\r
11996     aGetItemLength: LB_GETTEXTLEN;\r
11997     aGetItemText: LB_GETTEXT;\r
11998     aSetItemText: 0;\r
11999     aGetItemData: LB_GETITEMDATA;\r
12000     aSetItemData: LB_SETITEMDATA;\r
12001     aAddItem: LB_ADDSTRING;\r
12002     aDeleteItem: LB_DELETESTRING;\r
12003     aInsertItem: LB_INSERTSTRING;\r
12004     aFindItem: LB_FINDSTRINGEXACT;\r
12005     aFindPartial: LB_FINDSTRING;\r
12006     aItem2Pos: 0;\r
12007     aPos2Item: 0;\r
12008     aGetSelCount: LB_GETSELCOUNT;\r
12009     aGetSelected: LB_GETSEL;\r
12010     aGetSelRange: 0;\r
12011     aExGetSelRange: 0;\r
12012     aGetCurrent: LB_GETCURSEL;\r
12013     aSetSelected: LB_SETSEL;\r
12014     aSetCurrent: LB_SETCURSEL;\r
12015     aSetSelRange: 0;\r
12016     aExSetSelRange: 0;\r
12017     aGetSelection: 0;\r
12018     aReplaceSel: 0;\r
12019     aTextAlignLeft: 0;\r
12020     aTextAlignRight: 0;\r
12021     aTextAlignCenter: 0;\r
12022     aTextAlignMask: 0;\r
12023     aVertAlignCenter: 0;\r
12024     aVertAlignTop: 0;\r
12025     aVertAlignBottom: 0;\r
12026     aDir: LB_DIR;\r
12027     aSetLimit: 0;\r
12028     aSetImgList: 0;\r
12029     aAutoSzX: 0;\r
12030     aAutoSzY: 0;\r
12031     aSetBkColor: 0;\r
12032     aItem2XY: LB_GETITEMRECT;\r
12033   );\r
12035 const\r
12036   ComboActions: TCommandActions = (\r
12037     aClear: ClearCombobox;\r
12038     aAddText: nil;\r
12039     aClick: CBN_DBLCLK;\r
12040     aEnter: CBN_SETFOCUS;\r
12041     aLeave: CBN_KILLFOCUS;\r
12042     aChange: CBN_EDITCHANGE;\r
12043     aSelChange: CM_CBN_SELCHANGE; // CBN_SELCHANGE;\r
12044     aGetCount: CB_GETCOUNT;\r
12045     aSetCount: 0;\r
12046     aGetItemLength: CB_GETLBTEXTLEN;\r
12047     aGetItemText: CB_GETLBTEXT;\r
12048     aSetItemText: 0;\r
12049     aGetItemData: CB_GETITEMDATA;\r
12050     aSetItemData: CB_SETITEMDATA;\r
12051     aAddItem: CB_ADDSTRING;\r
12052     aDeleteItem: CB_DELETESTRING;\r
12053     aInsertItem: CB_INSERTSTRING;\r
12054     aFindItem: CB_FINDSTRINGEXACT;\r
12055     aFindPartial: CB_FINDSTRING;\r
12056     aItem2Pos: 0;\r
12057     aPos2Item: 0;\r
12058     aGetSelCount: 0;\r
12059     aGetSelected: CB_GETCURSEL;\r
12060     aGetSelRange: 0;\r
12061     aExGetSelRange: 0;\r
12062     aGetCurrent: CB_GETCURSEL;\r
12063     aSetSelected: 0;\r
12064     aSetCurrent: CB_SETCURSEL;\r
12065     aSetSelRange: 0;\r
12066     aExSetSelRange: 0;\r
12067     aGetSelection: 0;\r
12068     aReplaceSel: 0;\r
12069     aTextAlignLeft: 0; //ES_LEFT;\r
12070     aTextAlignRight: 0; //ES_RIGHT;\r
12071     aTextAlignCenter: 0; //ES_CENTER;\r
12072     aTextAlignMask: 0;\r
12073     aVertAlignCenter: 0;\r
12074     aVertAlignTop: 0;\r
12075     aVertAlignBottom: 0;\r
12076     aDir: CB_DIR;\r
12077     aSetLimit: 0;\r
12078     aSetImgList: 0;\r
12079     aAutoSzX: 0;\r
12080     aAutoSzY: 6;\r
12081     aSetBkColor: 0;\r
12082   );\r
12084 const\r
12085   ListViewActions: TCommandActions = (\r
12086     aClear: ClearListView;\r
12087     aAddText: nil;\r
12088     aClick: 0;\r
12089     aEnter: 0;\r
12090     aLeave: 0;\r
12091     aChange: LVN_ITEMCHANGED;\r
12092     aSelChange: 0;\r
12093     aGetCount: LVM_GETITEMCOUNT;\r
12094     aSetCount: LVM_SETITEMCOUNT;\r
12095     aGetItemLength: 0;\r
12096     aGetItemText: 0;\r
12097     aSetItemText: 0;\r
12098     aGetItemData: 0;\r
12099     aSetItemData: 0;\r
12100     aAddItem: 0;\r
12101     aDeleteItem: 0;\r
12102     aInsertItem: 0;\r
12103     aFindItem: 0;\r
12104     aFindPartial: 0;\r
12105     aItem2Pos: 0;\r
12106     aPos2Item: 0;\r
12107     aGetSelCount: $8000 or LVM_GETSELECTEDCOUNT;\r
12108     aGetSelected: 0;\r
12109     aGetSelRange: 0;\r
12110     aExGetSelRange: 0;\r
12111     aGetCurrent: LVM_GETNEXTITEM;\r
12112     aSetSelected: 0;\r
12113     aSetCurrent: 0;\r
12114     aSetSelRange: 0;\r
12115     aExSetSelRange: 0;\r
12116     aGetSelection: 0;\r
12117     aReplaceSel: 0;\r
12118     aTextAlignLeft: 0;\r
12119     aTextAlignRight: 0;\r
12120     aTextAlignCenter: 0;\r
12121     aTextAlignMask: 0;\r
12122     aVertAlignCenter: 0;\r
12123     aVertAlignTop: 0;\r
12124     aVertAlignBottom: 0;\r
12125     aDir: 0;\r
12126     aSetLimit: 0;\r
12127     aSetImgList: LVM_SETIMAGELIST;\r
12128     aAutoSzX: 0;\r
12129     aAutoSzY: 0;\r
12130     aSetBkColor: LVM_SETBKCOLOR;\r
12131     aItem2XY: LVM_GETITEMRECT;\r
12132   );\r
12134 const\r
12135   TreeViewActions: TCommandActions = (\r
12136     aClear: ClearTreeView;\r
12137     aAddText: nil;\r
12138     aClick: 0;\r
12139     aEnter: 0;\r
12140     aLeave: 0;\r
12141     aChange: TVN_ENDLABELEDIT;\r
12142     aSelChange: TVN_SELCHANGED;\r
12143     aGetCount: TVM_GETCOUNT;\r
12144     aSetCount: 0;\r
12145     aGetItemLength: 0;\r
12146     aGetItemText: 0;\r
12147     aSetItemText: 0;\r
12148     aGetItemData: 0;\r
12149     aSetItemData: 0;\r
12150     aAddItem: 0;\r
12151     aDeleteItem: 0;\r
12152     aInsertItem: 0;\r
12153     aFindItem: 0;\r
12154     aFindPartial: 0;\r
12155     aItem2Pos: 0;\r
12156     aPos2Item: 0;\r
12157     aGetSelCount: 0;\r
12158     aGetSelected: 0;\r
12159     aGetSelRange: 0;\r
12160     aExGetSelRange: 0;\r
12161     aGetCurrent: 0;\r
12162     aSetSelected: 0;\r
12163     aSetCurrent: 0;\r
12164     aSetSelRange: 0;\r
12165     aExSetSelRange: 0;\r
12166     aGetSelection: 0;\r
12167     aReplaceSel: 0;\r
12168     aTextAlignLeft: 0;\r
12169     aTextAlignRight: 0;\r
12170     aTextAlignCenter: 0;\r
12171     aTextAlignMask: 0;\r
12172     aVertAlignCenter: 0;\r
12173     aVertAlignTop: 0;\r
12174     aVertAlignBottom: 0;\r
12175     aDir: CB_DIR;\r
12176     aSetLimit: 0;\r
12177     aSetImgList: TVM_SETIMAGELIST;\r
12178     aAutoSzX: 0;\r
12179     aAutoSzY: 0;\r
12180     aSetBkColor: TVM_SETBKCOLOR;\r
12181     aItem2XY: TVM_GETITEMRECT;\r
12182   );\r
12184 const\r
12185   TabControlActions: TCommandActions = (\r
12186     aClear: ClearText;\r
12187     aAddText: nil;\r
12188     aClick: 0;\r
12189     aEnter: 0;\r
12190     aLeave: 0;\r
12191     aChange: TCN_SELCHANGE;\r
12192     aSelChange: TCN_SELCHANGE;\r
12193     aGetCount: TCM_GETITEMCOUNT;\r
12194     aSetCount: 0;\r
12195     aGetItemLength: 0;\r
12196     aGetItemText: 0;\r
12197     aSetItemText: 0;\r
12198     aGetItemData: 0;\r
12199     aSetItemData: 0;\r
12200     aAddItem: 0;\r
12201     aDeleteItem: 0;\r
12202     aInsertItem: 0;\r
12203     aFindItem: 0;\r
12204     aFindPartial: 0;\r
12205     aItem2Pos: 0;\r
12206     aPos2Item: 0;\r
12207     aGetSelCount: 0;\r
12208     aGetSelected: 0;\r
12209     aGetSelRange: 0;\r
12210     aExGetSelRange: 0;\r
12211     aGetCurrent: TCM_GETCURSEL;\r
12212     aSetSelected: 0;\r
12213     aSetCurrent: TCM_SETCURSEL; //TCM_SETCURFOCUS;\r
12214     aSetSelRange: 0;\r
12215     aExSetSelRange: 0;\r
12216     aGetSelection: 0;\r
12217     aReplaceSel: 0;\r
12218     aTextAlignLeft: 0;\r
12219     aTextAlignRight: 0;\r
12220     aTextAlignCenter: 0;\r
12221     aTextAlignMask: 0;\r
12222     aVertAlignCenter: 0;\r
12223     aVertAlignTop: 0;\r
12224     aVertAlignBottom: 0;\r
12225     aDir: CB_DIR;\r
12226     aSetLimit: 0;\r
12227     aSetImgList: TCM_SETIMAGELIST;\r
12228     aAutoSzX: 0;\r
12229     aAutoSzY: 0;\r
12230     aSetBkColor: 0;\r
12231     aItem2XY: TCM_GETITEMRECT;\r
12232   );\r
12234 const\r
12235   RichEditActions: TCommandActions = (\r
12236     aClear: ClearText;\r
12237     aAddText: nil;\r
12238     aClick: 0;\r
12239     aEnter: EN_SETFOCUS;\r
12240     aLeave: EN_KILLFOCUS;\r
12241     aChange: EN_CHANGE;\r
12242     aSelChange: EN_SELCHANGE;\r
12243     aGetCount: EM_GETLINECOUNT;\r
12244     aSetCount: 0;\r
12245     aGetItemLength: EM_LINELENGTH;\r
12246     aGetItemText: EM_GETLINE;\r
12247     aSetItemText: EM_REPLACESEL;\r
12248     aGetItemData: 0;\r
12249     aSetItemData: 0;\r
12250     aAddItem: 0;\r
12251     aDeleteItem: 0;\r
12252     aInsertItem: 0;\r
12253     aFindItem: 0;\r
12254     aFindPartial: 0;\r
12255     aItem2Pos: EM_LINEINDEX;\r
12256     aPos2Item: EM_LINEFROMCHAR;\r
12257     aGetSelCount: 0; //EM_EXGETSEL;\r
12258     aGetSelected: 0;\r
12259     aGetSelRange: 0;\r
12260     aExGetSelRange: EM_EXGETSEL;\r
12261     aGetCurrent: EM_LINEINDEX;\r
12262     aSetSelected: 0;\r
12263     aSetCurrent: 0;\r
12264     aSetSelRange: 0;\r
12265     aExSetSelRange: EM_EXSETSEL;\r
12266     aGetSelection: EM_GETSELTEXT;\r
12267     aReplaceSel: EM_REPLACESEL;\r
12268     aTextAlignLeft: ES_LEFT;\r
12269     aTextAlignRight: ES_RIGHT;\r
12270     aTextAlignCenter: ES_CENTER;\r
12271     aTextAlignMask: 0;\r
12272     aVertAlignCenter: 0;\r
12273     aVertAlignTop: 0;\r
12274     aVertAlignBottom: 0;\r
12275     aDir: 0;\r
12276     aSetLimit: EM_EXLIMITTEXT;\r
12277     aSetImgList: 0;\r
12278     aAutoSzX: 0;\r
12279     aAutoSzY: 0;\r
12280     aSetBkColor: EM_SETBKGNDCOLOR;\r
12281     aItem2XY: EM_POSFROMCHAR;\r
12282   );\r
12284 //[IMPLEMENTATION]\r
12285 implementation\r
12287 //[USES-2]\r
12288 uses\r
12289   ShellAPI,\r
12290   commdlg\r
12291   ; //, commctrl;\r
12292             // in Delphi3, including of commctrl.pas increases executable\r
12293             // onto about 30K. So, all needed definitions are copied here\r
12294             // (see commctrl.inc).\r
12295 //[END OF USES-2]\r
12297 {$IFDEF _D2orD3}\r
12298 const\r
12299   OFN_ENABLESIZING = $00800000;\r
12300 {$ENDIF}\r
12302 //[procedure Chk_BitBlt_ShowError]\r
12303 procedure Chk_BitBlt_ShowError;\r
12304 var Rslt: Integer;\r
12305 begin\r
12306     Rslt := GetLastError;\r
12307     ShowMessage( 'BitBlt ERROR: ' + Int2Str( Rslt )\r
12308                  + ' ' + SysErrorMessage( Rslt ) );\r
12309 end;\r
12310 //[ENDe Chk_BitBlt_ShowError]\r
12312 //[procedure Chk_BitBlt]\r
12313 procedure Chk_BitBlt;\r
12314 var Rslt: Integer;\r
12315 begin\r
12316   asm\r
12317     MOV Rslt, EAX\r
12318   end;\r
12319   if Rslt = 0 then\r
12320   begin\r
12321     Chk_BitBlt_ShowError;\r
12322     asm\r
12323       int 3;\r
12324     end;\r
12325   end;\r
12326 end;\r
12327 //[ENDe Chk_BitBlt]\r
12329 //[FUNCTION MulDiv]\r
12330 {$IFNDEF FPC}\r
12331 function MulDiv( A, B, C: Integer ): Integer;\r
12332 asm\r
12333   IMUL EDX\r
12334   IDIV ECX\r
12335 end;\r
12336 {$ENDIF}\r
12337 //[END MulDiv]\r
12339 {-}\r
12340 {$ifdef _D2}\r
12342 //[PROCEDURE Assert]\r
12343 procedure Assert( Cond: Boolean; const Msg: String );\r
12344 begin\r
12345   if not Cond then\r
12346   begin\r
12347     AssertErrorProc( Msg, '', 0 );\r
12348     //MsgOK( Msg );\r
12349     asm\r
12350       int 3;\r
12351     end;\r
12352   end;\r
12353 end;\r
12355 //[API CreateDIBSection]\r
12356 function CreateDIBSection(DC: HDC; const p2: TBitmapInfo; p3: UINT;\r
12357   var p4: Pointer; p5: THandle; p6: DWORD): HBITMAP; stdcall;\r
12358 external gdi32 name 'CreateDIBSection';\r
12361 //[PROCEDURE _LStrFromPCharLen]\r
12362 procedure _LStrFromPCharLen(var Dest: AnsiString; Source: PAnsiChar; Length: Integer);\r
12363 asm\r
12364         { ->    EAX     pointer to dest }\r
12365         {       EDX source              }\r
12366         {       ECX length              }\r
12368         PUSH    EBX\r
12369         PUSH    ESI\r
12370         PUSH    EDI\r
12372         MOV     EBX,EAX\r
12373         MOV     ESI,EDX\r
12374         MOV     EDI,ECX\r
12376         { allocate new string }\r
12378         MOV     EAX,EDI\r
12380         CALL    System.@NewAnsiString\r
12381         MOV     ECX,EDI\r
12382         MOV     EDI,EAX\r
12384         TEST    ESI,ESI\r
12385         JE      @@noMove\r
12387         MOV     EDX,EAX\r
12388         MOV     EAX,ESI\r
12389         CALL    Move\r
12391         { assign the result to dest }\r
12393 @@noMove:\r
12394         MOV     EAX,EBX\r
12395         CALL    System.@LStrClr\r
12396         MOV     [EBX],EDI\r
12398         POP     EDI\r
12399         POP     ESI\r
12400         POP     EBX\r
12401 end;\r
12402 {$endif}\r
12403 {+}\r
12405 //[API InitCommonControls]\r
12406 procedure InitCommonControls; external cctrl name 'InitCommonControls';\r
12408 type\r
12409   TInitCommonControlsEx = packed record\r
12410     dwSize: DWORD;\r
12411     dwICC: DWORD;\r
12412   end;\r
12413   PInitCommonControlsEx = ^TInitCommonControlsEx;\r
12415 var ComCtl32_Module: HModule;\r
12416 //[procedure DoInitCommonControls]\r
12417 procedure DoInitCommonControls( dwICC: DWORD );\r
12418 var Proc: procedure( ICC: PInitCommonControlsEx ); stdcall;\r
12419     ICC: TInitCommonControlsEx;\r
12420 begin\r
12421   InitCommonControls;\r
12422   if ComCtl32_Module = 0 then\r
12423     ComCtl32_Module := LoadLibrary( 'comctl32.dll' );\r
12424   @ Proc := GetProcAddress( ComCtl32_Module, 'InitCommonControlsEx' );\r
12425   if Assigned( Proc ) then\r
12426   begin\r
12427     ICC.dwSize := Sizeof( ICC );\r
12428     ICC.dwICC := dwICC;\r
12429     Proc( @ ICC );\r
12430   end;\r
12431 end;\r
12432 //[END DoInitCommonControls]\r
12434 const size_TRect = 16; // used often in assembler versions of code\r
12435 {-}\r
12437 {$IFDEF ASM_VERSION}\r
12438 const\r
12439   EmptyString: String = '';\r
12441 //[PROCEDURE EAX2PChar]\r
12442 procedure EAX2PChar;\r
12443 asm\r
12444         TEST     EAX, EAX\r
12445         JNZ      @@exit\r
12446         MOV      EAX, offset[EmptyString]\r
12447 @@exit:\r
12448 end;\r
12450 //[PROCEDURE EDX2PChar]\r
12451 procedure EDX2PChar;\r
12452 asm\r
12453         TEST     EDX, EDX\r
12454         JNZ      @@exit\r
12455         MOV      EDX, offset[EmptyString]\r
12456 @@exit:\r
12457 end;\r
12459 //[PROCEDURE ECX2PChar]\r
12460 procedure ECX2PChar;\r
12461 asm\r
12462         JECXZ   @@convert\r
12463         RET\r
12464 @@convert:\r
12465         MOV     ECX, offset[EmptyString]\r
12466 @@exit:\r
12467 end;\r
12469 //[PROCEDURE RemoveStr]\r
12470 procedure RemoveStr;\r
12471 asm\r
12472         { <- [ESP+4] = string to remove\r
12473           -> ESP := ESP + 4\r
12474              EAX = 0\r
12475         }\r
12476         POP      EAX\r
12477         XCHG     EAX, [ESP]\r
12478         PUSH     EAX\r
12479         MOV      EAX, ESP\r
12480         CALL     System.@LStrClr\r
12481         POP      EAX\r
12482 end;\r
12483 {$ELSE ASM_VERSION}\r
12484 {$ENDIF ASM_VERSION}\r
12485 {+}\r
12487 //[PROCEDURE MsgOK]\r
12488 procedure MsgOK( const S: String );\r
12489 begin\r
12490   MsgBox( S, MB_OK );\r
12491 end;\r
12493 {$IFDEF ASM_VERSION}\r
12494 //[function MsgBox]\r
12495 function MsgBox( const S: String; Flags: DWORD ): DWORD;\r
12496 asm\r
12497         PUSH      EDX\r
12498         PUSH      EAX\r
12500         MOV       ECX, [Applet]\r
12501         XOR       EAX, EAX\r
12502         JECXZ     @@1\r
12503         MOV       EAX, [ECX].TControl.fCaption\r
12504 @@1:\r
12505         XCHG      EAX, [ESP]\r
12506         PUSH      EAX\r
12507         PUSH      0\r
12508         CALL      MessageBox\r
12509 end;\r
12510 {$ELSE ASM_VERSION} //Pascal\r
12511 function MsgBox( const S: String; Flags: DWORD ): DWORD;\r
12512 var Title: PChar;\r
12513 begin\r
12514   Title := nil;\r
12515   if assigned( Applet ) then\r
12516   begin\r
12517     Title := PChar( Applet.fCaption );\r
12518   end;\r
12519   Result := MessageBox( 0 {Wnd}, PChar( S ), Title, Flags );\r
12520 end;\r
12521 //[END MsgBox]\r
12522 {$ENDIF ASM_VERSION}\r
12524 //[function ShowMsg]\r
12525 function ShowMsg( const S: String; Flags: DWORD ): DWORD;\r
12526 var Title: PChar;\r
12527     Wnd: HWnd;\r
12528 begin\r
12529   Title := nil;\r
12530   Wnd := 0;\r
12531   if assigned( Applet ) then\r
12532   begin\r
12533      Title := PChar( Applet.fCaption );\r
12534      Wnd := Applet.Handle;\r
12535   end;\r
12536   Result := MessageBox( Wnd, PChar( S ), Title, Flags );\r
12537 end;\r
12538 //[END ShowMsg]\r
12540 //[procedure ShowMessage]\r
12541 procedure ShowMessage( const S: String );\r
12542 begin\r
12543   ShowMsg( S, MB_OK or MB_SETFOREGROUND );\r
12544 end;\r
12545 //[ENDe ShowMessage]\r
12547 //[procedure OKClick]\r
12548 procedure OKClick( Dialog, Btn: PControl );\r
12549 var Rslt: Integer;\r
12550 begin\r
12551   Rslt := -1;\r
12552   if Btn <> nil then\r
12553     Rslt := Btn.Tag;\r
12554   Dialog.ModalResult := Rslt;\r
12555   Dialog.Close;\r
12556 end;\r
12557 //[END OKClick]\r
12559 //[procedure KeyClick]\r
12560 procedure KeyClick( Dialog, Btn: PControl; var Key: Longint; Shift: DWORD );\r
12561 begin\r
12562   if (Key = VK_RETURN) or (Key = VK_ESCAPE) then\r
12563   begin\r
12564     if Key = VK_ESCAPE then\r
12565       Btn := nil;\r
12566     OKClick( Dialog, Btn );\r
12567   end;\r
12568 end;\r
12569 //[ENDe KeyClick]\r
12571 //[procedure CloseMsg]\r
12572 procedure CloseMsg( Dummy, Dialog: PControl; var Accept: Boolean );\r
12573 begin\r
12574   Accept := FALSE;\r
12575   Dialog.ModalResult := -1;\r
12576 end;\r
12577 //[ENDe CloseMsg]\r
12579 //[function ShowQuestionEx]\r
12580 function ShowQuestionEx( const S: String; Answers: String; CallBack: TOnEvent ): Integer;\r
12581 {$IFDEF F_P105ORBELOW}\r
12582 type POnEvent = ^TOnEvent;\r
12583      PONKey = ^TOnKey;\r
12584 var M: TMethod;\r
12585 {$ENDIF F_P105ORBELOW}\r
12586 var Dialog: PControl;\r
12587     Buttons: PList;\r
12588     Btn: PControl;\r
12589     AppTermFlag: Boolean;\r
12590     Lab: PControl;\r
12591     Y, W, I: Integer;\r
12592     Title: String;\r
12593     DlgWnd: HWnd;\r
12594     AppCtl: PControl;\r
12595 begin\r
12596   AppTermFlag := AppletTerminated;\r
12597   AppCtl := Applet;\r
12598   AppletTerminated := FALSE;\r
12599   Title := 'Information';\r
12600   if pos( '/', Answers ) > 0 then\r
12601     Title := 'Question';\r
12602   if Applet <> nil then\r
12603     Title := Applet.Caption;\r
12604   Dialog := NewForm( Applet, Title ).SetSize( 300, 40 );\r
12605   Dialog.Style := Dialog.Style and not (WS_MINIMIZEBOX or WS_MAXIMIZEBOX);\r
12606   Dialog.OnClose := TOnEventAccept( MakeMethod( Dialog, @CloseMsg ) );\r
12607   Dialog.Margin := 8;\r
12608   Lab := NewEditbox( Dialog, [ eoMultiline, eoReadonly, eoNoHScroll, eoNoVScroll ] ).SetSize( 278, 20 );\r
12609   Lab.HasBorder := FALSE;\r
12610   Lab.Color := clBtnFace;\r
12611   Lab.Caption := S;\r
12612   Lab.Style := Lab.Style and not WS_TABSTOP;\r
12613   Lab.TabStop := FALSE;\r
12614   //Lab.LikeSpeedButton;\r
12616   //Lab.CreateWindow; //virtual!!! -- not needed, window created in Perform\r
12617   while TRUE do\r
12618   begin\r
12619     Y := HiWord( Lab.Perform( EM_POSFROMCHAR, Length( S ) - 1, 0 ) );\r
12620     if Y < Lab.Height - 20 then break;\r
12621     Lab.Height := Lab.Height + 4;\r
12622     if Lab.Height + 40 > GetSystemMetrics( SM_CYSCREEN ) then break;\r
12623   end;\r
12625   Buttons := NewList;\r
12626   W := 0;\r
12627   if Answers = '' then\r
12628   begin\r
12629     Btn := NewButton( Dialog, '  OK  ' ).PlaceUnder;\r
12630     W := Btn.Width;\r
12631     Buttons.Add( Btn );\r
12632   end\r
12633     else\r
12634   while Answers <> '' do\r
12635   begin\r
12636     Btn := NewButton( Dialog, '  ' + Parse( Answers, '/' ) + '  ' );\r
12637     Buttons.Add( Btn );\r
12638     if W = 0 then\r
12639       Btn.PlaceUnder\r
12640     else\r
12641       Btn.PlaceRight;\r
12642     Btn.AutoSize( TRUE );\r
12643     if W > 0 then\r
12644     begin\r
12645       //Inc( W, 6 );\r
12646       Btn.Left := Btn.Left + 6;\r
12647     end;\r
12648     W := Btn.BoundsRect.Right + 12;\r
12649   end;\r
12650   if Dialog.ClientWidth < W then\r
12651     Dialog.ClientWidth := W;\r
12652   W := (Dialog.ClientWidth - W) div 2;\r
12653   for I := 0 to Buttons.Count-1 do\r
12654   begin\r
12655     Btn := Buttons.Items[ I ];\r
12656     Btn.Tag := I + 1;\r
12657     {$IFDEF F_P105ORBELOW}\r
12658     M := MakeMethod( Dialog, @OKClick );\r
12659     Btn.OnClick := POnEvent( @ M )^;\r
12660     M := MakeMethod( Dialog, @KeyClick );\r
12661     Btn.OnKeyDown := POnKey( @ M )^;\r
12662     {$ELSE}\r
12663     Btn.OnClick := TOnEvent( MakeMethod( Dialog, @OKClick ) );\r
12664     Btn.OnKeyDown := TOnKey( MakeMethod( Dialog, @KeyClick ) );\r
12665     {$ENDIF}\r
12666     Btn.Left := Btn.Left + W;\r
12667     if I = 0 then\r
12668     begin\r
12669       Btn.ResizeParentBottom;\r
12670       Dialog.ActiveControl := Btn;\r
12671     end;\r
12672   end;\r
12673   Dialog.CenterOnParent.Tabulate.CanResize := FALSE;\r
12674   Buttons.Free;\r
12676   if Assigned( CallBack ) then\r
12677     CallBack( Dialog );\r
12678   Dialog.CreateWindow; // virtual!!!\r
12680   if (Applet <> nil) and Applet.IsApplet then\r
12681   begin\r
12682     Dialog.ShowModal;\r
12683     Result := Dialog.ModalResult;\r
12684     Dialog.Free;\r
12685   end\r
12686     else\r
12687   begin\r
12688     DlgWnd := Dialog.Handle;\r
12689     while IsWindow( DlgWnd ) and (Dialog.ModalResult = 0) do\r
12690       Dialog.ProcessMessage;\r
12691     Result := Dialog.ModalResult;\r
12692     Dialog.Free;\r
12693     CreatingWindow := nil;\r
12694     Applet := AppCtl;\r
12695   end;\r
12697   AppletTerminated := AppTermFlag;\r
12698 end;\r
12699 //[END ShowQuestionEx]\r
12701 //[function ShowQuestion]\r
12702 function ShowQuestion( const S: String; Answers: String ): Integer;\r
12703 begin\r
12704   Result := ShowQuestionEx( S, Answers, nil );\r
12705 end;\r
12706 //[END ShowQuestion]\r
12708 //[procedure ShowMsgModal]\r
12709 procedure ShowMsgModal( const S: String );\r
12710 begin\r
12711   ShowQuestion( S, '' );\r
12712 end;\r
12713 //[ENDe ShowMsgModal]\r
12715 //[procedure SpeakerBeep]\r
12716 procedure SpeakerBeep( Freq: Word; Duration: DWORD );\r
12717 begin\r
12718   if WinVer >= wvNT then\r
12719     Windows.Beep( Freq, Duration )\r
12720   else\r
12721   begin\r
12722     if Freq < 18 then Exit;\r
12723     Freq := 1193181 div Freq;\r
12724     if Freq = 0 then Exit;\r
12725     asm\r
12726         mov al,0b6H\r
12727         out 43H,al\r
12728         mov ax,Freq\r
12729         //xchg al, ah\r
12730         out 42h,al\r
12731         xchg al, ah\r
12732         out 42h,al\r
12733         in  al,61H\r
12734         or  al,03H\r
12735         out 61H,al\r
12736     end {$IFDEF F_P} [ 'EAX' ] {$ENDIF} ;\r
12737     Sleep(Duration);\r
12738     asm\r
12739         in  al,61H\r
12740         and al,0fcH\r
12741         out 61H,al\r
12742     end {$IFDEF F_P} [ 'EAX' ] {$ENDIF} ;\r
12743   end;\r
12744 end;\r
12745 //[ENDe SpeakerBeep]\r
12747 {++}(*\r
12748 //[API FormatMessage]\r
12749 function FormatMessage; external kernel32 name 'FormatMessageA';\r
12750 *){--}\r
12752 //[FUNCTION SysErrorMessage]\r
12753 function SysErrorMessage(ErrorCode: Integer): string;\r
12754 var\r
12755   Len: Integer;\r
12756   Buffer: array[0..255] of Char;\r
12757 begin\r
12758   Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or\r
12759     FORMAT_MESSAGE_ARGUMENT_ARRAY, nil, ErrorCode, 0, Buffer,\r
12760     SizeOf(Buffer), nil);\r
12761   while (Len > 0) and (Buffer[Len - 1] in [#0..#32 {, '.'}]) do Dec(Len);\r
12762   SetString(Result, Buffer, Len);\r
12763 end;\r
12764 //[END SysErrorMessage]\r
12766 //[function MakeMethod]\r
12767 function MakeMethod( Data, Code: Pointer ): TMethod;\r
12768 begin\r
12769   Result.Data := Data;\r
12770   Result.Code := Code;\r
12771 end;\r
12772 //[END MakeMethod]\r
12774 //[function GetShiftState]\r
12775 function GetShiftState: DWORD;\r
12776 begin\r
12777   Result := 0;\r
12778   if GetKeyState( VK_SHIFT ) < 0 then\r
12779     Result := Result or MK_SHIFT;\r
12780   if GetKeyState( VK_CONTROL ) < 0 then\r
12781     Result := Result or MK_CONTROL;\r
12782   //if LONGBOOL(Msg.lParam and $20000000) then\r
12783   if GetKeyState( VK_MENU ) < 0 then\r
12784     Result := Result or MK_ALT;\r
12785 end;\r
12786 //[END GetShiftState]\r
12788 //[FUNCTION MakeRect]\r
12789 {$IFDEF ASM_VERSION}\r
12790 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;\r
12791 asm\r
12792         PUSH       ESI\r
12793         PUSH       EDI\r
12795         MOV        EDI, @Result\r
12796         LEA        ESI, [Left]\r
12798         MOVSD\r
12799         MOVSD\r
12800         MOVSD\r
12801         MOVSD\r
12803         POP        EDI\r
12804         POP        ESI\r
12805 end;\r
12806 {$ELSE ASM_VERSION} //Pascal\r
12807 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;\r
12808 begin\r
12809    Result.Left := Left;\r
12810    Result.Top  := Top;\r
12811    Result.Right:= Right;\r
12812    Result.Bottom := Bottom;\r
12813 end;\r
12814 {$ENDIF ASM_VERSION}\r
12815 //[END MakeRect]\r
12817 //[FUNCTION RectsEqual]\r
12818 {$IFDEF ASM_VERSION}\r
12819 function RectsEqual( const R1, R2: TRect ): Boolean;\r
12820 asm\r
12821         //LEA       EAX, [R1]\r
12822         //LEA       EDX, [R2]\r
12823         MOV       ECX, size_TRect\r
12824         CALL      CompareMem\r
12825 end;\r
12826 {$ELSE ASM_VERSION} //Pascal\r
12827 function RectsEqual( const R1, R2: TRect ): Boolean;\r
12828 begin\r
12829   Result := CompareMem( @R1, @R2, Sizeof( TRect ) );\r
12830 end;\r
12831 {$ENDIF ASM_VERSION}\r
12832 //[END RectsEqual]\r
12834 //[function RectsIntersected]\r
12835 function RectsIntersected( const R1, R2: TRect ): Boolean;\r
12836 begin\r
12837   Result := ((R1.Left <= R2.Left) and (R1.Right > R2.Left ) or\r
12838              (R1.Left <= R2.Right) and (R1.Right >= R2.Right) or\r
12839              (R1.Left >= R2.Left) and (R1.Right <= R2.Right))\r
12840              and\r
12841             ((R1.Top <= R2.Top) and (R1.Bottom > R2.Top) or\r
12842              (R1.Top <= R2.Bottom) and (R1.Bottom >= R2.Bottom) or\r
12843              (R1.Top >= R2.Top) and (R1.Bottom <= R2.Bottom)) ;\r
12844 end;\r
12845 //[END RectsIntersected]\r
12848 //[FUNCTION PointInRect]\r
12849 {$IFDEF ASM_VERSION}\r
12850 function PointInRect( const P: TPoint; const R: TRect ): Boolean;\r
12851 asm\r
12852         PUSH      ESI\r
12853         MOV       ECX, EAX\r
12854         MOV       ESI, EDX\r
12855         LODSD\r
12856         CMP       EAX, [ECX]\r
12857         JG        @@fail\r
12858         LODSD\r
12859         CMP       EAX, [ECX+4]\r
12860         JG        @@fail\r
12861         LODSD\r
12862         CMP       [ECX], EAX\r
12863         JG        @@fail\r
12864         LODSD\r
12865         CMP       [ECX+4], EAX\r
12866 @@fail: SETLE     AL\r
12867         POP       ESI\r
12868 end;\r
12869 {$ELSE ASM_VERSION} //Pascal\r
12870 function PointInRect( const P: TPoint; const R: TRect ): Boolean;\r
12871 begin\r
12872    Result := (P.x >= R.Left) and (P.x < R.Right)\r
12873              and (P.y >= R.Top) and (P.y < R.Bottom);\r
12874 end;\r
12875 {$ENDIF ASM_VERSION}\r
12876 //[END PointInRect]\r
12878 //[FUNCTION MakePoint]\r
12879 {$IFDEF ASM_VERSION}\r
12880 function MakePoint( X, Y: Integer ): TPoint;\r
12881 asm\r
12882         MOV      ECX, @Result\r
12883         MOV      [ECX].TPoint.x, EAX\r
12884         MOV      [ECX].TPoint.y, EDX\r
12885 end;\r
12886 {$ELSE ASM_VERSION} //Pascal\r
12887 function MakePoint( X, Y: Integer ): TPoint;\r
12888 begin\r
12889    Result.x := X;\r
12890    Result.y := Y;\r
12891 end;\r
12892 {$ENDIF ASM_VERSION}\r
12893 //[END MakePoint]\r
12895 //[FUNCTION MakeFlags]\r
12896 {$IFDEF ASM_VERSION}\r
12897 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;\r
12898 asm\r
12899         PUSH     EBX\r
12900         PUSH     ESI\r
12901         MOV      EBX, [EAX]\r
12902         MOV      ESI, EDX\r
12903         XOR      EDX, EDX\r
12904         INC      ECX\r
12905         JZ       @@exit\r
12906 @@loo:\r
12907         LODSD\r
12908         TEST     EAX, EAX\r
12909         JGE      @@ge\r
12910         NOT      EAX\r
12911         TEST     BL, 1\r
12912         JZ       @@or\r
12913         DEC      EBX\r
12914 @@ge:\r
12915         TEST     BL, 1\r
12916         JZ       @@nx\r
12917 @@or:\r
12918         OR       EDX, EAX\r
12919 @@nx:\r
12920         SHR      EBX, 1\r
12921         LOOP     @@loo\r
12923 @@exit:\r
12924         XCHG     EAX, EDX\r
12925         POP      ESI\r
12926         POP      EBX\r
12927 end;\r
12928 {$ELSE ASM_VERSION} //Pascal\r
12929 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;\r
12930 var I : Integer;\r
12931     Mask : DWORD;\r
12932 begin\r
12933   Result := 0;\r
12934   Mask := FlgSet^;\r
12935   for I := 0 to High( FlgArray ) do\r
12936   begin\r
12937     if (FlgArray[ I ] < 0) and not LongBool( Mask and 1 ) then\r
12938        Result := Result or not FlgArray[ I ]\r
12939     else\r
12940     if (FlgArray[ I ] >= 0) and LongBool( Mask and 1 ) then\r
12941        Result := Result or FlgArray[ I ];\r
12942     Mask := Mask shr 1;\r
12943   end;\r
12944 end;\r
12945 {$ENDIF ASM_VERSION}\r
12946 //[END MakeFlags]\r
12948 //[procedure HelpFastIncNum2Els]\r
12949 procedure HelpFastIncNum2Els( DataArray: Pointer; Value, Count: Integer );\r
12950 asm\r
12951   PUSH ESI\r
12952   PUSH EDI\r
12953   {$IFDEF F_P}\r
12954   MOV ESI, [DataArray]\r
12955   MOV EDX, [Value]\r
12956   MOV ECX, [Count]\r
12957   {$ELSE DELPHI}\r
12958   MOV ESI, EAX\r
12959   {$ENDIF F_P/DELPHI}\r
12960   MOV EDI, ESI\r
12961   CLD\r
12963 @@1:\r
12964   LODSD\r
12965   ADD EAX, EDX\r
12966   STOSD\r
12967   LOOP @@1\r
12969   POP EDI\r
12970   POP ESI\r
12971 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
12972 //[ENDe HelpFastIncNum2Els]\r
12974 //[procedure Swap]\r
12975 procedure Swap( var X, Y: Integer );\r
12976 {$IFDEF F_P}\r
12977 var Tmp: Integer;\r
12978 begin\r
12979   Tmp := X;\r
12980   X := Y;\r
12981   Y := Tmp;\r
12982 end;\r
12983 {$ELSE DELPHI}\r
12984 asm\r
12985   MOV  ECX, [EDX]\r
12986   XCHG ECX, [EAX]\r
12987   MOV  [EDX], ECX\r
12988 end;\r
12989 //[ENDe Swap]\r
12990 {$ENDIF F_P/DELPHI}\r
12992 //[function Min]\r
12993 function Min( X, Y: Integer ): Integer;\r
12994 asm\r
12995   {$IFDEF F_P}\r
12996   MOV EAX, [X]\r
12997   MOV EDX, [Y]\r
12998   {$ENDIF F_P}\r
12999   {$IFDEF USE_CMOV}\r
13000   CMP   EAX, EDX\r
13001   CMOVG EAX, EDX\r
13002   {$ELSE}\r
13003   CMP EAX, EDX\r
13004   JLE @@exit\r
13005   MOV EAX, EDX\r
13006 @@exit:\r
13007   {$ENDIF}\r
13008 end {$IFDEF F_P} [ 'EAX', 'EDX' ] {$ENDIF};\r
13009 //[END Min]\r
13011 //[function Max]\r
13012 function Max( X, Y: Integer ): Integer;\r
13013 asm\r
13014   {$IFDEF F_P}\r
13015   MOV EAX, [X]\r
13016   MOV EDX, [Y]\r
13017   {$ENDIF F_P}\r
13018   {$IFDEF USE_CMOV}\r
13019   CMP EAX, EDX\r
13020   CMOVL EAX, EDX\r
13021   {$ELSE}\r
13022   CMP EAX, EDX\r
13023   JGE @@exit\r
13024   MOV EAX, EDX\r
13025 @@exit:\r
13026   {$ENDIF}\r
13027 end {$IFDEF F_P} [ 'EAX', 'EDX' ] {$ENDIF};\r
13028 //[END Max]\r
13030 //[function Abs]\r
13031 function Abs( X: Integer ): Integer;\r
13032 asm\r
13033   {$IFDEF F_P}\r
13034   MOV EAX, [X]\r
13035   {$ENDIF F_P}\r
13036   TEST EAX, EAX\r
13037   JGE @@1\r
13038   NEG EAX\r
13039 @@1:\r
13040 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};\r
13041 //[END Abs]\r
13043 //[function Sgn]\r
13044 function Sgn( X: Integer ): Integer;\r
13045 asm\r
13046   CMP EAX, 0\r
13047   {$IFDEF USE_CMOV}\r
13048   MOV EDX, -1\r
13049   CMOVL EAX, EDX\r
13050   MOV EDX, 1\r
13051   CMOVG EAX, EDX\r
13052   {$ELSE}\r
13053   JZ  @@exit\r
13054   MOV EAX, 1\r
13055   JG  @@exit\r
13056   MOV EAX, -1\r
13057 @@exit:\r
13058   {$ENDIF}\r
13059 end;\r
13060 //[END Sgn]\r
13062 //[function iSqrt]\r
13063 function iSQRT( X: Integer ): Integer;\r
13064 var I, N: Integer;\r
13065 begin\r
13066   Result := 0;\r
13067   while Result < X do\r
13068   begin\r
13069     I := 1;\r
13070     while I > 0 do\r
13071     begin\r
13072       N := (Result + I) * (Result + I);\r
13073       if N > X then\r
13074       begin\r
13075         I := I shr 1;\r
13076         break;\r
13077       end\r
13078         else\r
13079       if N = X then\r
13080       begin\r
13081         Result := Result + I;\r
13082         Exit;\r
13083       end;\r
13084       I := I shl 1;\r
13085     end;\r
13086     if I <= 0 then Exit;\r
13087     Result := Result + I;\r
13088   end;\r
13089 end;\r
13090 //[END iSqrt]\r
13092 {$IFDEF ASM_VERSION}\r
13093 //[PROCEDURE StartDC]\r
13094 procedure StartDC;\r
13095 asm\r
13096   { <- EBX : PBitmap\r
13097     -> EAX = dc\r
13098        [ESP+8] = var dc\r
13099        [ESP+4] = var SaveBmp\r
13100   }\r
13101         PUSH     0\r
13102         CALL     CreateCompatibleDC\r
13103         POP      EDX\r
13104         PUSH     EAX\r
13105         PUSH     EDX\r
13106         MOV      EAX, EBX\r
13107         CALL     [EBX].TBitmap.fDetachCanvas\r
13108         MOV      EAX, EBX\r
13109         CALL     TBitmap.GetHandle\r
13110         PUSH     EAX\r
13111         PUSH     dword ptr [ESP+8]\r
13112         CALL     SelectObject\r
13113         POP      EDX\r
13114         PUSH     EAX\r
13115         PUSH     EDX\r
13116         MOV      EAX, [ESP+8]\r
13117 end;\r
13118 //[END StartDC]\r
13120 //[procedure FinishDC]\r
13121 procedure FinishDC;\r
13122 asm\r
13123         POP      ECX\r
13124         POP      EAX\r
13125         POP      EDX\r
13126         PUSH     ECX\r
13127         PUSH     EDX\r
13128         PUSH     EAX\r
13129         PUSH     EDX\r
13130         CALL     SelectObject\r
13131         CALL     DeleteDC\r
13132 end;\r
13133 //[ENDe FinishDC]\r
13134 {$ELSE ASM_VERSION}\r
13135 {$ENDIF ASM_VERSION}\r
13137 //[procedure FastIncNum2Elements]\r
13138 procedure FastIncNum2Elements( List: TList; FromIdx, Count, Value: Integer );\r
13139 begin\r
13140   HelpFastIncNum2Els( @List.fItems[ FromIdx ], Value, Count );\r
13141 end;\r
13143 //[function EnumDynHandlers FORWARD DECLARATION]\r
13144 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
13145   forward;\r
13147 //[procedure DummyObjProc]\r
13148 procedure DummyObjProc( Sender: PObj );\r
13149 begin\r
13150 end;\r
13152 //[procedure DummyObjProcParam]\r
13153 procedure DummyObjProcParam( Sender: PObj; Param: Pointer );\r
13154 begin\r
13155 end;\r
13157 //[procedure DummyPaintProc]\r
13158 procedure DummyPaintProc( Sender: PControl; DC: HDC );\r
13159 begin\r
13160 end;\r
13162 //[procedure Free_And_Nil]\r
13163 procedure Free_And_Nil( var Obj );\r
13164 var Obj1: PObj;\r
13165 begin\r
13166   Obj1 := PObj( Obj );\r
13167   Pointer( Obj ) := nil;\r
13168   Obj1.Free;\r
13169 end;\r
13170 //[ENDe Free_And_Nil]\r
13178 {-}\r
13179 { _TObj }\r
13181 //[procedure _TObj.Init]\r
13182 procedure _TObj.Init;\r
13183 begin\r
13184 {$IFDEF _D2orD3}\r
13185   FillChar( Pointer( Integer(@Self) + 4 )^, Sizeof( Self ) - 4, 0 );\r
13186 {$ENDIF}\r
13187 end;\r
13190 //[function _TObj.VmtAddr]\r
13191 function _TObj.VmtAddr: Pointer;\r
13192 asm\r
13193    MOV EAX, [EAX]\r
13194 end;\r
13196 { TObj }\r
13198 class function TObj.AncestorOfObject(Obj: Pointer): Boolean;\r
13199 asm\r
13200         MOV     ECX, [EAX]\r
13201         MOV     EAX, EDX\r
13202         JMP     @@loop1\r
13203 @@loop:\r
13204         MOV     EAX,[EAX]\r
13205 @@loop1:\r
13206         TEST    EAX,EAX\r
13207         JE      @@exit\r
13208         CMP     EAX,ECX\r
13209         JNE     @@loop\r
13210 @@success:\r
13211         MOV     AL,1\r
13212 @@exit:\r
13213 end;\r
13215 {+}\r
13217 {$IFDEF ASM_VERSION}\r
13218 constructor TObj.Create;\r
13219 asm\r
13220         //CALL      System.@ObjSetup - Generated always by compiler\r
13221         //JZ        @@exit\r
13223         PUSH      EAX\r
13224         MOV       EDX, [EAX]\r
13225         CALL      dword ptr [EDX]\r
13226         POP       EAX\r
13228 @@exit:\r
13229 end;\r
13230 {$ELSE ASM_VERSION} //Pascal\r
13231 constructor TObj.Create;\r
13232 begin\r
13233   Init;\r
13234   {++}(* inherited; *){--}\r
13235 end;\r
13236 {$ENDIF ASM_VERSION}\r
13238 {$IFDEF ASM_VERSION}\r
13239 //[procedure TObj.DoDestroy]\r
13240 procedure TObj.DoDestroy;\r
13241 asm\r
13242         MOV       EDX, [EAX].fRefCount\r
13243         SAR       EDX, 1\r
13244         JZ        @@1\r
13245         JC        @@exit\r
13246         DEC       [EAX].fRefCount\r
13247         STC\r
13249 @@1:    JC        @@exit\r
13250         MOV       EDX, [EAX]\r
13251         CALL      dword ptr [EDX + 4]\r
13252 @@exit:\r
13253 end;\r
13254 {$ELSE ASM_VERSION} //Pascal\r
13255 procedure TObj.DoDestroy;\r
13256 begin\r
13257   if fRefCount <> 0 then\r
13258   begin\r
13259     if not LongBool( fRefCount and 1) then\r
13260        Dec( fRefCount );\r
13261   end\r
13262   else\r
13263      Destroy;\r
13264 end;\r
13265 {$ENDIF ASM_VERSION}\r
13267 {$IFDEF ASM_VERSION}\r
13268 //[procedure TObj.RefDec]\r
13269 procedure TObj.RefDec;\r
13270 asm\r
13271         SUB      [EAX].fRefCount, 2\r
13272         JGE      @@exit\r
13273         TEST     [EAX].fRefCount, 1\r
13274         JZ       @@exit\r
13275         MOV      EDX, [EAX]\r
13276         PUSH     dword ptr [EDX+4]\r
13277 @@exit:\r
13278 end;\r
13279 {$ELSE ASM_VERSION} //Pascal\r
13280 procedure TObj.RefDec;\r
13281 begin\r
13282   Dec( fRefCount, 2 );\r
13283   if (fRefCount < 0) and LongBool(fRefCount and 1) then\r
13284     Destroy;\r
13285 end;\r
13286 {$ENDIF ASM_VERSION}\r
13288 //[procedure TObj.RefInc]\r
13289 procedure TObj.RefInc;\r
13290 begin\r
13291   Inc( fRefCount, 2 );\r
13292 end;\r
13294 {-}\r
13295 //[function TObj.VmtAddr]\r
13296 function TObj.VmtAddr: Pointer;\r
13297 asm\r
13298        MOV    EAX, [EAX - 4]\r
13299 end;\r
13301 //[function TObj.InstanceSize]\r
13302 function TObj.InstanceSize: Integer;\r
13303 asm\r
13304        MOV    EAX, [EAX]\r
13305        MOV    EAX,[EAX-4]\r
13306 end;\r
13307 {+}\r
13309 //[procedure TObj.Free]\r
13310 procedure TObj.Free;\r
13311 {$IFDEF F_P}\r
13312 begin\r
13313   if Self <> nil then\r
13314     DoDestroy;\r
13315 end;\r
13316 {$ELSE DELPHI}\r
13317 asm\r
13318    TEST    EAX,EAX\r
13319    JNE     DoDestroy\r
13320 end;\r
13321 {$ENDIF F_P/DELPHI}\r
13323 {$IFDEF ASM_VERSION}\r
13324 destructor TObj.Destroy;\r
13325 asm\r
13326         PUSH      EAX\r
13327         CALL      Final\r
13328         POP       EAX\r
13329         XOR       EDX, EDX\r
13330         CALL      System.@FreeMem\r
13331         //CALL      System.@Dispose\r
13332 end;\r
13333 {$ELSE ASM_VERSION} //Pascal\r
13334 destructor TObj.Destroy;\r
13335 begin\r
13336   Final;\r
13337   {$IFDEF DEBUG_ENDSESSION}\r
13338   if EndSession_Initiated then\r
13339     LogFileOutput( GetStartDir + 'es_debug.txt',\r
13340                    'FINALLED: ' + Int2Hex( DWORD( @ Self ), 8 ) );\r
13341   {$ENDIF}\r
13342   {-}\r
13343   Dispose( @Self );\r
13344   {+} {++}(*\r
13345   inherited; *){--}\r
13346 end;\r
13347 {$ENDIF ASM_VERSION}\r
13349 {++}(*\r
13350 //[procedure TObj.Init]\r
13351 procedure TObj.Init;\r
13352 begin\r
13354 end;\r
13355 *){--}\r
13357 {$IFDEF ASM_VERSION}\r
13358 //[procedure TObj.Final]\r
13359 procedure TObj.Final;\r
13360 asm     //cmd    //opd\r
13361         XOR      ECX, ECX\r
13362         XCHG     ECX, [EAX].fOnDestroy.TMethod.Code\r
13363         JECXZ    @@doAutoFree\r
13364         PUSH     EAX\r
13365         XCHG     EDX, EAX\r
13366         MOV      EAX, [EDX].fOnDestroy.TMethod.Data\r
13367         CALL     ECX\r
13368         POP      EAX\r
13369 @@doAutoFree:\r
13370         XOR      ECX, ECX\r
13371         XCHG     ECX, [EAX].fAutoFree\r
13372         JECXZ    @@exit\r
13373         PUSH     ESI\r
13374         PUSH     ECX\r
13375         MOV      ESI, [ECX].TList.fItems\r
13376         MOV      ECX, [ECX].TList.fCount\r
13377 @@freeloop:\r
13378         LODSD\r
13379         XCHG     EDX, EAX\r
13380         LODSD\r
13381         PUSH     ECX\r
13382         CALL     EDX\r
13383         POP      ECX\r
13384         DEC      ECX\r
13385         LOOP     @@freeloop\r
13386         POP      EAX\r
13387         CALL     TObj.Free\r
13388         POP      ESI\r
13389 @@exit:\r
13390 end;\r
13391 {$ELSE ASM_VERSION} //Pascal\r
13392 procedure TObj.Final;\r
13393 var I: Integer;\r
13394     ProcMethod: TMethod;\r
13395     Proc: TObjectMethod Absolute ProcMethod;\r
13396 begin\r
13397   if Assigned( fOnDestroy ) then\r
13398   begin\r
13399     fOnDestroy( @Self );\r
13400     fOnDestroy := nil;\r
13401   end;\r
13402   if fAutoFree <> nil then\r
13403   begin\r
13404     for I := 0 to fAutoFree.fCount div 2 - 1 do\r
13405     begin\r
13406       ProcMethod.Code := fAutoFree.fItems[ I * 2 ];\r
13407       ProcMethod.Data := fAutoFree.fItems[ I * 2 + 1 ];\r
13408       {-}\r
13409       Proc;\r
13410       {+}{++}(*\r
13411       asm\r
13412         MOV  EAX, [ProcMethod.Data]\r
13413         {$IFDEF F_P}\r
13414         PUSH EAX\r
13415         {$ENDIF F_P}\r
13416         MOV  ECX, [ProcMethod.Code]\r
13417         CALL ECX\r
13418       end {$IFDEF F_P}[ 'EAX', 'EDX', 'ECX' ]{$ENDIF};\r
13419       *){--}\r
13420     end;\r
13421     fAutoFree.Free;\r
13422     fAutoFree := nil;\r
13423   end;\r
13424 end;\r
13425 {$ENDIF ASM_VERSION}\r
13427 {$IFDEF ASM_VERSION}\r
13428 //[procedure TObj.Add2AutoFree]\r
13429 procedure TObj.Add2AutoFree(Obj: PObj);\r
13430 asm     //cmd    //opd\r
13431         PUSH     EBX\r
13432         PUSH     EDX\r
13433         XCHG     EBX, EAX\r
13434         MOV      EAX, [EBX].fAutoFree\r
13435         TEST     EAX, EAX\r
13436         JNZ      @@1\r
13437         CALL     NewList\r
13438         MOV      [EBX].fAutoFree, EAX\r
13439 @@1:    MOV      EBX, EAX\r
13440         XOR      EDX, EDX\r
13441         POP      ECX\r
13442         CALL     TList.Insert\r
13443         XCHG     EAX, EBX\r
13444         XOR      EDX, EDX\r
13445         MOV      ECX, offset TObj.Free\r
13446         //XOR      ECX, ECX\r
13447         CALL     TList.Insert\r
13448         POP      EBX\r
13449 end;\r
13450 {$ELSE ASM_VERSION} //Pascal\r
13451 procedure TObj.Add2AutoFree(Obj: PObj);\r
13452 begin\r
13453   if fAutoFree = nil then\r
13454     fAutoFree := NewList;\r
13455   fAutoFree.Insert( 0, Obj );\r
13456   fAutoFree.Insert( 0, Pointer( @TObj.Free ) );\r
13457 end;\r
13458 {$ENDIF ASM_VERSION}\r
13460 {$IFDEF ASM_VERSION}\r
13461 //[procedure TObj.Add2AutoFreeEx]\r
13462 procedure TObj.Add2AutoFreeEx( Proc: TObjectMethod );\r
13463 asm     //cmd    //opd\r
13464         PUSH     EBX\r
13465         XCHG     EAX, EBX\r
13466         MOV      EAX, [EBX].fAutoFree\r
13467         TEST     EAX, EAX\r
13468         JNZ      @@1\r
13469         CALL     NewList\r
13470         MOV      [EBX].fAutoFree, EAX\r
13471 @@1:    XOR      EDX, EDX\r
13472         MOV      ECX, [EBP+12] // Data\r
13473         MOV      EBX, EAX\r
13474         CALL     TList.Insert\r
13475         XCHG     EAX, EBX\r
13476         XOR      EDX, EDX\r
13477         MOV      ECX, [EBP+8] // Code\r
13478         CALL     TList.Insert\r
13479         POP      EBX\r
13480 end;\r
13481 {$ELSE ASM_VERSION} //Pascal\r
13482 procedure TObj.Add2AutoFreeEx( Proc: TObjectMethod );\r
13483 {$IFDEF F_P}\r
13484 var Ptr1, Ptr2: Pointer;\r
13485 {$ENDIF F_P}\r
13486 begin\r
13487   if fAutoFree = nil then\r
13488     fAutoFree := NewList;\r
13489   {$IFDEF F_P}\r
13490   asm\r
13491     MOV  EAX, [Proc]\r
13492     MOV  [Ptr1], EAX\r
13493     MOV  EAX, [Proc+4]\r
13494     MOV  [Ptr2], EAX\r
13495   end [ 'EAX' ];\r
13496   fAutoFree.Insert( 0, Ptr2 );\r
13497   fAutoFree.Insert( 0, Ptr1 );\r
13498   {$ELSE DELPHI}\r
13499   fAutoFree.Insert( 0, Pointer( TMethod( Proc ).Data ) );\r
13500   fAutoFree.Insert( 0, Pointer( TMethod( Proc ).Code ) );\r
13501   {$ENDIF}\r
13502 end;\r
13503 {$ENDIF ASM_VERSION}\r
13519 { TList }\r
13521 {$IFDEF USE_CONSTRUCTORS}\r
13522 //[function NewList]\r
13523 function NewList: PList;\r
13524 begin\r
13525   New( Result, Create );\r
13526   //Result.fAddBy := 4;\r
13527 end;\r
13528 //[END NewList]\r
13530 //[procedure TList.Init]\r
13531 procedure TList.Init;\r
13532 begin\r
13533   inherited;\r
13534   fAddBy := 4;\r
13535 end;\r
13536 {$ELSE not_USE_CONSTRUCTORS}\r
13537 //[function NewList]\r
13538 function NewList: PList;\r
13539 begin\r
13540   {-}\r
13541   New( Result, Create );\r
13542   {+} {++}(* Result := PList.Create; *){--}\r
13543   //Result.fAddBy := 4;\r
13544 end;\r
13545 //[END NewList]\r
13546 {$ENDIF USE_CONSTRUCTORS}\r
13548 {$IFDEF ASM_VERSION}\r
13549 destructor TList.Destroy;\r
13550 asm\r
13551         PUSH      EAX\r
13552         CALL      TList.Clear\r
13553         POP       EAX\r
13554         CALL      TObj.Destroy\r
13555 end;\r
13556 {$ELSE ASM_VERSION} //Pascal\r
13557 destructor TList.Destroy;\r
13558 begin\r
13559    Clear;\r
13560    inherited;\r
13561 end;\r
13562 {$ENDIF ASM_VERSION}\r
13564 {$IFDEF ASM_VERSION}\r
13565 //[procedure TList.Release]\r
13566 procedure TList.Release;\r
13567 asm\r
13568        TEST      EAX, EAX\r
13569        JZ        @@e\r
13570        MOV       ECX, [EAX].fCount\r
13571        JECXZ     @@e\r
13572        MOV       EDX, [EAX].fItems\r
13573        PUSH      EAX\r
13574 @@1:\r
13575        MOV       EAX, [EDX+ECX*4-4]\r
13576        TEST      EAX, EAX\r
13577        JZ        @@2\r
13578        PUSH      EDX\r
13579        PUSH      ECX\r
13580        CALL      System.@FreeMem\r
13581        POP       ECX\r
13582        POP       EDX\r
13583 @@2:   LOOP      @@1\r
13584        POP       EAX\r
13585 @@e:   CALL      TObj.Free\r
13586 end;\r
13587 {$ELSE ASM_VERSION} //Pascal\r
13588 procedure TList.Release;\r
13589 var I: Integer;\r
13590 begin\r
13591   if @ Self = nil then Exit;\r
13592   for I := 0 to fCount - 1 do\r
13593     if fItems[ I ] <> nil then\r
13594       FreeMem( fItems[ I ] );\r
13595   Free;\r
13596 end;\r
13597 {$ENDIF ASM_VERSION}\r
13599 //[procedure TList.ReleaseObjects]\r
13600 procedure TList.ReleaseObjects;\r
13601 var I: Integer;\r
13602 begin\r
13603   if @ Self = nil then Exit;\r
13604   for I := fCount-1 downto 0 do\r
13605     PObj( fItems[ I ] ).Free;\r
13606   Free;\r
13607 end;\r
13609 {$IFDEF ASM_VERSION}\r
13610 //[procedure TList.SetCapacity]\r
13611 procedure TList.SetCapacity( Value: Integer );\r
13612 asm\r
13613         CMP       EDX, [EAX].fCount\r
13614         {$IFDEF USE_CMOV}\r
13615         CMOVL     EDX, [EAX].fCount\r
13616         {$ELSE}\r
13617         JGE       @@1\r
13618         MOV       EDX, [EAX].fCount\r
13619 @@1:    {$ENDIF}\r
13620         CMP       EDX, [EAX].fCapacity\r
13621         JE        @@exit\r
13623         MOV       [EAX].fCapacity, EDX\r
13624         SAL       EDX, 2\r
13625         LEA       EAX, [EAX].fItems\r
13626         CALL      System.@ReallocMem\r
13627 @@exit:\r
13628 end;\r
13629 {$ELSE ASM_VERSION} //Pascal\r
13630 //var NewItems: PPointerList;\r
13631 procedure TList.SetCapacity( Value: Integer );\r
13632 begin\r
13633    if Value < Count then\r
13634       Value := Count;\r
13635    if Value = fCapacity then Exit;\r
13636    ReallocMem( fItems, Value * Sizeof( Pointer ) );\r
13637    fCapacity := Value;\r
13638 end;\r
13639 {$ENDIF ASM_VERSION}\r
13641 {$IFDEF ASM_VERSION}\r
13642 //[procedure TList.Clear]\r
13643 procedure TList.Clear;\r
13644 asm\r
13645         PUSH      [EAX].fItems\r
13646         XOR       EDX, EDX\r
13647         MOV       [EAX].fItems, EDX\r
13648         MOV       [EAX].fCount, EDX\r
13649         MOV       [EAX].fCapacity, EDX\r
13650         POP       EAX\r
13651         CALL      System.@FreeMem\r
13652 end;\r
13653 {$ELSE ASM_VERSION} //Pascal\r
13654 procedure TList.Clear;\r
13655 begin\r
13656    if fItems <> nil then\r
13657       FreeMem( fItems );\r
13658    fItems := nil;\r
13659    fCount := 0;\r
13660    fCapacity := 0;\r
13661 end;\r
13662 {$ENDIF ASM_VERSION}\r
13664 //[procedure TList.SetAddBy]\r
13665 procedure TList.SetAddBy(Value: Integer);\r
13666 begin\r
13667   if Value < 1 then Value := 1;\r
13668   fAddBy := Value;\r
13669 end;\r
13671 {$IFDEF ASM_VERSION}\r
13672 //[procedure TList.Add]\r
13673 procedure TList.Add( Value: Pointer );\r
13674 asm\r
13675         PUSH      EDX\r
13676         LEA       ECX, [EAX].fCount\r
13677         MOV       EDX, [ECX]\r
13678         INC       dword ptr [ECX]\r
13679           PUSH      EDX\r
13680           CMP       EDX, [EAX].fCapacity\r
13681             PUSH      EAX\r
13682             JL        @@ok\r
13684             MOV       ECX, [EAX].fAddBy\r
13685             TEST      ECX, ECX\r
13686             JNZ       @@add\r
13687             MOV       ECX, EDX\r
13688             SHR       ECX, 2\r
13689             INC       ECX\r
13690           @@add:\r
13691             ADD       EDX, ECX\r
13692             CALL      TList.SetCapacity\r
13693 @@ok:\r
13694             POP       ECX  // ECX = Self\r
13695           POP       EAX    // EAX = fCount -> Result (for TList.Insert)\r
13696         POP       EDX      // EDX = Value\r
13698         MOV       ECX, [ECX].fItems\r
13699         MOV       [ECX + EAX*4], EDX\r
13700 end;\r
13701 {$ELSE ASM_VERSION} //Pascal\r
13702 procedure TList.Add( Value: Pointer );\r
13703 begin\r
13704    //if fAddBy <= 0 then fAddBy := 4;\r
13705    if fCapacity <= Count then\r
13706    begin\r
13707      if fAddBy <= 0 then\r
13708        Capacity := Count + Min( 1000, Count div 4 + 1 )\r
13709      else\r
13710        Capacity := Count + fAddBy;\r
13711    end;\r
13712    fItems[ fCount ] := Value;\r
13713    Inc( fCount );\r
13714 end;\r
13715 {$ENDIF ASM_VERSION}\r
13717 //[procedure TList.Delete]\r
13718 procedure TList.Delete( Idx: Integer );\r
13719 begin\r
13720    {Assert( (Idx >= 0) and (Idx < fCount), 'TList.Delete: index out of bounds' );\r
13721    Move( fItems[ Idx + 1 ], fItems[ Idx ], Sizeof( Pointer ) * (Count - Idx - 1) );\r
13722    Dec( fCount );}\r
13723    DeleteRange( Idx, 1 );\r
13724 end;\r
13726 {$IFDEF ASM_VERSION}\r
13727 //[procedure TList.DeleteRange]\r
13728 procedure TList.DeleteRange(Idx, Len: Integer);\r
13729 asm     //cmd    //opd\r
13730         TEST     ECX, ECX\r
13731         JLE      @@exit\r
13732         CMP      EDX, [EAX].fCount\r
13733         JGE      @@exit\r
13734         PUSH     EBX\r
13735         XCHG     EBX, EAX\r
13736         LEA      EAX, [EDX+ECX]\r
13737         CMP      EAX, [EBX].fCount\r
13738         JBE      @@1\r
13739         MOV      ECX, [EBX].fCount\r
13740         SUB      ECX, EDX\r
13741 @@1:\r
13742         MOV      EAX, [EBX].fItems\r
13743         PUSH     [EBX].fCount\r
13744         SUB      [EBX].fCount, ECX\r
13745         MOV      EBX, EDX\r
13746         LEA      EDX, [EAX+EDX*4]\r
13747         LEA      EAX, [EDX+ECX*4]\r
13748         ADD      EBX, ECX\r
13749         POP      ECX\r
13750         SUB      ECX, EBX\r
13751         SHL      ECX, 2\r
13752         CALL     System.Move\r
13753         POP      EBX\r
13754 @@exit:\r
13755 end;\r
13756 {$ELSE ASM_VERSION} //Pascal\r
13757 procedure TList.DeleteRange(Idx, Len: Integer);\r
13758 begin\r
13759   if Len <= 0 then Exit;\r
13760   if Idx >= Count then Exit;\r
13761   Assert( (Idx >= 0), 'TList.DeleteRange: index out of bounds' );\r
13762   if DWORD( Idx + Len ) > DWORD( Count ) then\r
13763     Len := Count - Idx;\r
13764   Move( fItems[ Idx + Len ], fItems[ Idx ], Sizeof( Pointer ) * (Count - Idx - Len) );\r
13765   Dec( fCount, Len );\r
13766 end;\r
13767 {$ENDIF ASM_VERSION}\r
13769 //[procedure TList.Remove]\r
13770 procedure TList.Remove(Value: Pointer);\r
13771 var I: Integer;\r
13772 begin\r
13773   I := IndexOf( Value );\r
13774   if I >= 0 then\r
13775     Delete( I );\r
13776 end;\r
13778 //[procedure TList.Put]\r
13779 procedure TList.Put( Idx: Integer; Value: Pointer );\r
13780 begin\r
13781    if Idx < 0 then Exit;\r
13782    if Idx >= Count then Exit;\r
13783    //Assert( (Idx >= 0) and (Idx < fCount), 'TList.Put: index out of bounds' );\r
13784    fItems[ Idx ] := Value;\r
13785 end;\r
13787 //[function TList.Get]\r
13788 function TList.Get( Idx: Integer ): Pointer;\r
13789 begin\r
13790    Result := nil;\r
13791    if Idx < 0 then Exit;\r
13792    if Idx >= fCount then Exit;\r
13793    //Assert( (Idx >= 0) and (Idx < fCount), 'TList.Get: index out of bounds' );\r
13794    Result := fItems[ Idx ];\r
13795 end;\r
13797 {$IFDEF ASM_VERSION}\r
13798 //[function TList.IndexOf]\r
13799 function TList.IndexOf( Value: Pointer ): Integer;\r
13800 asm\r
13801         PUSH      EDI\r
13803         MOV       EDI, [EAX].fItems\r
13804         MOV       ECX, [EAX].fCount\r
13805           PUSH      EDI\r
13806           DEC       EAX            // make "NZ" - EAX always <> 1\r
13807           MOV       EAX, EDX\r
13808           REPNZ     SCASD\r
13809           POP       EDX\r
13810         {$IFDEF USE_CMOV}\r
13811         CMOVNZ    EDI, EDX\r
13812         {$ELSE}\r
13813         JZ        @@succ\r
13814         MOV       EDI, EDX\r
13815 @@succ: {$ENDIF}\r
13817         MOV       EAX, EDI\r
13818         STC\r
13819         SBB       EAX, EDX\r
13820         SAR       EAX, 2\r
13822         POP       EDI\r
13823 end;\r
13824 {$ELSE ASM_VERSION} //Pascal\r
13825 function TList.IndexOf( Value: Pointer ): Integer;\r
13826 var I: Integer;\r
13827 begin\r
13828    Result := -1;\r
13829    for I := 0 to Count - 1 do\r
13830    begin\r
13831       if fItems[ I ] = Value then\r
13832       begin\r
13833          Result := I;\r
13834          break;\r
13835       end;\r
13836    end;\r
13837 end;\r
13838 {$ENDIF ASM_VERSION}\r
13840 {$IFDEF ASM_VERSION}\r
13841 //[procedure TList.Insert]\r
13842 procedure TList.Insert(Idx: Integer; Value: Pointer);\r
13843 asm\r
13844         PUSH      ECX\r
13845         PUSH      EAX\r
13846         PUSH      [EAX].fCount\r
13847           PUSH      EDX\r
13848           CALL      TList.Add   // don't matter what to add\r
13849           POP       EDX         // EDX = Idx, Eax = Count-1\r
13850         POP       EAX\r
13851         SUB       EAX, EDX\r
13853         SAL       EAX, 2\r
13854         MOV       ECX, EAX      // ECX = (Count - Idx - 1) * 4\r
13855         POP       EAX\r
13856         MOV       EAX, [EAX].fItems\r
13857         LEA       EAX, [EAX + EDX*4]\r
13858         JL        @@1\r
13859           PUSH      EAX\r
13860           LEA       EDX, [EAX + 4]\r
13861           CALL      System.Move\r
13863           POP       EAX          // EAX = @fItems[ Idx ]\r
13864 @@1:\r
13865         POP       ECX            // ECX = Value\r
13866         MOV       [EAX], ECX\r
13867 end;\r
13868 {$ELSE ASM_VERSION} //Pascal\r
13869 procedure TList.Insert(Idx: Integer; Value: Pointer);\r
13870 begin\r
13871    Assert( (Idx >= 0) and (Idx <= Count), 'List index out of bounds' );\r
13872    Add( nil );\r
13873    if fCount > Idx then\r
13874      Move( FItems[ Idx ], FItems[ Idx + 1 ], (fCount - Idx - 1) * Sizeof( Pointer ) );\r
13875    FItems[ Idx ] := Value;\r
13876 end;\r
13877 {$ENDIF ASM_VERSION}\r
13879 {$IFDEF ASM_VERSION}\r
13880 //[procedure TList.MoveItem]\r
13881 procedure TList.MoveItem(OldIdx, NewIdx: Integer);\r
13882 asm\r
13883         CMP       EDX, ECX\r
13884         JE        @@exit\r
13886         CMP       ECX, [EAX].fCount\r
13887         JGE       @@exit\r
13889         PUSH      EDI\r
13891         MOV       EDI, [EAX].fItems\r
13892         PUSH      dword ptr [EDI + EDX*4]\r
13893           PUSH      ECX\r
13894           PUSH      EAX\r
13895           CALL      TList.Delete\r
13896           POP       EAX\r
13897           POP       EDX\r
13898         POP       ECX\r
13900         POP       EDI\r
13901         CALL      TList.Insert\r
13902 @@exit:\r
13903 end;\r
13904 {$ELSE ASM_VERSION} //Pascal\r
13905 procedure TList.MoveItem(OldIdx, NewIdx: Integer);\r
13906 var Item: Pointer;\r
13907     //I: Integer;\r
13908 begin\r
13909   if OldIdx = NewIdx then Exit;\r
13910   if NewIdx >= Count then Exit;\r
13911   Item := Items[ OldIdx ];\r
13912   Delete( OldIdx );\r
13913   Insert( NewIdx, Item );\r
13914 end;\r
13915 {$ENDIF ASM_VERSION}\r
13917 {$IFDEF ASM_VERSION}\r
13918 //[function TList.Last]\r
13919 function TList.Last: Pointer;\r
13920 asm     //cmd    //opd\r
13921         MOV      ECX, [EAX].fCount\r
13922         JECXZ    @@0\r
13923         MOV      EAX, [EAX].fItems\r
13924         DEC      ECX\r
13925         MOV      ECX, [EAX + ECX*4]\r
13926 @@0:    XCHG     EAX, ECX\r
13927 end;\r
13928 {$ELSE ASM_VERSION} //Pascal\r
13929 function TList.Last: Pointer;\r
13930 begin\r
13931   if Count = 0 then\r
13932     Result := nil\r
13933   else\r
13934     Result := Items[ Count-1 ];\r
13935 end;\r
13936 {$ENDIF ASM_VERSION}\r
13938 {$IFDEF ASM_VERSION}\r
13939 //[procedure TList.Swap]\r
13940 procedure TList.Swap(Idx1, Idx2: Integer);\r
13941 asm\r
13942         MOV       EAX, [EAX].fItems\r
13943           PUSH      dword ptr [EAX + EDX*4]\r
13944             PUSH      ECX\r
13945             MOV       ECX, [EAX + ECX*4]\r
13946             MOV       [EAX + EDX*4], ECX\r
13947             POP       ECX\r
13948           POP       EDX\r
13949         MOV       [EAX + ECX*4], EDX\r
13950 end;\r
13951 {$ELSE ASM_VERSION} //Pascal\r
13952 procedure TList.Swap(Idx1, Idx2: Integer);\r
13953 var Tmp: Pointer;\r
13954 begin\r
13955   Tmp := FItems[ Idx1 ];\r
13956   FItems[ Idx1 ] := FItems[ Idx2 ];\r
13957   FItems[ Idx2 ] := Tmp;\r
13958 end;\r
13959 {$ENDIF ASM_VERSION}\r
13961 //[procedure TList.SetCount]\r
13962 procedure TList.SetCount(const Value: Integer);\r
13963 begin\r
13964   if Value >= Count then exit;\r
13965   fCount := Value;\r
13966 end;\r
13968 //[procedure TList.Assign]\r
13969 procedure TList.Assign(SrcList: PList);\r
13970 begin\r
13971   Clear;\r
13972   if SrcList.fCount > 0 then\r
13973   begin\r
13974     Capacity := SrcList.fCount;\r
13975     fCount := SrcList.fCount;\r
13976     Move( SrcList.FItems[ 0 ], FItems[ 0 ], Sizeof( Pointer ) * fCount );\r
13977   end;\r
13978 end;\r
13980 { TListEx }\r
13982 //[function NewListEx]\r
13983 function NewListEx: PListEx;\r
13984 begin\r
13985   {-}\r
13986   new( Result, Create );\r
13987   {+}{++}(*Result := PListEx.Create;*){--}\r
13988   Result.fList := NewList;\r
13989   Result.fObjects := NewList;\r
13990 end;\r
13991 //[END NewListEx]\r
13993 //[procedure TListEx.Add]\r
13994 procedure TListEx.Add(Value: Pointer);\r
13995 begin\r
13996   AddObj( Value, nil );\r
13997 end;\r
13999 //[procedure TListEx.AddObj]\r
14000 procedure TListEx.AddObj(Value, Obj: Pointer);\r
14001 var C: Integer;\r
14002 begin\r
14003   C := Count;\r
14004   fList.Add( Value );\r
14005   fObjects.Insert( C, Obj );\r
14006 end;\r
14008 //[procedure TListEx.Clear]\r
14009 procedure TListEx.Clear;\r
14010 begin\r
14011   fList.Clear;\r
14012   fObjects.Clear;\r
14013 end;\r
14015 //[procedure TListEx.Delete]\r
14016 procedure TListEx.Delete(Idx: Integer);\r
14017 begin\r
14018   DeleteRange( Idx, 1 );\r
14019 end;\r
14021 //[procedure TListEx.DeleteRange]\r
14022 procedure TListEx.DeleteRange(Idx, Len: Integer);\r
14023 begin\r
14024   fList.DeleteRange( Idx, Len );\r
14025   fObjects.DeleteRange( Idx, Len );\r
14026 end;\r
14028 //[destructor TListEx.Destroy]\r
14029 destructor TListEx.Destroy;\r
14030 begin\r
14031   fList.Free;\r
14032   fObjects.Free;\r
14033   inherited;\r
14034 end;\r
14036 //[function TListEx.GetAddBy]\r
14037 function TListEx.GetAddBy: Integer;\r
14038 begin\r
14039   Result := fList.AddBy;\r
14040 end;\r
14042 //[function TListEx.GetCount]\r
14043 function TListEx.GetCount: Integer;\r
14044 begin\r
14045   Result := fList.Count;\r
14046 end;\r
14048 //[function TListEx.GetEx]\r
14049 function TListEx.GetEx(Idx: Integer): Pointer;\r
14050 begin\r
14051   Result := fList.Items[ Idx ];\r
14052 end;\r
14054 //[function TListEx.IndexOf]\r
14055 function TListEx.IndexOf(Value: Pointer): Integer;\r
14056 begin\r
14057   Result := fList.IndexOf( Value );\r
14058 end;\r
14060 //[function TListEx.IndexOfObj]\r
14061 function TListEx.IndexOfObj(Obj: Pointer): Integer;\r
14062 begin\r
14063   Result := fObjects.IndexOf( Obj );\r
14064 end;\r
14066 //[procedure TListEx.Insert]\r
14067 procedure TListEx.Insert(Idx: Integer; Value: Pointer);\r
14068 begin\r
14069   InsertObj( Idx, Value, nil );\r
14070 end;\r
14072 //[procedure TListEx.InsertObj]\r
14073 procedure TListEx.InsertObj(Idx: Integer; Value, Obj: Pointer);\r
14074 begin\r
14075   fList.Insert( Idx, Value );\r
14076   fObjects.Insert( Idx, Obj );\r
14077 end;\r
14079 //[function TListEx.Last]\r
14080 function TListEx.Last: Pointer;\r
14081 begin\r
14082   Result := fList.Last;\r
14083 end;\r
14085 //[function TListEx.LastObj]\r
14086 function TListEx.LastObj: Pointer;\r
14087 begin\r
14088   Result := fObjects.Last;\r
14089 end;\r
14091 //[procedure TListEx.MoveItem]\r
14092 procedure TListEx.MoveItem(OldIdx, NewIdx: Integer);\r
14093 begin\r
14094   fList.MoveItem( OldIdx, NewIdx );\r
14095   fObjects.MoveItem( OldIdx, NewIdx );\r
14096 end;\r
14098 //[procedure TListEx.PutEx]\r
14099 procedure TListEx.PutEx(Idx: Integer; const Value: Pointer);\r
14100 begin\r
14101   fList.Items[ Idx ] := Value;\r
14102 end;\r
14104 //[procedure TListEx.Set_AddBy]\r
14105 procedure TListEx.Set_AddBy(const Value: Integer);\r
14106 begin\r
14107   fList.AddBy := Value;\r
14108   fObjects.AddBy := Value;\r
14109 end;\r
14111 //[procedure TListEx.Swap]\r
14112 procedure TListEx.Swap(Idx1, Idx2: Integer);\r
14113 begin\r
14114   fList.Swap( Idx1, Idx2 );\r
14115   fObjects.Swap( Idx1, Idx2 );\r
14116 end;\r
14135 { -- Window procedure -- }\r
14137 {$IFDEF ASM_VERSION} //!!//!!\r
14138 //[FUNCTION CallCtlWndProc]\r
14139 function CallCtlWndProc( Ctl: PControl; var Msg: TMsg ): Integer;\r
14140 begin\r
14141   Result := Ctl.WndProc( Msg );\r
14142 end;\r
14143 //[END CallCtlWndProc]\r
14145 //[function WndFunc]\r
14146 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )\r
14147                                    : Integer; stdcall;\r
14148 const   size_TMsg = sizeof( TMsg );\r
14149 asm\r
14150         ADD       ESP, -size_TMsg\r
14151         MOV       EDX, ESP\r
14153         PUSH      ESI\r
14154         PUSH      EDI\r
14156         MOV       EDI, EDX\r
14157         LEA       ESI, [W]\r
14159         MOVSD\r
14160         MOVSD\r
14161         MOVSD\r
14162         MOVSD\r
14164         MOV       EDI, EDX\r
14165         MOV       EAX, [EDI]\r
14166         TEST      EAX, EAX\r
14167         JZ        @@self_is_nil\r
14169         MOV       ECX, [CreatingWindow]\r
14170         JECXZ     @@get_self_prop\r
14172         MOV       [ECX].TControl.fHandle, EAX\r
14174 //set_self_prop:\r
14175         PUSH      ECX\r
14176           PUSH      ECX\r
14177           PUSH      Offset[ID_SELF]\r
14178           PUSH      EAX\r
14179           CALL      SetProp\r
14181           XOR       EAX, EAX\r
14182           MOV       [CreatingWindow], EAX\r
14183         POP       EAX                 // EAX = self_\r
14184         JMP       @@self_got\r
14186 @@get_self_prop:\r
14187         PUSH      Offset[ID_SELF]\r
14188         PUSH      EAX\r
14189         CALL      GetProp\r
14190         TEST      EAX, EAX\r
14191         JNZ       @@self_got\r
14193 @@self_is_nil:\r
14194         OR        EAX, [ Applet ]\r
14195         JNZ       @@self_got\r
14197 //try_defwndproc:\r
14198         POP       EDI\r
14199         POP       ESI\r
14200         MOV       ESP, EBP\r
14201         POP       EBP\r
14202         JMP       DefWindowProc\r
14204 //@@id_self:\r
14205 //        DB        'SELF_',0\r
14207 @@self_got:\r
14208         MOV       EDX, EDI\r
14209         //CALL      TControl.WndProc\r
14210         CALL      CallCtlWndProc\r
14212         POP       EDI\r
14213         POP       ESI\r
14215         MOV       ESP, EBP\r
14216 end;\r
14217 {$ELSE ASM_VERSION} //Pascal\r
14218 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )\r
14219                                    : Integer; stdcall;\r
14220 var M: TMsg;\r
14221     self_: PControl;\r
14222 begin\r
14223    M.hwnd := W;\r
14224    M.message := Msg;\r
14225    M.wParam := wParam;\r
14226    M.lParam := lParam;\r
14228    {$IFDEF DEBUG_ENDSESSION}\r
14229    if EndSession_Initiated then\r
14230    begin\r
14231      LogFileOutput( GetStartDir + 'es_debug.txt',\r
14232        'HWND:' + Int2Str( W ) + ' MSG:$' + Int2Hex( Msg, 4 ) +\r
14233        ' WParam: ' + Int2Str( wParam ) + '($' + Int2Hex( wParam, 8 ) + ')' +\r
14234        ' LParam: ' + Int2Str( lParam ) + '($' + Int2Hex( lParam, 8 ) + ')' );\r
14235    end;\r
14236    {$ENDIF}\r
14238    self_ := nil;\r
14239    if W <> 0 then\r
14240    begin\r
14241      if CreatingWindow <> nil then\r
14242      begin\r
14243         {$IFDEF DEBUG_CREATEWINDOW}\r
14244         LogFileOutput( GetStartDir + 'Session.log',\r
14245                        'WndFunc: Creating window = ' + Int2Hex( Integer( CreatingWindow ), 4 ) +\r
14246                        ' hwnd=' + Int2Str( M.hwnd ) +\r
14247                        ' message=' + Int2Hex( M.message, 4 ) +\r
14248                        ' wParam=' + Int2Str( M.wParam ) + '=$' + Int2Hex( M.wParam, 4 ) +\r
14249                        ' lParam=' + Int2Str( M.lParam ) + '=$' + Int2Hex( M.lParam, 4 )\r
14250                      );\r
14251         {$ENDIF DEBUG_CREATEWINDOW}\r
14252         self_ := CreatingWindow;\r
14253         CreatingWindow.fHandle := W;\r
14254         SetProp( W, ID_SELF, THandle( CreatingWindow ) );\r
14255         CreatingWindow := nil;\r
14256      end\r
14257         else\r
14258      self_ := Pointer( GetProp( W, ID_SELF ) );\r
14259    end;\r
14261    if self_ <> nil then\r
14262       Result := self_.WndProc( M )\r
14263    else\r
14264    if Assigned( Applet ) then\r
14265       Result := Applet.WndProc( M )\r
14266    else\r
14267       Result := DefWindowProc( W, Msg, wParam, lParam );\r
14268    {$IFDEF DEBUG_ENDSESSION}\r
14269    if EndSession_Initiated then\r
14270    begin\r
14271      LogFileOutput( GetStartDir + 'es_debug.txt',\r
14272        'HWND:' + Int2Str( W ) + ' MSG:$' + Int2Hex( Msg, 4 ) +\r
14273        ' Result: ' + Int2Str( Result ) + '($' + Int2Hex( Result, 8 ) + ')' );\r
14274    end;\r
14275    {$ENDIF}\r
14276 end;\r
14277 //[END WndFunc]\r
14278 {$ENDIF ASM_VERSION}\r
14280 var\r
14281   IdleHandlers: PList;\r
14282   ProcessIdle: procedure ( Sender: PObj ) = DummyObjProc;\r
14284 //[procedure ProcessIdleProc]\r
14285 procedure ProcessIdleProc( Sender: PObj );\r
14286 var\r
14287   i: integer;\r
14288   m: TMethod;\r
14289 begin\r
14290   if AppletTerminated then exit;  // YS +\r
14291   i := 0;\r
14292   with IdleHandlers{-}^{+} do\r
14293     while i < Count do begin\r
14294       m.Code:=Items[i];\r
14295       Inc(i);\r
14296       m.Data:=Items[i];\r
14297       Inc(i);\r
14298       TOnEvent(m)(Sender);\r
14299     end;\r
14300 end;\r
14302 //[function FindIdleHandler]\r
14303 function FindIdleHandler( const OnIdle: TOnEvent ): integer;\r
14304 var\r
14305   i: integer;\r
14306 begin\r
14307   i := 0;\r
14308   if not AppletTerminated then //+ {Maxim Pushkar}\r
14309   with TMethod(OnIdle), IdleHandlers{-}^{+} do\r
14310     while i < Count do begin\r
14311       if (Items[i] = Code) and (Items[i + 1] = Data) then\r
14312       begin\r
14313         Result := i;\r
14314         exit;\r
14315       end;\r
14316       Inc(i, 2);\r
14317     end;\r
14318   Result := -1;\r
14319 end;\r
14320 //[END FindIdleHandler]\r
14322 //[procedure RegisterIdleHandler]\r
14323 procedure RegisterIdleHandler( const OnIdle: TOnEvent );\r
14324 begin\r
14325   if IdleHandlers = nil then begin\r
14326     IdleHandlers := NewList;\r
14327     if Applet <> nil then\r
14328       Applet.Add2AutoFree(IdleHandlers);\r
14329   end;\r
14330   with TMethod(OnIdle) do\r
14331   begin\r
14332     IdleHandlers.Add(Code);\r
14333     IdleHandlers.Add(Data);\r
14334   end;\r
14335   ProcessIdle := @ProcessIdleProc;\r
14336 end;\r
14338 //[procedure UnRegisterIdleHandler]\r
14339 procedure UnRegisterIdleHandler( const OnIdle: TOnEvent );\r
14340 var\r
14341   i: integer;\r
14342 begin\r
14343   i := FindIdleHandler(OnIdle);\r
14344   if i <> -1 then\r
14345   with IdleHandlers{-}^{+} do\r
14346   begin\r
14347     Delete(i);\r
14348     Delete(i);\r
14349   end;\r
14350 end;\r
14352 //[procedure TerminateExecution]\r
14353 procedure TerminateExecution( var AppletWnd: PControl );\r
14354 var App: PControl;\r
14355     Appalreadyterminated: Boolean;\r
14356 begin\r
14357   Appalreadyterminated := AppletTerminated;\r
14358   AppletTerminated := TRUE;\r
14359   AppletRunning := FALSE;\r
14360   App := Applet;\r
14361   Applet := nil;\r
14362   if (App <> nil) {and (App.RefCount >= 0)} then\r
14363   begin\r
14364     App.RefInc;\r
14365     if not Appalreadyterminated then\r
14366     begin\r
14367       App.ProcessMessages;\r
14368       App.Perform( WM_CLOSE, 0, 0 );\r
14369     end;\r
14370     AppletWnd := nil;\r
14371     App.Free;\r
14372     App.RefDec;\r
14373   end;\r
14374 end;\r
14376 //[PROCEDURE CallTControlCreateWindow]\r
14377 {$IFDEF ASM_VERSION}\r
14378 procedure CallTControlCreateWindow( Ctl: PControl );\r
14379 begin\r
14380   Ctl.CreateWindow;\r
14381 end;\r
14382 //[END CallTControlCreateWindow]\r
14384 //[PROCEDURE Run]\r
14385 procedure Run( var AppletWnd: PControl );\r
14386 asm\r
14387         PUSH      EBX\r
14388         XCHG      EBX, EAX\r
14390         INC       [AppletRunning]\r
14391         MOV       EAX, [EBX]\r
14392         MOV       [Applet], EAX\r
14393         CALL      CallTControlCreateWindow\r
14394         JMP       @@2\r
14395 @@1:\r
14396         CALL      WaitMessage\r
14397         MOV       EAX, [EBX]\r
14398         CALL      TControl.ProcessMessages\r
14399         {$IFNDEF NOT_USE_OnIdle}\r
14400         MOV       EAX, [EBX]\r
14401         CALL      [ProcessIdle]\r
14402         {$ENDIF}\r
14403 @@2:\r
14404         CMP       [AppletTerminated],0\r
14405         JZ        @@1\r
14407         XCHG      EAX, EBX\r
14409         POP       EBX\r
14410         TEST      EAX, EAX\r
14411         JNZ       TerminateExecution\r
14412 end;\r
14413 {$ELSE ASM_VERSION} //Pascal\r
14414 procedure Run( var AppletWnd: PControl );\r
14415 begin\r
14416   AppletRunning := True;\r
14417   Applet := AppletWnd;\r
14418   AppletWnd.CreateWindow; //virtual!!!\r
14419   while not AppletTerminated do\r
14420   begin\r
14421     WaitMessage;\r
14422     AppletWnd.ProcessMessages;\r
14423     {$IFNDEF NOT_USE_OnIdle}\r
14424     ProcessIdle( AppletWnd );\r
14425     {$ENDIF}\r
14426   end;\r
14427   if AppletWnd <> nil then\r
14428     TerminateExecution( AppletWnd );\r
14429 end;\r
14430 //[END Run]\r
14431 {$ENDIF ASM_VERSION}\r
14433 //[procedure AppletMinimize]\r
14434 procedure AppletMinimize;\r
14435 begin\r
14436   if Applet = nil then Exit;\r
14437   Applet.Perform( WM_SYSCOMMAND, SC_MINIMIZE, 0 );\r
14438 end;\r
14440 //[procedure AppletHide]\r
14441 procedure AppletHide;\r
14442 begin\r
14443   if Applet = nil then Exit;\r
14444   AppletMinimize;\r
14445   Applet.Hide;\r
14446 end;\r
14448 //[procedure AppletRestore]\r
14449 procedure AppletRestore;\r
14450 begin\r
14451   if Applet = nil then Exit;\r
14452   Applet.Show;\r
14453   Applet.Perform( WM_SYSCOMMAND, SC_RESTORE, 0 );\r
14454 end;\r
14456 //[function ScreenWidth]\r
14457 function ScreenWidth: Integer;\r
14458 begin\r
14459   Result := GetSystemMetrics( SM_CXSCREEN );\r
14460 end;\r
14461 //[END ScreenWidth]\r
14463 //[function ScreenHeight]\r
14464 function ScreenHeight: Integer;\r
14465 begin\r
14466   Result := GetSystemMetrics( SM_CYSCREEN );\r
14467 end;\r
14468 //[END ScreenHeight]\r
14476 {$IFDEF USE_CONSTRUCTORS}\r
14477   {$DEFINE WNDPROCAPP_USED}\r
14478   {$DEFINE WNDPROCAPP_ASM_USED}\r
14479 {$ENDIF USE_CONSTRUCTORS}\r
14480 {$IFNDEF ASM_VERSION}\r
14481   {$DEFINE WNDPROCAPP_USED}\r
14482 {$ENDIF  ASM_VERSION}\r
14484   {$DEFINE WNDPROCAPP_USED}\r
14488 {$IFNDEF WNDPROCAPP_USED}\r
14489 //[WndProcXXX FORWARD DECLARATIONS]\r
14490   {$IFNDEF ASM_VERSION}\r
14491 function WndProcApp( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14492   {$ENDIF}\r
14493 {$ENDIF}\r
14494 function WndProcForm( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14495 //function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14496 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14497 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14498 function WndProcGradientEx( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14499 function WndProcLabelEffect( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14500 //function WndProcParentResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14501 //function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14502 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14503 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;\r
14504 var fGlobalProcKeybd: function( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean =\r
14505     WndProcDummy;\r
14506 //[END OF WndProcXXX FORWARD DECLARATIONS]\r
14520 { -- Graphics support -- }\r
14522 //[function _NewGraphicTool]\r
14523 function _NewGraphicTool: PGraphicTool;\r
14524 begin\r
14525   {-}\r
14526   New( Result, Create );\r
14527   {+}\r
14528   {++}(*Result := PGraphicTool.Create;*){--}\r
14529 end;\r
14530 //[END _NewGraphicTool]\r
14532 //[FUNCTION SimpleGetCtlBrushHandle]\r
14533 {$IFDEF ASM_VERSION}\r
14534 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush;\r
14535 asm     //        //\r
14536 @@1:    MOV       ECX, [EAX].TControl.fParent\r
14537         JECXZ     @@2\r
14538         MOV       EDX, [EAX].TControl.fColor\r
14539         CMP       EDX, [ECX].TControl.fColor\r
14540         XCHG      EAX, ECX\r
14541         JE        @@1\r
14542         XCHG      EAX, ECX\r
14543 @@2:    PUSH      EBX\r
14544         XCHG      EBX, EAX\r
14545         MOV       ECX, [EBX].TControl.fTmpBrush\r
14546         JECXZ     @@3\r
14547         MOV       EAX, [EBX].TControl.fColor\r
14548         CALL      Color2RGB\r
14549         CMP       EAX, [EBX].TControl.fTmpBrushColorRGB\r
14550         JE        @@3\r
14551         XOR       EAX, EAX\r
14552         XCHG      [EBX].TControl.fTmpBrush, EAX\r
14553         PUSH      EAX\r
14554         CALL      DeleteObject\r
14555 @@3:    MOV       EAX, [EBX].TControl.fTmpBrush\r
14556         TEST      EAX, EAX\r
14557         JNE       @@4\r
14558         MOV       EAX, [EBX].TControl.fColor\r
14559         CALL      Color2RGB\r
14560         MOV       [EBX].TControl.fTmpBrushColorRGB, EAX\r
14561         PUSH      EAX\r
14562         CALL      CreateSolidBrush\r
14563         MOV       [EBX].TControl.fTmpBrush, EAX\r
14564 @@4:    POP       EBX\r
14565 end;\r
14566 {$ELSE ASM_VERSION PAS_VERSION}\r
14567 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush;\r
14568 begin\r
14569   if (Sender.fParent <> nil) and (Sender.fColor = Sender.fParent.fColor) then\r
14570     Result := SimpleGetCtlBrushHandle( Sender.fParent )\r
14571   else\r
14572   begin\r
14573     if (Sender.fTmpBrush <> 0) and\r
14574        (Color2RGB( Sender.fColor ) <> Sender.fTmpBrushColorRGB) then\r
14575     begin\r
14576       DeleteObject( Sender.fTmpBrush );\r
14577       Sender.fTmpBrush := 0;\r
14578     end;\r
14579     if Sender.fTmpBrush = 0 then\r
14580     begin\r
14581       Sender.fTmpBrushColorRGB := Color2RGB( Sender.fColor );\r
14582       Sender.fTmpBrush := CreateSolidBrush( Sender.fTmpBrushColorRGB );\r
14583     end;\r
14584     Result := Sender.fTmpBrush;\r
14585   end;\r
14586 end;\r
14587 {$ENDIF ASM_VERSION}\r
14588 //[END SimpleGetCtlBrushHandle]\r
14590 //[function NormalGetCtlBrushHandle]\r
14591 function NormalGetCtlBrushHandle( Sender: PControl ): HBrush;\r
14592 begin\r
14593   if (Sender.fParent <> nil) then\r
14594     Sender.Brush.fParentGDITool := Sender.fParent.Brush;\r
14595   {if (Sender.Brush.fHandle <> 0) and\r
14596      (Color2RGB( Sender.fBrush.fData.Color ) <> Sender.fBrush.fColorRGB) then\r
14597     DeleteObject( Sender.Brush.ReleaseHandle );}\r
14598   Result := Sender.Brush.Handle;\r
14599 end;\r
14600 //[END NormalGetCtlBrushHandle]\r
14602 {++}(*\r
14603 //[API CreateFontIndirect]\r
14604 function CreateFontIndirect(const p1: TLogFont): HFONT; stdcall;\r
14605 external gdi32 name 'CreateFontIndirectA';\r
14606 *){--}\r
14607 //[MakeXXXHandle FORWARD DECLARATIONS]\r
14608 function MakeFontHandle( Self_: PGraphicTool ): THandle; forward;\r
14609 function MakeBrushHandle( Self_: PGraphicTool ): THandle; forward;\r
14610 function MakePenHandle( Self_: PGraphicTool ): THandle; forward;\r
14611 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle; forward;\r
14612 //[END OF MakeXXXHandle FORWARD DECLARATIONS]\r
14614 //[FUNCTION NewBrush]\r
14615 {$IFDEF ASM_VERSION}\r
14616 function NewBrush: PGraphicTool;\r
14617 asm\r
14618         MOV      [Global_GetCtlBrushHandle], offset NormalGetCtlBrushHandle  \r
14619         CALL     _NewGraphicTool\r
14620         MOV      [EAX].TGraphicTool.fNewProc, offset[NewBrush]\r
14621         MOV      [EAX].TGraphicTool.fType, gttBrush\r
14622         MOV      [EAX].TGraphicTool.fMakeHandleProc, offset[MakeBrushHandle]\r
14623         MOV      [EAX].TGraphicTool.fData.Color, clBtnFace\r
14624 end;\r
14625 {$ELSE ASM_VERSION} //Pascal\r
14626 function NewBrush: PGraphicTool;\r
14627 begin\r
14628   Global_GetCtlBrushHandle := NormalGetCtlBrushHandle;\r
14629   Result := _NewGraphicTool;\r
14630   with Result {-}^{+} do\r
14631   begin\r
14632     fNewProc := @ NewBrush;\r
14633     fType := gttBrush;\r
14634     fMakeHandleProc := @ MakeBrushHandle;\r
14635     Result.fData.Color := clBtnFace;\r
14636     //Result.fData.Brush.Style := bsSolid;\r
14637   end;\r
14638 end;\r
14639 {$ENDIF ASM_VERSION}\r
14640 //[END NewBrush]\r
14642 const size_FontData = sizeof( Integer {fFontHeight} ) + sizeof( Integer {fFontWidth} ) +\r
14643                       sizeof( TFontPitch ) +  sizeof( TFontStyle ) +\r
14644                       sizeof( Integer {fFontOrientation} ) +\r
14645                       sizeof( Integer {fFontWeight} ) + sizeof( TFontCharset ) +\r
14646                       sizeof( TFontQuality );\r
14648 //[FUNCTION NewFont]\r
14649 {$IFDEF ASM_VERSION}\r
14650 function NewFont: PGraphicTool;\r
14651 const FontDtSz = sizeof( TGDIFont );\r
14652 asm\r
14653         CALL     _NewGraphicTool\r
14654         MOV      [EAX].TGraphicTool.fNewProc, offset[NewFont]\r
14655         MOV      [EAX].TGraphicTool.fType, gttFont\r
14656         MOV      [EAX].TGraphicTool.fMakeHandleProc, offset[MakeFontHandle]\r
14657         MOV      EDX, [DefFontColor]\r
14658         MOV      [EAX].TGraphicTool.fData.Color, EDX\r
14660         PUSH     EAX\r
14661         LEA      EDX, [EAX].TGraphicTool.fData.Font\r
14662         MOV      EAX, offset[ DefFont ]\r
14663         XOR      ECX, ECX\r
14664         MOV      CL, FontDtSz\r
14665         CALL     System.Move\r
14666         POP      EAX\r
14667 end;\r
14668 {$ELSE ASM_VERSION} //Pascal\r
14669 function NewFont: PGraphicTool;\r
14670 begin\r
14671   Result := _NewGraphicTool;\r
14672   with Result {-}^{+} do\r
14673   begin\r
14674     fNewProc := @ NewFont;\r
14675     fType := gttFont;\r
14676     fMakeHandleProc := @ MakeFontHandle;\r
14677     fData.Color := DefFontColor;\r
14678     Move( DefFont, fData.Font, Sizeof( TGDIFont ) );\r
14679   end;\r
14680 end;\r
14681 {$ENDIF ASM_VERSION}\r
14682 //[END NewFont]\r
14684 //[FUNCTION NewPen]\r
14685 {$IFDEF ASM_VERSION}\r
14686 function NewPen: PGraphicTool;\r
14687 asm\r
14688         CALL     _NewGraphicTool\r
14689         MOV      [EAX].TGraphicTool.fNewProc, offset[NewPen]\r
14690         MOV      [EAX].TGraphicTool.fType, gttPen\r
14691         MOV      [EAX].TGraphicTool.fMakeHandleProc, offset[MakePenHandle]\r
14692         MOV      [EAX].TGraphicTool.fData.Pen.Mode, pmCopy\r
14693 end;\r
14694 {$ELSE ASM_VERSION} //Pascal\r
14695 function NewPen: PGraphicTool;\r
14696 begin\r
14697   Result := _NewGraphicTool;\r
14698   with Result{-}^{+} do\r
14699   begin\r
14700     fNewProc := @ NewPen;\r
14701     fType := gttPen;\r
14702     fMakeHandleProc := @ MakePenHandle;\r
14703     fData.Pen.Mode := pmCopy;\r
14704   end;\r
14705 end;\r
14706 {$ENDIF ASM_VERSION}\r
14707 //[END NewPen]\r
14709 //+\r
14710 //[function Color2RGB]\r
14711 function Color2RGB( Color: TColor ): TColor;\r
14712 begin\r
14713   if Color < 0 then\r
14714     Result := GetSysColor(Color and $FF) else\r
14715     Result := Color;\r
14716 end;\r
14717 //[END Color2RGB]\r
14719 //[function ColorsMix]\r
14720 function ColorsMix( Color1, Color2: TColor ): TColor;\r
14721 {$IFDEF F_P}\r
14722 begin\r
14723   Result := ((Color2RGB( Color1 ) and $FEFEFE) shr 1) +\r
14724             ((Color2RGB( Color2 ) and $FEFEFE) shr 1);\r
14725 end;\r
14726 {$ELSE DELPHI}\r
14727 asm\r
14728    PUSH EDX\r
14729    CALL Color2Rgb\r
14730    XCHG EAX, [ESP]\r
14731    CALL Color2Rgb\r
14732    POP EDX\r
14733    AND EAX, 0FEFEFEh\r
14734    AND EDX, 0FEFEFEh\r
14735    SHR EAX, 1\r
14736    SHR EDX, 1\r
14737    ADD EAX, EDX\r
14738 end;\r
14739 {$ENDIF F_P/DELPHI}\r
14740 //[END ColorsMix]\r
14742 //[FUNCTION Color2RGBQuad]\r
14743 {$IFDEF ASM_VERSION}\r
14744 function Color2RGBQuad( Color: TColor ): TRGBQuad;\r
14745 asm\r
14746         CALL     Color2RGB\r
14747         // code by bart:\r
14748         xchg    ah,al                   // xxRRGGBB\r
14749         ror     eax,16                  // BBGGxxRR\r
14750         xchg    ah,al                   // BBGGRRxx\r
14751         shr     eax,8                   // 00BBGGRR\r
14752 end;\r
14753 {$ELSE ASM_VERSION} //Pascal\r
14754 function Color2RGBQuad( Color: TColor ): TRGBQuad;\r
14755 var C: Integer;\r
14756 begin\r
14757   C := Color2RGB( Color );\r
14758   C := ((C shr 16) and $FF)\r
14759     or ((C shl 16) and $FF0000)\r
14760     or (C and $FF00);\r
14761   Result := TRGBQuad( C );\r
14762 end;\r
14763 {$ENDIF ASM_VERSION}\r
14764 //[END Color2RGBQuad]\r
14766 //[FUNCTION Color2Color16]\r
14767 {$IFDEF ASM_VERSION}\r
14768 function Color2Color16( Color: TColor ): WORD;\r
14769 asm\r
14770   MOV  EDX, EAX\r
14771   SHR  EDX, 19\r
14772   AND  EDX, $1F\r
14773   MOV  ECX, EAX\r
14774   SHR  ECX, 5\r
14775   AND  ECX, $7E0;\r
14776   MOV  AH, AL\r
14777   AND  EAX, $F800\r
14778   OR   EAX, EDX\r
14779   OR   EAX, ECX\r
14780 end;\r
14781 {$ELSE ASM_VERSION}\r
14782 function Color2Color16( Color: TColor ): WORD;\r
14783 begin\r
14784   Color := Color2RGB( Color );\r
14785   Result := (Color shr 19) and $1F or\r
14786             (Color shr 5) and $7E0 or\r
14787             (Color shl 8) and $F800;\r
14788 end;\r
14789 {$ENDIF ASM_VERSION}\r
14790 //[END Color2Color16]\r
14792 { TGraphicTool }\r
14794 {$IFDEF ASM_VERSION}\r
14795 //[function TGraphicTool.Assign]\r
14796 function TGraphicTool.Assign(Value: PGraphicTool): PGraphicTool;\r
14797 const SzfData = sizeof( fData );\r
14798 asm     //        //\r
14799         TEST      EDX, EDX\r
14800         JNZ       @@1\r
14801         TEST      EAX, EAX\r
14802         JZ        @@0\r
14803         CALL      TObj.DoDestroy\r
14804         XOR       EAX, EAX\r
14805 @@0:    RET\r
14806 @@1:    PUSH      EDI\r
14807         MOV       EDI, EDX\r
14808         TEST      EAX, EAX\r
14809         JNZ       @@2\r
14810         XCHG      EAX, EDX\r
14811         CALL      dword ptr[EAX].TGraphicTool.fNewProc\r
14812 @@2:    CMP       EAX, EDI\r
14813         JE        @@exit\r
14814         PUSH      EBX\r
14815         XCHG      EBX, EAX\r
14817         MOV       ECX, [EBX].TGraphicTool.fHandle\r
14818         JECXZ     @@3\r
14819         CMP       ECX, [EDI].TGraphicTool.fHandle\r
14820         JE        @@exit1\r
14821 @@3:\r
14822         MOV       EAX, EBX\r
14823         CALL      TGraphicTool.Changed\r
14824         LEA       EDX, [EBX].TGraphicTool.fData\r
14825         LEA       EAX, [EDI].TGraphicTool.fData\r
14826         MOV       ECX, SzfData\r
14827         CALL      System.Move\r
14828         MOV       EAX, EBX\r
14829         CALL      TGraphicTool.Changed\r
14831 @@exit1:\r
14832         XCHG      EAX, EBX\r
14833         POP       EBX\r
14834 @@exit: POP       EDI\r
14835 end;\r
14836 {$ELSE ASM_VERSION}\r
14837 function TGraphicTool.Assign(Value: PGraphicTool): PGraphicTool;\r
14838 var _Self: PGraphicTool;\r
14839 begin\r
14840   Result := nil;\r
14841   if Value = nil then\r
14842   begin\r
14843     if @Self <> nil then\r
14844        DoDestroy;\r
14845     Exit;\r
14846   end;\r
14847   _Self := @Self;\r
14848   if _Self = nil then\r
14849     _Self := Value.fNewProc();\r
14850   Result := _Self;\r
14851   if _Self = Value then Exit; // to avoid infinite loop when assigning to itself\r
14852   if _Self.fHandle <> 0 then\r
14853      if Value.fHandle = _Self.fHandle then Exit;\r
14854   _Self.Changed; // to destroy handle if allocated and release it from the canvas (if any uses it)\r
14855   Assert( Value.fType = _Self.fType, 'Attempt to assign to different GDI tool type' );\r
14856   Move( Value.fData, _Self.fData, Sizeof( fData ) );\r
14857   _Self.Changed; // to inform owner control, that its tool (font, brush) changed\r
14858 end;\r
14859 {$ENDIF ASM_VERSION}\r
14861 //[procedure TGraphicTool.AssignHandle]\r
14862 procedure TGraphicTool.AssignHandle(NewHandle: Integer);\r
14863 begin\r
14864   //------------ by Yury Sidorov --------\r
14865   //Changed;\r
14866   //-------------------------------------//\r
14867   if fHandle <> 0 then                   //\r
14868     DeleteObject( fHandle );             //\r
14869   //-------------------------------------//\r
14870   fHandle := NewHandle;\r
14871   GetObject( fHandle, Sizeof( TGDIFont ), @ fData.Font );\r
14872   Changed;\r
14873 end;\r
14875 {$IFDEF ASM_VERSION}\r
14876 //[procedure TGraphicTool.Changed]\r
14877 procedure TGraphicTool.Changed;\r
14878 asm\r
14879         XOR      ECX, ECX\r
14880         XCHG     ECX, [EAX].fHandle\r
14881         JECXZ    @@exit\r
14882         PUSH     EAX\r
14883         PUSH     ECX\r
14885         CALL     @@CallOnChange\r
14887         CALL     DeleteObject\r
14888         POP      EAX\r
14889 @@exit:\r
14891 @@CallOnChange:\r
14892         MOV      ECX, [EAX].fOnChange.TMethod.Code\r
14893         JECXZ    @@no_onChange\r
14894         PUSH     EAX\r
14895         XCHG     EDX, EAX\r
14896         MOV      EAX, [EDX].fOnChange.TMethod.Data\r
14897         CALL     ECX\r
14898         POP      EAX\r
14899 @@no_onChange:\r
14900 end;\r
14901 {$ELSE ASM_VERSION} //Pascal\r
14902 procedure TGraphicTool.Changed;\r
14903 var H: THandle;\r
14904 begin\r
14905    if fHandle <> 0 then\r
14906    begin\r
14907      H := fHandle;\r
14908      fHandle := 0;\r
14909      ////////////////////////////////\r
14910      if Assigned( fOnChange ) then\r
14911         fOnChange( @Self );\r
14912      ////////////////////////////////\r
14913      DeleteObject( H );\r
14914       {$IFDEF DEBUG_GDIOBJECTS}\r
14915       case fType of\r
14916       gttBrush:  Dec( BrushCount );\r
14917       gttFont:   Dec( FontCount );\r
14918       gttPen:    Dec( PenCount );\r
14919       end;\r
14920       {$ENDIF}\r
14921    end;\r
14922    //////////////////////////////////\r
14923    if Assigned( fOnChange ) then\r
14924       fOnChange( @Self );\r
14925    //////////////////////////////////\r
14926 end;\r
14927 {$ENDIF ASM_VERSION}\r
14929 {$IFDEF ASM_VERSION}\r
14930 //[destructor TGraphicTool.Destroy]\r
14931 destructor TGraphicTool.Destroy;\r
14932 asm\r
14933           PUSH      EAX\r
14934           CMP       [EAX].fType, gttFont\r
14935           JE        @@0\r
14936           MOV       ECX, [EAX].fData.Brush.Bitmap\r
14937           JECXZ     @@0\r
14938           PUSH      ECX\r
14939           CALL      DeleteObject\r
14940           POP       EAX\r
14941           PUSH      EAX\r
14942 @@0:\r
14943         MOV       ECX, [EAX].fHandle\r
14944         JECXZ     @@1\r
14945         PUSH      ECX\r
14946         CALL      DeleteObject\r
14947 @@1:\r
14948           POP       EAX\r
14949           CALL      TObj.Destroy\r
14950 end;\r
14951 {$ELSE ASM_VERSION} //Pascal\r
14952 destructor TGraphicTool.Destroy;\r
14953 begin\r
14954   case fType of\r
14955   gttBrush: if fData.Brush.Bitmap <> 0 then\r
14956                DeleteObject( fData.Brush.Bitmap );\r
14957   gttPen:   if fData.Pen.BrushBitmap <> 0 then\r
14958                DeleteObject( fData.Pen.BrushBitmap )\r
14959   end;\r
14960   if fHandle <> 0 then\r
14961   begin\r
14962      DeleteObject( fHandle );\r
14963      {$IFDEF DEBUG_GDIOBJECTS}\r
14964      case fType of\r
14965      gttPen:    Dec( PenCount );\r
14966      gttBrush:  Dec( BrushCount );\r
14967      gttFont:   Dec( FontCount );\r
14968      end;\r
14969      {$ENDIF}\r
14970      //fHandle := 0; Why to do this? It is now destroying!\r
14971   end;\r
14972   inherited;\r
14973 end;\r
14974 {$ENDIF ASM_VERSION}\r
14976 //[function TGraphicTool.HandleAllocated]\r
14977 function TGraphicTool.HandleAllocated: Boolean;\r
14978 begin\r
14979   Result := fHandle <> 0;\r
14980 end;\r
14982 {$IFDEF ASM_VERSION}\r
14983 //[function TGraphicTool.ReleaseHandle]\r
14984 function TGraphicTool.ReleaseHandle: Integer;\r
14985 asm     //        //\r
14986         PUSH      EAX\r
14987         CALL      Changed\r
14988         POP       EDX\r
14989         XOR       EAX, EAX\r
14990         XCHG      [EDX].fHandle, EAX  \r
14991 end;\r
14992 {$ELSE ASM_VERSION PAS_VERSION}\r
14993 function TGraphicTool.ReleaseHandle: Integer;\r
14994 begin\r
14995   Changed;\r
14996   Result := fHandle;\r
14997   fHandle := 0;\r
14998 end;\r
14999 {$ENDIF ASM_VERSION}\r
15001 {$IFDEF ASM_VERSION}\r
15002 //[procedure TGraphicTool.SetInt]\r
15003 procedure TGraphicTool.SetInt( const Index: Integer; Value: Integer );\r
15004 asm\r
15005         LEA    EDX, [EDX+EAX].fData\r
15006         CMP    [EDX], ECX\r
15007         JE     @@exit\r
15008         MOV    [EDX], ECX\r
15009         CALL   Changed\r
15010 @@exit:\r
15011 end;\r
15012 {$ELSE ASM_VERSION} //Pascal\r
15013 procedure TGraphicTool.SetInt( const Index: Integer; Value: Integer );\r
15014 var Where: PInteger;\r
15015 begin\r
15016   Where := Pointer( Integer( @ fData ) + Index );\r
15017   if Where^ = Value then Exit;\r
15018   Where^ := Value;\r
15019   Changed;\r
15020 end;\r
15021 {$ENDIF ASM_VERSION}\r
15023 {$IFDEF F_P}\r
15024 //[function TGraphicTool.GetInt]\r
15025 function TGraphicTool.GetInt(const Index: Integer): Integer;\r
15026 var Where: PInteger;\r
15027 begin\r
15028   Where := Pointer( Integer( @ fData ) + Index );\r
15029   Result := Where^;\r
15030 end;\r
15031 {$ENDIF}\r
15033 //[procedure TGraphicTool.SetColor]\r
15034 procedure TGraphicTool.SetColor( Value: TColor );\r
15035 begin\r
15036   SetInt( go_Color, Value );\r
15037   fColorRGB := Color2RGB( Value );\r
15038 end;\r
15040 {$IFDEF ASM_VERSION}\r
15041 //[function TGraphicTool.IsFontTrueType]\r
15042 function TGraphicTool.IsFontTrueType: Boolean;\r
15043 asm\r
15044         CALL     GetHandle\r
15045         TEST     EAX, EAX\r
15046         JZ       @@exit\r
15048         PUSH     EBX\r
15050         PUSH     EAX                  // fHandle\r
15052         PUSH     0\r
15053         CALL     GetDC\r
15055         PUSH     EAX                  // DC\r
15056         MOV      EBX, EAX\r
15057         CALL     SelectObject\r
15058         PUSH     EAX\r
15060         XOR      ECX, ECX\r
15061         PUSH     ECX\r
15062         PUSH     ECX\r
15063         PUSH     ECX\r
15064         PUSH     ECX\r
15065         PUSH     EBX\r
15066         CALL     GetFontData\r
15068         XCHG     EAX, [ESP]\r
15070         PUSH     EAX\r
15071         PUSH     EBX\r
15072         CALL     SelectObject\r
15074         PUSH     EBX\r
15075         PUSH     0\r
15076         CALL     ReleaseDC\r
15078         POP      EAX\r
15079         INC      EAX\r
15080         SETNZ    AL\r
15082         POP      EBX\r
15083 @@exit:\r
15084 end;\r
15085 {$ELSE ASM_VERSION} //Pascal\r
15086 function TGraphicTool.IsFontTrueType: Boolean;\r
15087 var OldFont: HFont;\r
15088     DC: HDC;\r
15089 begin\r
15090   Result := False;\r
15091   if GetHandle = 0 then Exit;\r
15092   DC := GetDC( 0 );\r
15093   OldFont := SelectObject( DC, fHandle );\r
15094   if GetFontData( DC, 0, 0, nil, 0 ) <> GDI_ERROR then\r
15095      Result := True;\r
15096   SelectObject( DC, OldFont );\r
15097   ReleaseDC( 0, DC );\r
15098 end;\r
15099 {$ENDIF ASM_VERSION}\r
15101 //[procedure TGraphicTool.SetBrushBitmap]\r
15102 procedure TGraphicTool.SetBrushBitmap(const Value: HBitmap);\r
15103 begin\r
15104   if fData.Brush.Bitmap = Value then Exit;\r
15105   if fData.Brush.Bitmap <> 0 then\r
15106   begin\r
15107     ///////////\r
15108     Changed; // !!!\r
15109     ///////////\r
15110     DeleteObject( fData.Brush.Bitmap );\r
15111   end;\r
15112   fData.Brush.Bitmap := Value;\r
15113   Changed;\r
15114 end;\r
15116 //[procedure TGraphicTool.SetBrushStyle]\r
15117 procedure TGraphicTool.SetBrushStyle(const Value: TBrushStyle);\r
15118 begin\r
15119   if fData.Brush.Style = Value then Exit;\r
15120   fData.Brush.Style := Value;\r
15121   Changed;\r
15122 end;\r
15124 //[procedure TGraphicTool.SetFontCharset]\r
15125 procedure TGraphicTool.SetFontCharset(const Value: TFontCharset);\r
15126 begin\r
15127   if fData.Font.Charset = Value then Exit;\r
15128   fData.Font.Charset := Value;\r
15129   Changed;\r
15130 end;\r
15132 //[procedure TGraphicTool.SetFontQuality]\r
15133 procedure TGraphicTool.SetFontQuality(const Value: TFontQuality);\r
15134 begin\r
15135   if fData.Font.Quality = Value then Exit;\r
15136   fData.Font.Quality := Value;\r
15137   Changed;\r
15138 end;\r
15140 //[function TGraphicTool.GetFontName]\r
15141 function TGraphicTool.GetFontName: String;\r
15142 begin\r
15143   Result := fData.Font.Name;\r
15144 end;\r
15146 //[procedure TGraphicTool.SetFontName]\r
15147 procedure TGraphicTool.SetFontName(const Value: String);\r
15148 begin\r
15149   if fData.Font.Name = Value then Exit;\r
15150   FillChar( fData.Font.Name[ 0 ], LF_FACESIZE, 0 );\r
15151   StrLCopy( fData.Font.Name, PChar( Value ), LF_FACESIZE );\r
15152   Changed;\r
15153 end;\r
15155 {$IFDEF ASM_VERSION}\r
15156 //[procedure TextAreaEx]\r
15157 procedure TextAreaEx( Sender: PCanvas; var Sz : TSize; var Pt : TPoint );\r
15158 asm\r
15159         PUSH     EBX\r
15160         PUSH     ESI\r
15161         PUSH     EDI\r
15162         PUSH     EBP\r
15163         MOV      EBP, ESP\r
15164         PUSH     EDX // [EBP-4] = @Sz\r
15165         PUSH     ECX // [EBP-8] = @Pt\r
15166         MOV      EBX, EAX\r
15167         CALL     TCanvas.GetFont\r
15168         MOV      ESI, [EAX].TGraphicTool.fData.Font.Orientation\r
15169         CALL     TGraphicTool.IsFontTrueType\r
15170         TEST     AL, AL\r
15171         JZ       @@exit\r
15173         MOV      EDI, [EBP-8]\r
15174         XOR      EAX, EAX\r
15175         STOSD\r
15176         STOSD\r
15177         TEST     ESI, ESI\r
15178         JZ       @@exit\r
15180         PUSH     EAX // Pts[1].x\r
15181         PUSH     EAX // Pts[1].y\r
15183         PUSH     ESI\r
15184         FILD     dword ptr [ESP]\r
15185         POP      EDX\r
15187         FILD     word ptr [@@1800]\r
15188         FDIV\r
15189         //FWAIT\r
15190         FLDPI\r
15191         FMUL\r
15192         //FWAIT\r
15194         FLD      ST(0)\r
15195         FSINCOS\r
15196         FWAIT\r
15198         MOV      ESI, [EBP-4]\r
15199         LODSD         // Sz.cx\r
15200         PUSH     EAX\r
15201         FILD     dword ptr [ESP]\r
15202         FMUL\r
15203         FISTP    dword ptr [ESP] // Pts[2].x\r
15204         FWAIT\r
15205         NEG      EAX\r
15206         PUSH     EAX\r
15207         FILD     dword ptr [ESP]\r
15208         FMUL\r
15209         FISTP    dword ptr [ESP] // Pts[2].y\r
15210         FWAIT\r
15212         FLDPI\r
15213         FLD1\r
15214         FLD1\r
15215         FADD\r
15216         FDIV\r
15217         FADD\r
15218         FSINCOS\r
15219         FWAIT\r
15221         LODSD\r
15222         NEG      EAX\r
15223         PUSH     EAX\r
15224         FILD     dword ptr [ESP]\r
15225         FMUL\r
15226         FISTP    dword ptr [ESP] // Pts[4].x\r
15227         FWAIT\r
15228         NEG      EAX\r
15229         PUSH     EAX\r
15230         FILD     dword ptr [ESP]\r
15231         FMUL\r
15232         FISTP    dword ptr [ESP] // Pts[4].y\r
15233         FWAIT\r
15235         POP      ECX\r
15236         POP      EDX\r
15237         PUSH     EDX\r
15238         PUSH     ECX\r
15239         ADD      EDX, [ESP+12]\r
15240         ADD      ECX, [ESP+8]\r
15241         PUSH     EDX\r
15242         PUSH     ECX\r
15244         MOV      ESI, ESP\r
15245         XOR      EDX, EDX // MinX\r
15246         XOR      EDI, EDI // MinY\r
15247         XOR      ECX, ECX\r
15248         MOV      CL, 3\r
15250 @@loo1: LODSD\r
15251         CMP      EAX, EDI\r
15252         JGE      @@1\r
15253         XCHG     EDI, EAX\r
15254 @@1:    LODSD\r
15255         CMP      EAX, EDX\r
15256         JGE      @@2\r
15257         XCHG     EDX, EAX\r
15258 @@2:    LOOP     @@loo1\r
15260         MOV      ESI, [EBP-4]\r
15261         MOV      [ESI], ECX\r
15262         MOV      [ESI+4], ECX\r
15263         MOV      CL, 4\r
15264 @@loo2:\r
15265         POP      EBX\r
15266         SUB      EBX, EDI\r
15267         CMP      EBX, [ESI+4]\r
15268         JLE      @@3\r
15269         MOV      [ESI+4], EBX\r
15270 @@3:\r
15271         POP      EAX\r
15272         SUB      EAX, EDX\r
15273         CMP      EAX, [ESI]\r
15274         JLE      @@4\r
15275         MOV      [ESI], EAX\r
15276 @@4:\r
15277         LOOP     @@loo2\r
15279         MOV      EDI, [EBP-8]\r
15280         STOSD\r
15281         XCHG     EAX, EBX\r
15282         STOSD\r
15283         JMP      @@exit\r
15285 @@1800: DW  1800\r
15287 @@exit:\r
15288         MOV      ESP, EBP\r
15289         POP      EBP\r
15290         POP      EDI\r
15291         POP      ESI\r
15292         POP      EBX\r
15293 end;\r
15294 {$ELSE ASM_VERSION} //Pascal\r
15295 procedure TextAreaEx( Sender: PCanvas; var Sz : TSize; var Pt : TPoint );\r
15296 var Orient : Integer;\r
15297     Pts : array[ 1..4 ] of TPoint;\r
15298     MinX, MinY, I : Integer;\r
15299     A : Double;\r
15300 begin\r
15301    if not Sender.Font.IsFontTrueType then Exit;\r
15302    Orient := Sender.Font.FontOrientation;\r
15303    Pt.x := 0; Pt.y := 0;\r
15304    if Orient = 0 then\r
15305       Exit;\r
15306    A := Orient / 1800.0 * PI;\r
15307    Pts[ 1 ] := Pt;\r
15308    Pts[ 2 ].x := Round( Sz.cx * cos( A ) );\r
15309    Pts[ 2 ].y := - Round( Sz.cx * sin( A ) );\r
15310    Pts[ 4 ].x := - Round( Sz.cy * cos( A + PI / 2 ) );\r
15311    Pts[ 4 ].y := Round( Sz.cy * sin( A + PI / 2 ) );\r
15312    Pts[ 3 ].x := Pts[ 2 ].x + Pts[ 4 ].x;\r
15313    Pts[ 3 ].y := Pts[ 2 ].y + Pts[ 4 ].y;\r
15314    MinX := 0; MinY := 0;\r
15315    for I := 2 to 4 do\r
15316    begin\r
15317       if Pts[ I ].x < MinX then\r
15318          MinX := Pts[ I ].x;\r
15319       if Pts[ I ].y < MinY then\r
15320          MinY := Pts[ I ].y;\r
15321    end;\r
15322    Sz.cx := 0;\r
15323    Sz.cy := 0;\r
15324    for I := 1 to 4 do\r
15325    begin\r
15326       Pts[ I ].x := Pts[ I ].x - MinX;\r
15327       Pts[ I ].y := Pts[ I ].y - MinY;\r
15328       if Pts[ I ].x > Sz.cx then\r
15329          Sz.cx := Pts[ I ].x;\r
15330       if Pts[ I ].y > Sz.cy then\r
15331          Sz.cy := Pts[ I ].y;\r
15332    end;\r
15333    Pt := Pts[ 1 ];\r
15334 end;\r
15335 {$ENDIF ASM_VERSION}\r
15337 {$IFDEF ASM_VERSION}\r
15338 //[procedure TGraphicTool.SetFontOrientation]\r
15339 procedure TGraphicTool.SetFontOrientation(Value: Integer);\r
15340 asm\r
15341         PUSH     EAX\r
15342 @@1:    MOV      EAX, EDX\r
15343         MOV      ECX, 3600\r
15344         CDQ\r
15345         IDIV     ECX     // EDX = Value mod 3600\r
15346         POP      EAX\r
15348         MOV      byte ptr [GlobalGraphics_UseFontOrient], 1\r
15349         MOV      [GlobalCanvas_OnTextArea], offset[TextAreaEx]\r
15351         MOV      [EAX].fData.Font.Escapement, EDX\r
15352         MOV      ECX, EDX\r
15353         MOV      DX, go_FontOrientation\r
15354         CALL     SetInt\r
15355 end;\r
15356 {$ELSE ASM_VERSION} //Pascal\r
15357 procedure TGraphicTool.SetFontOrientation(Value: Integer);\r
15358 begin\r
15359   GlobalGraphics_UseFontOrient := True;\r
15360   GlobalCanvas_OnTextArea := TextAreaEx;\r
15361   Value := Value mod 3600; // -3599..+3599\r
15362   SetInt( go_FontOrientation, Value );\r
15363   SetInt( go_FontEscapement, Value );\r
15364 end;\r
15365 {$ENDIF ASM_VERSION}\r
15367 //[procedure TGraphicTool.SetFontPitch]\r
15368 procedure TGraphicTool.SetFontPitch(const Value: TFontPitch);\r
15369 begin\r
15370   if fData.Font.Pitch = Value then Exit;\r
15371   fData.Font.Pitch := Value;\r
15372   Changed;\r
15373 end;\r
15375 {$IFDEF ASM_VERSION}\r
15376 //[function TGraphicTool.GetFontStyle]\r
15377 function TGraphicTool.GetFontStyle: TFontStyle;\r
15378 asm\r
15379        MOV   EDX, dword ptr [EAX].fData.Font.Italic\r
15380        AND   EDX, $010101\r
15381        MOV   EAX, [EAX].fData.Font.Weight\r
15382        CMP   EAX, 700\r
15383        SETGE AL       //AL:1 = fsBold\r
15384        ADD   EDX, EDX\r
15385        OR    EAX, EDX //AL:2 = fsItalic\r
15386        SHR   EDX, 7\r
15387        OR    EAX, EDX //AL:3 = fsUnderline\r
15388        SHR   EDX, 7\r
15389        OR    EAX, EDX //AL:4 = fsStrikeOut\r
15390 end;\r
15391 {$ELSE ASM_VERSION} //Pascal\r
15392 function TGraphicTool.GetFontStyle: TFontStyle;\r
15393 type PFontStyle = ^TFontStyle;\r
15394 begin\r
15395   Result := [ ];\r
15396   if fData.Font.Weight >= 700 then Result := [ fsBold ];\r
15397   if fData.Font.Italic        then Result := Result + [ fsItalic ];\r
15398   if fData.Font.Underline     then Result := Result + [ fsUnderline ];\r
15399   if fData.Font.StrikeOut     then Result := Result + [ fsStrikeOut ];\r
15400 end;\r
15401 {$ENDIF ASM_VERSION}\r
15403 {$IFDEF ASM_VERSION}\r
15404 //[procedure TGraphicTool.SetFontStyle]\r
15405 procedure TGraphicTool.SetFontStyle(const Value: TFontStyle);\r
15406 asm\r
15407         PUSH     EDI\r
15408         MOV      EDI, EAX\r
15409         PUSH     EDX\r
15410         CALL     GetFontStyle\r
15411         POP      EDX\r
15412         CMP      AL, DL\r
15413         JE       @@exit\r
15414         PUSH     EDI\r
15416         LEA      EDI, [EDI].fData.Font.Weight\r
15417         MOV      ECX, [EDI]\r
15418         SHR      EDX, 1\r
15419         JNC      @@1\r
15420         CMP      ECX, 700\r
15421         JGE      @@2\r
15422         MOV      ECX, 700\r
15423         JMP      @@2\r
15424 @@1:    CMP      ECX, 700\r
15425         JL       @@2\r
15426         XOR      ECX, ECX\r
15427 @@2:    XCHG     EAX, ECX\r
15428         STOSD    // change Weight\r
15429         SHR      EDX, 1\r
15430         SETC     AL\r
15431         STOSB    // change Italic\r
15432         SHR      EDX, 1\r
15433         SETC     AL\r
15434         STOSB    // change Underline\r
15435         SHR      EDX, 1\r
15436         SETC     AL\r
15437         STOSB    // change StrikeOut\r
15438         POP      EAX\r
15439         CALL     Changed\r
15440 @@exit: POP      EDI\r
15441 end;\r
15442 {$ELSE ASM_VERSION} //Pascal\r
15443 procedure TGraphicTool.SetFontStyle(const Value: TFontStyle);\r
15444 begin\r
15445   if FontStyle = Value then Exit;\r
15446   if fsBold in Value then\r
15447   begin\r
15448     if fData.Font.Weight < 700 then\r
15449       fData.Font.Weight := 700;\r
15450   end\r
15451     else\r
15452   begin\r
15453     if fData.Font.Weight >= 700 then\r
15454       fData.Font.Weight := 0;\r
15455   end;\r
15456   fData.Font.Italic := fsItalic in Value;\r
15457   fData.Font.Underline := fsUnderline in Value;\r
15458   fData.Font.StrikeOut := fsStrikeOut in Value;\r
15459   Changed;\r
15460 end;\r
15461 {$ENDIF ASM_VERSION}\r
15463 //[procedure TGraphicTool.SetPenMode]\r
15464 procedure TGraphicTool.SetPenMode(const Value: TPenMode);\r
15465 begin\r
15466   if fData.Pen.Mode = Value then Exit;\r
15467   fData.Pen.Mode := Value;\r
15468   Changed;\r
15469 end;\r
15471 //[procedure TGraphicTool.SetPenStyle]\r
15472 procedure TGraphicTool.SetPenStyle(const Value: TPenStyle);\r
15473 begin\r
15474   if fData.Pen.Style = Value then Exit;\r
15475   fData.Pen.Style := Value;\r
15476   Changed;\r
15477 end;\r
15479 {$IFDEF ASM_VERSION}\r
15480 //[function TGraphicTool.GetHandle]\r
15481 function TGraphicTool.GetHandle: THandle;\r
15482 const DataSz = sizeof( TGDIToolData );\r
15483 asm\r
15484         PUSH      EBX\r
15485 @@start:\r
15486         XCHG      EBX, EAX\r
15487         MOV       ECX, [EBX].fHandle\r
15488         JECXZ     @@1\r
15490         MOV       EAX, [EBX].fData.Color\r
15491         CALL      Color2RGB\r
15492         CMP       EAX, [EBX].fColorRGB\r
15493         JE        @@1\r
15495         MOV       EAX, EBX\r
15496         CALL      ReleaseHandle\r
15497         PUSH      EAX\r
15498         CALL      DeleteObject\r
15500 @@1:    MOV       ECX, [EBX].fHandle\r
15501         INC       ECX\r
15502         LOOP      @@exit\r
15504         MOV       ECX, [EBX].fParentGDITool\r
15505         JECXZ     @@2\r
15506         LEA       EDX, [ECX].fData\r
15507         LEA       EAX, [EBX].fData\r
15508         MOV       ECX, DataSz\r
15509         CALL      CompareMem\r
15510         TEST      AL, AL\r
15511         MOV       EAX, [EBX].fParentGDITool\r
15512         JNZ       @@start\r
15514 @@2:    MOV       ECX, [EBX].fHandle\r
15515         INC       ECX\r
15516         LOOP      @@exit\r
15518         MOV       EAX, [EBX].fData.Color\r
15519         CALL      Color2RGB\r
15520         MOV       [EBX].fColorRGB, EAX\r
15521         XCHG      EAX, EBX\r
15522         CALL      dword ptr [EAX].fMakeHandleProc\r
15523         XCHG      ECX, EAX\r
15525 @@exit: XCHG      EAX, ECX\r
15526         POP       EBX\r
15527 end;\r
15528 {$ELSE ASM_VERSION} //Pascal\r
15529 function TGraphicTool.GetHandle: THandle;\r
15530 begin\r
15531   Result := fHandle;\r
15532   if Result <> 0 then\r
15533   begin\r
15534     if Color2RGB( fData.Color ) <> fColorRGB then\r
15535     begin\r
15536       DeleteObject( ReleaseHandle );\r
15537       Result := 0;\r
15538     end;\r
15539   end;\r
15540   if Result = 0 then\r
15541   begin\r
15542     if Assigned( fParentGDITool ) then\r
15543     begin\r
15544       if CompareMem( @ fData, @ fParentGDITool.fData, Sizeof( fData ) ) then\r
15545       begin\r
15546         Result := fParentGDITool.Handle;\r
15547         Exit;\r
15548       end;\r
15549     end;\r
15551     if fHandle = 0 then\r
15552     begin\r
15553       fColorRGB := Color2RGB( fData.Color );\r
15554       fMakeHandleProc( @Self );\r
15555     end;\r
15556     Result := fHandle;\r
15557   end;\r
15558 end;\r
15559 {$ENDIF ASM_VERSION}\r
15561 //[FUNCTION MakeBrushHandle]\r
15562 {$IFDEF ASM_VERSION}\r
15563 function MakeBrushHandle( Self_: PGraphicTool ): THandle;\r
15564 asm\r
15565         PUSH     EBX\r
15566         XCHG     EBX, EAX\r
15567         MOV      EAX, [EBX].TGraphicTool.fHandle\r
15568         TEST     EAX, EAX\r
15569         JNZ      @@exit\r
15571         MOV      EAX, [EBX].TGraphicTool.fData.Color\r
15572         CALL     Color2RGB   // EAX = ColorRef\r
15574         XOR      EDX, EDX\r
15576         MOV      ECX, [EBX].TGraphicTool.fData.Brush.Bitmap\r
15577         PUSH     ECX\r
15578         JECXZ    @@1\r
15580         MOV      DL, BS_PATTERN\r
15581         JMP      @@2\r
15583 @@1:\r
15584         MOV      CL, [EBX].TGraphicTool.fData.Brush.Style\r
15585         MOV      DL, CL\r
15586         SUB      CL, 2\r
15587         JL       @@2\r
15589         XCHG     ECX, [ESP]\r
15591 @@2:    PUSH     EAX\r
15592         PUSH     EDX\r
15594         PUSH     ESP\r
15595         CALL     CreateBrushIndirect\r
15596         MOV      [EBX].TGraphicTool.fHandle, EAX\r
15598         ADD      ESP, 12\r
15600 @@exit:\r
15601         POP      EBX\r
15602 end;\r
15603 {$ELSE ASM_VERSION} //Pascal\r
15604 function MakeBrushHandle( Self_: PGraphicTool ): THandle;\r
15605 var\r
15606   LogBrush: TLogBrush;\r
15607 begin\r
15608   if Self_.fHandle = 0 then\r
15609   begin\r
15610    LogBrush.lbColor := Color2RGB( Self_.fData.Color );\r
15611    if Self_.fData.Brush.Bitmap <> 0 then\r
15612    begin\r
15613      LogBrush.lbStyle := BS_PATTERN;\r
15614      LogBrush.lbHatch := Self_.fData.Brush.Bitmap;\r
15615    end\r
15616       else\r
15617    begin\r
15618      LogBrush.lbHatch := 0;\r
15619      case Self_.fData.Brush.Style of\r
15620        bsSolid: LogBrush.lbStyle := BS_SOLID;\r
15621        bsClear: LogBrush.lbStyle := BS_NULL;\r
15622      else\r
15623        LogBrush.lbStyle := BS_HATCHED;\r
15624        LogBrush.lbHatch := Ord( Self_.fData.Brush.Style ) - Ord( bsHorizontal );\r
15625        LogBrush.lbColor := Color2RGB( Self_.fData.Brush.LineColor );\r
15626      end;\r
15627    end;\r
15628    Self_.fHandle := CreateBrushIndirect(LogBrush);\r
15629    {$IFDEF DEBUG_GDIOBJECTS}\r
15630    if Self_.fHandle <> 0 then\r
15631      Inc( BrushCount )\r
15632    else\r
15633      ShowMessage( 'Could not create brush, error ' + Int2Str( GetLastError ) +\r
15634                   ': ' + SysErrorMessage( GetLastError ) );\r
15635    {$ENDIF}\r
15636   end;\r
15637   //GlobalGraphics_OnObjectCreated( @Self );\r
15638   Result := Self_.fHandle;\r
15639 end;\r
15640 {$ENDIF ASM_VERSION}\r
15641 //[END MakeBrushHandle]\r
15643 //[FUNCTION MakeFontHandle]\r
15644 {$IFDEF ASM_VERSION}\r
15645 function MakeFontHandle( Self_: PGraphicTool ): THandle;\r
15646 asm\r
15647          XCHG   EDX, EAX\r
15648          MOV    EAX, [EDX].TGraphicTool.fHandle\r
15649          TEST   EAX, EAX\r
15650          JNZ    @@exit\r
15651          PUSH   EDX\r
15652          LEA    ECX, [EDX].TGraphicTool.fData.Font\r
15653          PUSH   ECX\r
15654          CALL   CreateFontIndirect\r
15655          POP    EDX\r
15656          MOV    [EDX].TGraphicTool.fHandle, EAX\r
15657 @@exit:\r
15658 end;\r
15659 {$ELSE ASM_VERSION} //Pascal\r
15660 function MakeFontHandle( Self_: PGraphicTool ): THandle;\r
15661 //var LogFont: TLogFont;\r
15662 begin\r
15663   with Self_{-}^{+} do\r
15664   begin\r
15665     if fHandle = 0 then\r
15666     begin\r
15667       fHandle := CreateFontIndirect( PLogFont( @ fData.Font )^ );\r
15668       {$IFDEF DEBUG_GDIOBJECTS}\r
15669       Inc( FontCount );\r
15670       {$ENDIF}\r
15671     end;\r
15672     Result := fHandle;\r
15673   end;\r
15674 end;\r
15675 {$ENDIF ASM_VERSION}\r
15676 //[END MakeFontHandle]\r
15678 //[FUNCTION MakePenHandle]\r
15679 {$IFDEF ASM_VERSION}\r
15680 function MakePenHandle( Self_: PGraphicTool ): THandle;\r
15681 asm\r
15682         PUSH     EBX\r
15683         MOV      EBX, EAX\r
15685         MOV      EAX, [EBX].TGraphicTool.fHandle\r
15686         TEST     EAX, EAX\r
15687         JNZ      @@exit\r
15689         MOV      EAX, [EBX].TGraphicTool.fData.Color\r
15690         CALL     Color2RGB\r
15691         PUSH     EAX\r
15692         PUSH     EAX\r
15693         PUSH     [EBX].TGraphicTool.fData.Pen.Width\r
15694         MOVZX    EAX, [EBX].TGraphicTool.fData.Pen.Style\r
15695         PUSH     EAX\r
15696         PUSH     ESP\r
15697         CALL     CreatePenIndirect\r
15698         MOV      [EBX].TGraphicTool.fHandle, EAX\r
15699         ADD      ESP, 16\r
15700 @@exit:\r
15701         POP      EBX\r
15702 end;\r
15703 {$ELSE ASM_VERSION} //Pascal\r
15704 function MakePenHandle( Self_: PGraphicTool ): THandle;\r
15705 var\r
15706   LogPen: TLogPen;\r
15707 begin\r
15708   with Self_{-}^{+} do\r
15709   begin\r
15710     //GlobalGraphics_OnObjectCreating( @Self );\r
15711     if fHandle = 0 then\r
15712     with LogPen do\r
15713     begin\r
15714       lopnStyle := Byte( fData.Pen.Style );\r
15715       lopnWidth.X := fData.Pen.Width;\r
15716       lopnColor := Color2RGB( fData.Color );\r
15717       fHandle := CreatePenIndirect( LogPen );\r
15718       {$IFDEF DEBUG_GDIOBJECTS}\r
15719       Inc( PenCount );\r
15720       {$ENDIF}\r
15721     end;\r
15722     //GlobalGraphics_OnObjectCreated( @Self );\r
15723     Result := fHandle;\r
15724   end;\r
15725 end;\r
15726 {$ENDIF ASM_VERSION}\r
15727 //[END MakePenHandle]\r
15729 //+\r
15730 //[procedure TGraphicTool.SetGeometricPen]\r
15731 procedure TGraphicTool.SetGeometricPen(const Value: Boolean);\r
15732 begin\r
15733   if fData.Pen.Geometric = Value then Exit;\r
15734   fData.Pen.Geometric := Value;\r
15735   fMakeHandleProc := MakeGeometricPenHandle;\r
15736   Changed;\r
15737 end;\r
15739 //[procedure TGraphicTool.SetPenEndCap]\r
15740 procedure TGraphicTool.SetPenEndCap(const Value: TPenEndCap);\r
15741 begin\r
15742   if fData.Pen.EndCap = Value then Exit;\r
15743   fData.Pen.EndCap := Value;\r
15744   Changed;\r
15745 end;\r
15747 //[procedure TGraphicTool.SetPenJoin]\r
15748 procedure TGraphicTool.SetPenJoin(const Value: TPenJoin);\r
15749 begin\r
15750   if fData.Pen.Join = Value then Exit;\r
15751   fData.Pen.Join := Value;\r
15752   Changed;\r
15753 end;\r
15755 //[FUNCTION MakeGeometricPenHandle]\r
15756 {$IFDEF ASM_VERSION}\r
15757 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle;\r
15758 asm\r
15759         MOV      ECX, [EAX].TGraphicTool.fHandle\r
15760         INC      ECX\r
15761         LOOP     @@exit\r
15763         PUSH     EBX\r
15764         XCHG     EBX, EAX\r
15765         MOV      EAX, [EBX].TGraphicTool.fData.Color\r
15766         CALL     Color2RGB // EAX = Color2RGB( fColor )\r
15767         CDQ                // EDX = lbHatch (0)\r
15768         MOV      ECX, [EBX].TGraphicTool.fData.Pen.BrushBitmap\r
15769         JECXZ    @@no_brush_bitmap\r
15771         XCHG     EDX, ECX // lbHatch = fPenBrushBitmap\r
15772         MOV      CL, BS_PATTERN // = 3\r
15773         JMP      @@create_pen\r
15775 @@no_brush_bitmap:\r
15776         MOVZX    ECX, [EBX].TGraphicTool.fData.Pen.BrushStyle\r
15777         CMP      CL, 1\r
15778         JLE      @@create_pen\r
15779         MOV      EDX, ECX\r
15780         MOV      CL, 2\r
15781         SUB      EDX, ECX\r
15783 @@create_pen:\r
15784         PUSH     EDX\r
15785         PUSH     EAX\r
15786         PUSH     ECX\r
15787         MOV      ECX, ESP\r
15789         CDQ\r
15790         PUSH     EDX\r
15791         PUSH     EDX\r
15792         PUSH     ECX\r
15793         PUSH     [EBX].TGraphicTool.fData.Pen.Width\r
15794         MOVZX    ECX, [EBX].TGraphicTool.fData.Pen.Join\r
15795         SHL      ECX, 12\r
15796         MOVZX    EDX, [EBX].TGraphicTool.fData.Pen.EndCap\r
15797         SHL      EDX, 8\r
15798         OR       EDX, ECX\r
15799         OR       DL, byte ptr [EBX].TGraphicTool.fData.Pen.Style\r
15800         OR       EDX, PS_GEOMETRIC\r
15801         PUSH     EDX\r
15802         CALL     ExtCreatePen\r
15804         POP      ECX\r
15805         POP      ECX\r
15806         POP      ECX\r
15808         MOV      [EBX].TGraphicTool.fHandle, EAX\r
15809         POP      EBX\r
15810         RET\r
15811 @@exit:\r
15812         XCHG     EAX, ECX\r
15813 end;\r
15814 {$ELSE ASM_VERSION} //Pascal\r
15815 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle;\r
15816 const\r
15817   PenStyles: array[ TPenStyle ] of Word =\r
15818     (PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL,\r
15819      PS_INSIDEFRAME);\r
15820   PenEndCapStyles: array[ TPenEndCap ] of Word =\r
15821     (PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT);\r
15822   PenJoinStyles: array[ TPenJoin ] of Word =\r
15823     (PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER );\r
15824 var\r
15825   LogBrush: TLogBrush;\r
15826 begin\r
15827   if Self_.fHandle = 0 then\r
15828   with Self_{-}^{+}, LogBrush do\r
15829   begin\r
15830       lbColor := Color2RGB( fData.Color );\r
15831       lbHatch := 0;\r
15832       if fData.Pen.BrushBitmap <> 0 then\r
15833       begin\r
15834         lbStyle := BS_PATTERN;\r
15835         lbHatch := fData.Pen.BrushBitmap;\r
15836       end\r
15837          else\r
15838       case fData.Pen.BrushStyle of\r
15839       bsSolid: lbStyle := BS_SOLID;\r
15840       bsClear: lbStyle := BS_NULL;\r
15841       else  begin\r
15842                lbStyle := BS_HATCHED;\r
15843                case fData.Pen.BrushStyle of\r
15844                bsHorizontal: lbHatch := HS_HORIZONTAL;\r
15845                bsVertical:   lbHatch := HS_VERTICAL;\r
15846                bsFDiagonal:  lbHatch := HS_FDIAGONAL;\r
15847                bsBDiagonal:  lbHatch := HS_BDIAGONAL;\r
15848                bsCross:      lbHatch := HS_CROSS;\r
15849                bsDiagCross:  lbHatch := HS_DIAGCROSS;\r
15850                end;\r
15851             end;\r
15852       end;\r
15853   end;\r
15854   Self_.fHandle := ExtCreatePen( PS_GEOMETRIC or Byte( Self_.fData.Pen.Style ) or\r
15855                            PenEndCapStyles[ Self_.fData.Pen.EndCap ] or\r
15856                            PenJoinStyles[ Self_.fData.Pen.Join ],\r
15857              Self_.fData.Pen.Width, LogBrush, 0, nil );\r
15858   {Assert( Self_.fHandle <> 0, 'Error ' + Int2Str( GetLastError ) +\r
15859                               ': ' + SysErrorMessage( GetLastError ) );}\r
15860   {$IFDEF DEBUG_GDIOBJECTS}\r
15861   Inc( PenCount );\r
15862   {$ENDIF}\r
15863   Result := Self_.fHandle;\r
15864 end;\r
15865 {$ENDIF ASM_VERSION}\r
15866 //[END MakeGeometricPenHandle]\r
15868 //[procedure TGraphicTool.SetFontWeight]\r
15869 procedure TGraphicTool.SetFontWeight(const Value: Integer);\r
15870 begin\r
15871   if fData.Font.Weight = Value then Exit;\r
15872   fData.Font.Weight := Value;\r
15873   Changed;\r
15874 end;\r
15876 //[procedure TGraphicTool.SetLogFontStruct]\r
15877 procedure TGraphicTool.SetLogFontStruct(const Value: TLogFont);\r
15878 begin\r
15879   if  CompareMem(@fData.Font, @Value, SizeOf(TLogFont)) then Exit;\r
15880   Move(Value, fData.Font, SizeOF(TLogFont));\r
15881   Changed;\r
15882 end;\r
15884 //[function TGraphicTool.GetLogFontStruct]\r
15885 function TGraphicTool.GetLogFontStruct: TLogFont;\r
15886 begin\r
15887   Move(fData.Font, Result, SizeOf(TLogFont));\r
15888 end;\r
15901 { TCanvas }\r
15903 type\r
15904   TStock = Packed Record\r
15905     StockPen: HPEN;\r
15906     StockBrush: HBRUSH;\r
15907     StockFont: HFONT;\r
15908   end;\r
15910 var\r
15911   Stock: TStock;\r
15913 //[destructor TCanvas.Destroy]\r
15914 destructor TCanvas.Destroy;\r
15915 begin\r
15916   Handle := 0;\r
15917   fPen.Free;\r
15918   fBrush.Free;\r
15919   fFont.Free;\r
15920   //if Assigned( GlobalCanvas_OnDestroyCanvas ) then\r
15921   //   GlobalCanvas_OnDestroyCanvas( Self );\r
15922   inherited;\r
15923 end;\r
15925 {$IFDEF ASM_VERSION}\r
15926 //[function TCanvas.Assign]\r
15927 function TCanvas.Assign(SrcCanvas: PCanvas): Boolean;\r
15928 asm\r
15929         PUSH     EBX\r
15930         PUSH     ESI\r
15931         XCHG     EBX, EAX\r
15932         MOV      ESI, EDX\r
15934         MOV      EAX, [EBX].fFont\r
15935         MOV      EDX, [ESI].fFont\r
15936         CALL     TGraphicTool.Assign\r
15937         MOV      [EBX].fFont, EAX\r
15939         MOV      EAX, [EBX].fBrush\r
15940         MOV      EDX, [ESI].fBrush\r
15941         CALL     TGraphicTool.Assign\r
15942         MOV      [EBX].fBrush, EAX\r
15944         MOV      EAX, [EBX].fPen\r
15945         MOV      EDX, [ESI].fPen\r
15946         CALL     TGraphicTool.Assign\r
15947         MOV      [EBX].fPen, EAX\r
15949         CALL     AssignChangeEvents\r
15951         MOV      ECX, [EBX].fFont\r
15952         OR       ECX, [EBX].fBrush\r
15953         OR       ECX, [EBX].fPen\r
15954         SETNZ    AL\r
15956         MOV      EDX, [ESI].fPenPos.x\r
15957         MOV      ECX, [ESI].fPenPos.y\r
15958         CMP      EDX, [EBX].fPenPos.x\r
15959         JNE      @@chg_penpos\r
15960         CMP      ECX, [EBX].fPenPos.y\r
15961         JE       @@1\r
15962 @@chg_penpos:\r
15963         MOV      AL, 1\r
15964         MOV      [EBX].fPenPos.x, EDX\r
15965         MOV      [EBX].fPenPos.y, ECX\r
15966 @@1:\r
15967         MOV       EDX, [ESI].fCopyMode\r
15968         CMP       EDX, [EBX].fCopyMode\r
15969         JE        @@2\r
15970         MOV       [EBX].fCopyMode, EDX\r
15971         MOV       AL, 1\r
15972 @@2:\r
15973         POP       ESI\r
15974         POP       EBX\r
15975 end;\r
15976 {$ELSE ASM_VERSION} //Pascal\r
15977 function TCanvas.Assign(SrcCanvas: PCanvas): Boolean;\r
15978 begin\r
15979   fFont := fFont.Assign( SrcCanvas.fFont );\r
15980   fBrush := fBrush.Assign( SrcCanvas.fBrush );\r
15981   fPen := fPen.Assign( SrcCanvas.fPen );\r
15982   AssignChangeEvents;\r
15983   Result := (fFont <> nil) or (fBrush <> nil) or (fPen <> nil);\r
15984   if (SrcCanvas.PenPos.x <> PenPos.x) or (SrcCanvas.PenPos.y <> PenPos.y) then\r
15985   begin\r
15986      Result := True;\r
15987      PenPos := SrcCanvas.PenPos;\r
15988   end;\r
15989   if SrcCanvas.ModeCopy <> ModeCopy then\r
15990   begin\r
15991      Result := True;\r
15992      ModeCopy := SrcCanvas.ModeCopy;\r
15993   end;\r
15994 end;\r
15995 {$ENDIF ASM_VERSION}\r
15997 {$IFDEF ASM_VERSION}\r
15998 //[procedure TCanvas.CreateBrush]\r
15999 procedure TCanvas.CreateBrush;\r
16000 asm\r
16001         PUSH     EBX\r
16002         MOV      EBX, EAX\r
16004         MOV      ECX, [EAX].fBrush\r
16005         JECXZ    @@chk_owner\r
16007         MOV      EAX, ECX\r
16008         CALL     TGraphicTool.GetHandle\r
16009         PUSH     EAX\r
16011         MOV      EAX, EBX\r
16012         CALL     AssignChangeEvents\r
16014         MOV      EAX, EBX\r
16015         CALL     TCanvas.GetHandle\r
16016         PUSH     EAX\r
16018         CALL     SelectObject\r
16020         MOV      EDX, [EBX].TCanvas.fBrush\r
16021         CMP      [EDX].TGraphicTool.fData.Brush.Style, bsSolid\r
16023         MOV      EAX, [EDX].TGraphicTool.fData.Color\r
16024 @@0:\r
16025         MOV      EBX, [EBX].TCanvas.fHandle\r
16026         MOV      ECX, offset[Color2RGB]\r
16027         JNZ      @@1\r
16029         PUSH     OPAQUE\r
16030         PUSH     EBX\r
16032         CALL     ECX //Color2RGB\r
16033         PUSH     EAX\r
16034         PUSH     EBX\r
16035         JMP      @@2\r
16036 @@1:\r
16037         PUSH     TRANSPARENT\r
16038         PUSH     EBX\r
16040         CALL     ECX //Color2RGB\r
16041         NOT      EAX\r
16042         PUSH     EAX\r
16043         PUSH     EBX\r
16044 @@2:\r
16045         CALL     SetBkColor\r
16046         CALL     SetBkMode\r
16047 @@exit:\r
16048         POP      EBX\r
16049         RET\r
16051 @@chk_owner:\r
16052         MOV      ECX, [EBX].fOwnerControl\r
16053         JECXZ    @@exit\r
16055         MOV      EAX, [ECX].TControl.fColor\r
16056         XOR      ECX, ECX\r
16057         JMP      @@0\r
16058 end;\r
16059 {$ELSE ASM_VERSION} //Pascal\r
16060 procedure TCanvas.CreateBrush;\r
16061 begin\r
16062   //UnrealizeObject( Brush.Handle );\r
16063   // if GdiObject parameter of UnrealizeObject is brush handle,\r
16064   // this call does nothing (from Win32.hlp)\r
16066   if assigned( fBrush ) then\r
16067   begin\r
16068     SelectObject( GetHandle, fBrush.Handle );\r
16069     //fBrush.fOnChange := ObjectChanged;\r
16070     AssignChangeEvents;\r
16071     if fBrush.fData.Brush.Style = bsSolid then\r
16072     begin\r
16073       SetBkColor( fHandle, Color2RGB( fBrush.fData.Color ) );\r
16074       SetBkMode( fHandle, OPAQUE );\r
16075     end\r
16076        else\r
16077     begin\r
16078       { Win95 doesn't draw brush hatches if bkcolor = brush color }\r
16079       { Since bkmode is transparent, nothing should use bkcolor anyway }\r
16080       SetBkColor( fHandle, not Color2RGB( fBrush.fData.Color ) );\r
16081       SetBkMode( fHandle, TRANSPARENT );\r
16082     end;\r
16083   end\r
16084      else\r
16085   if Assigned( fOwnerControl ) then\r
16086   begin\r
16087     SetBkColor( GetHandle, Color2RGB( PControl( fOwnerControl ).fColor ) );\r
16088     SetBkMode( fHandle, OPAQUE );\r
16089   end;\r
16090 end;\r
16091 {$ENDIF ASM_VERSION}\r
16093 {$IFDEF ASM_VERSION}\r
16094 //[procedure TCanvas.CreateFont]\r
16095 procedure TCanvas.CreateFont;\r
16096 asm\r
16097         PUSH     EBX\r
16098         MOV      EBX, EAX\r
16100         MOV      ECX, [EAX].TCanvas.fFont\r
16101         JECXZ    @@chk_owner\r
16103         MOV      EAX, [ECX].TGraphicTool.fData.Color\r
16104         PUSH     ECX\r
16105         CALL     Color2RGB\r
16106         XCHG     EAX, [ESP]\r
16108         CALL     TGraphicTool.GetHandle\r
16109         PUSH     EAX\r
16111         MOV      EAX, EBX\r
16112         CALL     AssignChangeEvents;\r
16114         MOV      EAX, EBX\r
16115         CALL     TCanvas.GetHandle\r
16116         PUSH     EAX\r
16117         MOV      EBX, EAX\r
16119         CALL     SelectObject\r
16121 @@set_txcolor:\r
16122         PUSH     EBX\r
16123         CALL     SetTextColor\r
16125 @@exit:\r
16126         POP      EBX\r
16127         RET\r
16129 @@chk_owner:\r
16130         MOV      ECX, [EBX].fOwnerControl\r
16131         JECXZ    @@exit\r
16133         MOV      EBX, [EBX].fHandle\r
16134         MOV      EAX, [ECX].TControl.fTextColor\r
16135         CALL     Color2RGB\r
16136         PUSH     EAX\r
16137         JMP      @@set_txcolor\r
16138 end;\r
16139 {$ELSE ASM_VERSION} //Pascal\r
16140 procedure TCanvas.CreateFont;\r
16141 begin\r
16142   if assigned( fFont ) then\r
16143   begin\r
16144     SelectObject( GetHandle, fFont.Handle );\r
16145     SetTextColor( fHandle, Color2RGB( fFont.fData.Color ) );\r
16146     //fFont.fOnChange := ObjectChanged;\r
16147     AssignChangeEvents;\r
16148   end\r
16149      else\r
16150   if Assigned( fOwnerControl ) then\r
16151   begin\r
16152     SetTextColor( fHandle, Color2RGB( PControl( fOwnerControl ).fTextColor ) );\r
16153   end;\r
16154 end;\r
16155 {$ENDIF ASM_VERSION}\r
16157 {$IFDEF ASM_VERSION}\r
16158 //[procedure TCanvas.CreatePen]\r
16159 procedure TCanvas.CreatePen;\r
16160 asm\r
16161         MOV      ECX, [EAX].TCanvas.fPen\r
16162         JECXZ    @@exit\r
16164         PUSH     EBX\r
16165         MOV      EBX, EAX\r
16167         MOV      DL, [ECX].TGraphicTool.fData.Pen.Mode\r
16168         MOVZX    EDX, DL\r
16169         INC      EDX\r
16170         PUSH     EDX\r
16172         MOV      EAX, ECX\r
16173         CALL     TGraphicTool.GetHandle\r
16174         PUSH     EAX\r
16176         MOV      EAX, EBX\r
16177         CALL     AssignChangeEvents\r
16179         MOV      EAX, EBX\r
16180         CALL     TCanvas.GetHandle\r
16181         PUSH     EAX\r
16182         MOV      EBX, EAX\r
16184         CALL     SelectObject\r
16185         PUSH     EBX\r
16186         CALL     SetROP2\r
16188         POP      EBX\r
16189 @@exit:\r
16190 end;\r
16191 {$ELSE ASM_VERSION} //Pascal\r
16192 procedure TCanvas.CreatePen;\r
16193 begin\r
16194   if assigned( fPen ) then\r
16195   begin\r
16196     SelectObject( GetHandle, fPen.Handle );\r
16197     SetROP2( fHandle, Ord( fPen.fData.Pen.Mode ) + 1 );\r
16198     //fPen.fOnChange := ObjectChanged;\r
16199     AssignChangeEvents;\r
16200   end;\r
16201 end;\r
16202 {$ENDIF ASM_VERSION}\r
16204 //[function TCanvas.GetPixels]\r
16205 function TCanvas.GetPixels(X, Y: Integer): TColor;\r
16206 begin\r
16207   RequiredState( HandleValid );\r
16208   Result := Windows.GetPixel(FHandle, X, Y);\r
16209 end;\r
16211 //[procedure TCanvas.SetPixels]\r
16212 procedure TCanvas.SetPixels(X, Y: Integer; const Value: TColor);\r
16213 begin\r
16214   Changing;\r
16215   RequiredState( HandleValid );\r
16216   Windows.SetPixel(FHandle, X, Y, Color2RGB( Value ));\r
16217 end;\r
16219 {$IFDEF ASM_VERSION}\r
16220 //[procedure TCanvas.DeselectHandles]\r
16221 procedure TCanvas.DeselectHandles;\r
16222 asm\r
16223         PUSH     EBX\r
16224         PUSH     ESI\r
16225         PUSH     EDI\r
16226         LEA      EBX, [EAX].TCanvas.fState\r
16227         //CALL     TCanvas.GetHandle\r
16228         MOV      EAX, [EAX].TCanvas.fHandle\r
16229         TEST     EAX, EAX\r
16230         JZ       @@exit\r
16232         MOVZX    EDX, byte ptr[EBX]\r
16233         AND      DL, PenValid or BrushValid or FontValid\r
16234         JZ       @@exit\r
16236         PUSH     EAX\r
16237         LEA      EDI, [Stock]\r
16239         MOV      ECX, [EDI]\r
16240         INC      ECX\r
16241         LOOP     @@1\r
16243         MOV      ESI, offset[ GetStockObject ]\r
16245         PUSH     BLACK_PEN\r
16246         CALL     ESI\r
16247         STOSD\r
16249         PUSH     HOLLOW_BRUSH\r
16250         CALL     ESI\r
16251         STOSD\r
16253         PUSH     SYSTEM_FONT\r
16254         CALL     ESI\r
16255         STOSD\r
16257 @@1:\r
16258         LEA      ESI, [Stock]\r
16259         POP      EDX\r
16261         LODSD\r
16262         PUSH     EAX\r
16263         PUSH     EDX\r
16265         LODSD\r
16266         PUSH     EAX\r
16267         PUSH     EDX\r
16269         LODSD\r
16270         PUSH     EAX\r
16271         PUSH     EDX\r
16273         MOV      ESI, offset[ SelectObject ]\r
16274         CALL     ESI\r
16275         CALL     ESI\r
16276         CALL     ESI\r
16278         AND      byte ptr [EBX], not( PenValid or BrushValid or FontValid )\r
16279 @@exit:\r
16280         POP      EDI\r
16281         POP      ESI\r
16282         POP      EBX\r
16283 end;\r
16284 {$ELSE ASM_VERSION} //Pascal\r
16285 procedure TCanvas.DeselectHandles;\r
16286 begin\r
16287    //if (GetHandle <> 0) and\r
16288    if (fHandle <> 0) and\r
16289       LongBool(fState and (PenValid or BrushValid or FontValid)) then\r
16290    with Stock do\r
16291    begin\r
16292      if StockPen = 0 then\r
16293      begin\r
16294        StockPen := GetStockObject(BLACK_PEN);\r
16295        StockBrush := GetStockObject(HOLLOW_BRUSH);\r
16296        StockFont := GetStockObject(SYSTEM_FONT);\r
16297      end;\r
16298      SelectObject( fHandle, StockPen );\r
16299      SelectObject( fHandle, StockBrush );\r
16300      SelectObject( fHandle, StockFont );\r
16301      fState := fState and not( PenValid or BrushValid or FontValid );\r
16302    end;\r
16303 end;\r
16304 {$ENDIF ASM_VERSION}\r
16306 {$IFDEF ASM_VERSION}\r
16307 //[function TCanvas.RequiredState]\r
16308 function TCanvas.RequiredState(ReqState: DWORD): Integer; stdcall;\r
16309 asm\r
16310         PUSH     EBX\r
16311         PUSH     ESI\r
16312         MOV      EBX, ReqState\r
16313         MOV      ESI, [EBP+8] //Self\r
16314         MOV      EAX, ESI\r
16315         TEST     BL, ChangingCanvas\r
16316         JZ       @@1\r
16317         CALL     Changing\r
16318 @@1:    AND      BL, 0Fh\r
16320         TEST     BL, HandleValid\r
16321         JZ       @@2\r
16322         CALL     TCanvas.GetHandle\r
16323         TEST     EAX, EAX\r
16324         JZ       @@ret_0\r
16325 @@2:\r
16326         MOV      AL, [ESI].TCanvas.fState\r
16327         NOT      EAX\r
16328         AND      BL, AL\r
16329         JZ       @@ret_handle\r
16331         TEST     BL, FontValid\r
16332         JZ       @@3\r
16333         MOV      EAX, ESI\r
16334         CALL     CreateFont\r
16335 @@3:    TEST     BL, PenValid\r
16336         JZ       @@5\r
16337         MOV      EAX, ESI\r
16338         CALL     CreatePen\r
16339         MOV      ECX, [ESI].TCanvas.fPen\r
16340         JCXZ     @@5\r
16341         MOV      AL, [ECX].TGraphicTool.fData.Pen.Style\r
16342         DEC      AL\r
16343         {$IFDEF PARANOIA}\r
16344         DB $2C, 3\r
16345         {$ELSE}\r
16346         SUB      AL, 3\r
16347         {$ENDIF}\r
16348         JB       @@6\r
16349 @@5:    TEST     BL, BrushValid\r
16350         JZ       @@7\r
16351 @@6:    MOV      EAX, ESI\r
16352         CALL     CreateBrush\r
16353 @@7:    OR       [ESI].TCanvas.fState, BL\r
16354 @@ret_handle:\r
16355         MOV      EAX, [ESI].TCanvas.fHandle\r
16356 @@ret_0:\r
16357         POP      ESI\r
16358         POP      EBX\r
16359 end;\r
16360 {$ELSE ASM_VERSION} //Pascal\r
16361 function TCanvas.RequiredState(ReqState: DWORD): Integer; stdcall;\r
16362 var\r
16363   NeededState: Byte;\r
16364 begin\r
16365   if Boolean(ReqState and ChangingCanvas) then\r
16366      Changing;\r
16367   ReqState := ReqState and 15;\r
16368   NeededState := Byte( ReqState ) and not fState;\r
16369   Result := 0;\r
16370     if Boolean(ReqState and HandleValid) then\r
16371     begin\r
16372       if GetHandle = 0 then Exit;\r
16373       // Important!\r
16374     end;\r
16375   if NeededState <> 0 then\r
16376   begin\r
16377     if Boolean( NeededState and FontValid ) then\r
16378        CreateFont;\r
16379     if Boolean( NeededState and PenValid ) then\r
16380     begin\r
16381       CreatePen;\r
16382       if assigned( fPen ) then\r
16383       if fPen.fData.Pen.Style in [psDash, psDot, psDashDot, psDashDotDot] then\r
16384         NeededState := NeededState or BrushValid;\r
16385     end;\r
16386     if Boolean( NeededState and BrushValid ) then\r
16387        CreateBrush;\r
16388     fState := fState or NeededState;\r
16389   end;\r
16390   Result := fHandle;\r
16391 end;\r
16392 {$ENDIF ASM_VERSION}\r
16394 {$IFDEF ASM_VERSION}\r
16395 //[procedure TCanvas.SetHandle]\r
16396 procedure TCanvas.SetHandle(Value: HDC);\r
16397 asm\r
16398         PUSH     EBX\r
16399         MOV      EBX, EAX\r
16400         MOV      ECX, [EBX].fHandle\r
16401         CMP      ECX, EDX\r
16402         JZ       @@exit\r
16403         JECXZ    @@chk_val\r
16405         PUSH     EDX\r
16406         PUSH     ECX\r
16407           CALL     DeselectHandles\r
16408         POP      EDX\r
16410         MOV      ECX, [EBX].fOwnerControl\r
16411         JECXZ    @@chk_Release\r
16412         CMP      [ECX].TControl.fPaintDC, EDX\r
16413         JE       @@clr_Handle\r
16415 @@chk_Release:\r
16416         PUSH     EDX\r
16417         CMP      [EBX].fOnGetHandle.TMethod.Code, offset[TControl.DC2Canvas]\r
16418         JNE      @@deldc\r
16419         PUSH     [ECX].TControl.fHandle\r
16420         CALL     ReleaseDC\r
16421         JMP      @@clr_Handle\r
16422 @@deldc:\r
16423         CALL     DeleteDC\r
16425 @@clr_Handle:\r
16426         XOR      ECX, ECX\r
16427         MOV      [EBX].TCanvas.fHandle, ECX\r
16428         MOV      [EBX].TCanvas.fIsPaintDC, CL\r
16429         AND      [EBX].TCanvas.fState, not HandleValid\r
16431         POP      EDX\r
16432 @@chk_val:\r
16433         TEST     EDX, EDX\r
16434         JZ       @@exit\r
16436         OR       [EBX].TCanvas.fState, HandleValid\r
16437         MOV      [EBX].TCanvas.fHandle, EDX\r
16438         LEA      EDX, [EBX].TCanvas.fPenPos\r
16439         MOV      EAX, EBX\r
16440         CALL     SetPenPos\r
16442 @@exit: POP      EBX\r
16443 end;\r
16444 {$ELSE ASM_VERSION} //Pascal\r
16445 procedure TCanvas.SetHandle(Value: HDC);\r
16446 {$IFDEF F_P}\r
16447 var Ptr1: Pointer;\r
16448 {$ENDIF F_P}\r
16449 begin\r
16450   if fHandle = Value then Exit;\r
16451   if fHandle <> 0 then\r
16452   begin\r
16453     DeselectHandles;\r
16454     {if not fIsPaintDC and\r
16455        not( assigned(fOwnerControl) and\r
16456             PControl(fOwnerControl).fDoubleBuffered )\r
16457        then}\r
16458       if not( assigned(fOwnerControl) and\r
16459               (PControl(fOwnerControl).fPaintDC = fHandle) ) then\r
16460       begin\r
16461         {$IFDEF F_P}\r
16462         Ptr1 := Self;\r
16463         asm\r
16464           MOV  EAX, [Ptr1]\r
16465           MOV  EAX, [EAX].TCanvas.fOnGetHandle\r
16466           MOV  [Ptr1], EAX\r
16467         end [ 'EAX' ];\r
16468         if Ptr1 = @ TControl.DC2Canvas then\r
16469         {$ELSE DELPHI}\r
16470       //////////////////// SLAG\r
16471         if   TMethod(fOnGetHandle).Code =\r
16472              @TControl.Dc2Canvas then\r
16473         {$ENDIF F_P/DELPHI}\r
16474              ReleaseDC(PControl(fOwnerControl).Handle, fHandle )\r
16475         else\r
16476              DeleteDC( fHandle );\r
16477       ////////////////////\r
16478       end;\r
16479     fHandle := 0;\r
16480     fIsPaintDC := False;\r
16481     fState := fState and not HandleValid;\r
16482   end;\r
16483   if Value <> 0 then\r
16484   begin\r
16485     fState := fState or HandleValid;\r
16486     fHandle := Value;\r
16487     SetPenPos( fPenPos );\r
16488   end;\r
16489 end;\r
16490 {$ENDIF ASM_VERSION}\r
16492 {$IFDEF ASM_VERSION}\r
16493 //[procedure TCanvas.SetPenPos]\r
16494 procedure TCanvas.SetPenPos(const Value: TPoint);\r
16495 asm\r
16496           MOV     ECX, [EDX].TPoint.y\r
16497           MOV     EDX, [EDX].TPoint.x\r
16498           MOV     [EAX].fPenPos.x, EDX\r
16499           MOV     [EAX].fPenPos.y, ECX\r
16500           CALL    MoveTo\r
16501 end;\r
16502 {$ELSE ASM_VERSION} //Pascal\r
16503 procedure TCanvas.SetPenPos(const Value: TPoint);\r
16504 begin\r
16505   fPenPos := Value;\r
16506   MoveTo( Value.x, Value.y );\r
16507 end;\r
16508 {$ENDIF ASM_VERSION}\r
16510 {$IFDEF ASM_VERSION}\r
16511 //[procedure TCanvas.Changing]\r
16512 procedure TCanvas.Changing;\r
16513 asm\r
16514         PUSHAD\r
16515         MOV      ECX, [EAX].fOnChange.TMethod.Code\r
16516         JECXZ    @@exit\r
16517         XCHG     EDX, EAX\r
16518         MOV      EAX, [EDX].fOnChange.TMethod.Data\r
16519         CALL     ECX\r
16520 @@exit:\r
16521         POPAD\r
16522 end;\r
16523 {$ELSE ASM_VERSION} //Pascal\r
16524 procedure TCanvas.Changing;\r
16525 begin\r
16526   if Assigned( fOnChange ) then\r
16527      fOnChange( @Self );\r
16528 end;\r
16529 {$ENDIF ASM_VERSION}\r
16531 {$IFDEF ASM_VERSION}\r
16532 //[procedure TCanvas.Arc]\r
16533 procedure TCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;\r
16534 asm\r
16535         PUSH     ESI\r
16537         PUSH     HandleValid or PenValid or ChangingCanvas\r
16538         PUSH     dword ptr [EBP+8]\r
16539         CALL     RequiredState\r
16541         MOV      EDX, EAX\r
16543         LEA      ESI, [Y4]\r
16544         STD\r
16546         XOR      ECX, ECX\r
16547         MOV      CL, 8\r
16548 @@1:\r
16549         LODSD\r
16550         PUSH     EAX\r
16552         LOOP     @@1\r
16554         CLD\r
16555         PUSH     EDX  //Canvas.fHandle\r
16556         CALL     Windows.Arc\r
16557         POP      ESI\r
16558 end;\r
16559 {$ELSE ASM_VERSION} //Pascal\r
16560 procedure TCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;\r
16561 begin\r
16562   RequiredState( HandleValid or PenValid or ChangingCanvas );\r
16563   Windows.Arc(FHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);\r
16564 end;\r
16565 {$ENDIF ASM_VERSION}\r
16567 {$IFDEF ASM_VERSION}\r
16568 //[procedure TCanvas.Chord]\r
16569 procedure TCanvas.Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;\r
16570 asm\r
16571         PUSH     HandleValid or PenValid or BrushValid or ChangingCanvas\r
16572         PUSH     dword ptr [EBP + 8]\r
16573         CALL     RequiredState\r
16575         MOV      EDX, EAX\r
16577         PUSH     ESI\r
16578         LEA      ESI, [Y4]\r
16579         STD\r
16581         XOR      ECX, ECX\r
16582         MOV      CL, 8\r
16583 @@1:\r
16584         LODSD\r
16585         PUSH     EAX\r
16587         LOOP     @@1\r
16589         CLD\r
16590         PUSH     EDX  //Canvas.fHandle\r
16591         CALL     Windows.Chord\r
16592         POP      ESI\r
16593 end;\r
16594 {$ELSE ASM_VERSION} //Pascal\r
16595 procedure TCanvas.Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;\r
16596 begin\r
16597   RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );\r
16598   Windows.Chord(FHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);\r
16599 end;\r
16600 {$ENDIF ASM_VERSION}\r
16602 {$IFDEF ASM_VERSION}\r
16603 //[procedure TCanvas.CopyRect]\r
16604 procedure TCanvas.CopyRect(const DstRect: TRect; SrcCanvas: PCanvas;\r
16605   const SrcRect: TRect);\r
16606 asm\r
16607         PUSH     ESI\r
16608         PUSH     EDI\r
16610         PUSH     [EAX].fCopyMode\r
16612         PUSH     EDX\r
16614           PUSH     HandleValid or BrushValid\r
16615           PUSH     ECX\r
16617           PUSH     HandleValid or FontValid or BrushValid or ChangingCanvas\r
16618           PUSH     EAX\r
16619           MOV      ESI, offset[ RequiredState ]\r
16620           CALL     ESI\r
16621           MOV      EDI, EAX     // EDI = @Self.fHandle\r
16623           CALL     ESI\r
16624           MOV      EDX, EAX     // EDX = SrcCanvas.fHandle\r
16626         POP      ECX          // ECX = @DstRect\r
16628         MOV      ESI, [SrcRect]\r
16630         MOV      EAX, [ESI].TRect.Bottom\r
16631         SUB      EAX, [ESI].TRect.Top\r
16632         PUSH     EAX\r
16634         MOV      EAX, [ESI].TRect.Right\r
16635         SUB      EAX, [ESI].TRect.Left\r
16636         PUSH     EAX\r
16638         PUSH     [ESI].TRect.Top\r
16640         LODSD\r
16641         PUSH     EAX\r
16643         PUSH     EDX\r
16645         MOV      EAX, [ECX].TRect.Bottom\r
16646         MOV      EDX, [ECX].TRect.Top\r
16647         SUB      EAX, EDX\r
16648         PUSH     EAX\r
16650         MOV      EAX, [ECX].TRect.Right\r
16651         MOV      ESI, [ECX].TRect.Left\r
16652         SUB      EAX, ESI\r
16653         PUSH     EAX\r
16655         PUSH     EDX\r
16657         PUSH     ESI\r
16659         PUSH     EDI\r
16661         CALL     StretchBlt\r
16663         POP      EDI\r
16664         POP      ESI\r
16665 end;\r
16666 {$ELSE ASM_VERSION} //Pascal\r
16667 procedure TCanvas.CopyRect(const DstRect: TRect; SrcCanvas: PCanvas;\r
16668   const SrcRect: TRect);\r
16669 begin\r
16670   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
16671   SrcCanvas.RequiredState( HandleValid or BrushValid );\r
16672   StretchBlt( fHandle, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left,\r
16673     DstRect.Bottom - DstRect.Top, SrcCanvas.Handle, SrcRect.Left, SrcRect.Top,\r
16674     SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top, ModeCopy);\r
16675 end;\r
16676 {$ENDIF ASM_VERSION}\r
16678 {$IFDEF ASM_VERSION}\r
16679 //[procedure TCanvas.DrawFocusRect]\r
16680 procedure TCanvas.DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);\r
16681 asm\r
16682         PUSH     EDX\r
16684         PUSH     HandleValid or BrushValid or FontValid or ChangingCanvas\r
16685         PUSH     EAX\r
16686         CALL     RequiredState\r
16688         PUSH     EAX\r
16689         CALL     Windows.DrawFocusRect\r
16690 end;\r
16691 {$ELSE ASM_VERSION} //Pascal\r
16692 procedure TCanvas.DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);\r
16693 begin\r
16694   RequiredState( HandleValid or BrushValid or FontValid or ChangingCanvas );\r
16695   Windows.DrawFocusRect(FHandle, Rect);\r
16696 end;\r
16697 {$ENDIF ASM_VERSION}\r
16699 {$IFDEF ASM_VERSION}\r
16700 //[procedure TCanvas.Ellipse]\r
16701 procedure TCanvas.Ellipse(X1, Y1, X2, Y2: Integer);\r
16702 asm\r
16703         PUSH     [Y2]\r
16704         PUSH     [X2]\r
16705         PUSH     ECX\r
16706         PUSH     EDX\r
16708         PUSH     HandleValid or PenValid or BrushValid or ChangingCanvas\r
16709         PUSH     EAX\r
16710         CALL     RequiredState\r
16712         PUSH     EAX\r
16713         CALL     Windows.Ellipse\r
16714 end;\r
16715 {$ELSE ASM_VERSION} //Pascal\r
16716 procedure TCanvas.Ellipse(X1, Y1, X2, Y2: Integer);\r
16717 begin\r
16718   RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );\r
16719   Windows.Ellipse(FHandle, X1, Y1, X2, Y2);\r
16720 end;\r
16721 {$ENDIF ASM_VERSION}\r
16723 {$IFDEF ASM_VERSION}\r
16724 //[procedure TCanvas.FillRect]\r
16725 procedure TCanvas.FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);\r
16726 asm\r
16727         PUSH     EBX\r
16728         XCHG     EBX, EAX\r
16729         PUSH     EDX\r
16730         PUSH     HandleValid or BrushValid or ChangingCanvas\r
16731         PUSH     EBX\r
16732         CALL     RequiredState\r
16733         MOV      ECX, [EBX].fBrush\r
16734         JECXZ    @@chk_ctl\r
16736 @@fill_with_Brush:\r
16737         XCHG     EAX, ECX\r
16738         CALL     TGraphicTool.GetHandle\r
16739         POP      EDX\r
16740         PUSH     EAX\r
16741         JMP      @@fin\r
16742 @@chk_ctl:\r
16743         MOV      ECX, [EBX].fOwnerControl\r
16744         JECXZ    @@dflt_fill\r
16745         XCHG     EAX, ECX\r
16746         MOV      ECX, [EAX].TControl.fBrush\r
16747         INC      ECX\r
16748         LOOP     @@fill_with_Brush\r
16749         MOV      EAX, [EAX].TControl.fColor\r
16750         CALL     Color2RGB\r
16751         PUSH     EAX\r
16752         CALL     CreateSolidBrush\r
16753         POP      EDX\r
16754         PUSH     EAX\r
16755         PUSH     EAX\r
16756         PUSH     EDX\r
16757         PUSH     [EBX].fHandle\r
16758         CALL     Windows.FillRect\r
16759         CALL     DeleteObject\r
16760         POP      EBX\r
16761         RET\r
16762 @@dflt_fill:\r
16763         POP      EDX\r
16764         PUSH     COLOR_WINDOW + 1\r
16765 @@fin:\r
16766         PUSH     EDX\r
16767         PUSH     [EBX].fHandle\r
16768         CALL     Windows.FillRect\r
16769         POP      EBX\r
16770 end;\r
16771 {$ELSE ASM_VERSION} //Pascal\r
16772 procedure TCanvas.FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);\r
16773 var Br: HBrush;\r
16774 begin\r
16775   RequiredState( HandleValid or BrushValid or ChangingCanvas );\r
16776   if assigned( fBrush ) then\r
16777   begin\r
16778     Windows.FillRect(fHandle, Rect, fBrush.Handle);\r
16779   end\r
16780     else\r
16781   if assigned( fOwnerControl ) then\r
16782   begin\r
16783     if assigned( PControl( fOwnerControl ).fBrush ) then\r
16784       Windows.FillRect( fHandle, Rect, PControl( fOwnerControl ).fBrush.Handle )\r
16785     else\r
16786     begin\r
16787       Br := CreateSolidBrush( Color2RGB(PControl(fOwnerControl).fColor) );\r
16788       Windows.FillRect(fHandle, Rect, Br );\r
16789       DeleteObject( Br );\r
16790     end;\r
16791   end\r
16792   else\r
16793   begin\r
16794     Windows.FillRect(fHandle, Rect, HBrush(COLOR_WINDOW + 1) );\r
16795   end;\r
16796 end;\r
16797 {$ENDIF ASM_VERSION}\r
16799 {$IFDEF ASM_VERSION}\r
16800 //[procedure TCanvas.FillRgn]\r
16801 procedure TCanvas.FillRgn(const Rgn: HRgn);\r
16802 asm\r
16803         PUSH     EBX\r
16804         XCHG     EBX, EAX\r
16805         PUSH     EDX\r
16807         PUSH     HandleValid or BrushValid or ChangingCanvas\r
16808         PUSH     EBX\r
16809         CALL     RequiredState\r
16811         MOV      ECX, [EBX].TCanvas.fBrush\r
16812         JECXZ    @@1\r
16814         //PUSH     [ECX].TGraphicTool.fData.Color\r
16815         //JMP      @@cr_br\r
16817 @@fill_rgn_using_Brush:\r
16818         XCHG     EAX, ECX\r
16819         CALL     TGraphicTool.GetHandle\r
16820         POP      EDX\r
16821         PUSH     EAX\r
16822         PUSH     EDX\r
16823         PUSH     [EBX].fHandle\r
16824         CALL     Windows.FillRgn\r
16825         JMP      @@fin\r
16827 @@1:    MOV      ECX, [EBX].TCanvas.fOwnerControl\r
16828         MOV      EAX, -1 // clWhite\r
16829         JECXZ    @@2\r
16831         XCHG     EAX, ECX\r
16832         MOV      ECX, [EAX].TControl.fBrush\r
16833         INC      ECX\r
16834         LOOP     @@fill_rgn_using_Brush\r
16836         MOV      EAX, [EAX].TControl.fColor\r
16837 @@2:\r
16838         CALL     Color2RGB\r
16839         PUSH     EAX\r
16840         CALL     CreateSolidBrush // EAX = Br\r
16842         POP      EDX // Rgn\r
16844         PUSH     EAX //-------------------//\r
16845         PUSH     EAX           // Br\r
16846         PUSH     EDX           // Rgn\r
16847         PUSH     [EBX].FHandle // fHandle\r
16848         CALL     Windows.FillRgn\r
16850         CALL     DeleteObject\r
16852 @@fin:\r
16853         POP      EBX\r
16854 end;\r
16855 {$ELSE ASM_VERSION} //Pascal\r
16856 procedure TCanvas.FillRgn(const Rgn: HRgn);\r
16857 var Br : HBrush;\r
16858 begin\r
16859   RequiredState( HandleValid or BrushValid or ChangingCanvas );\r
16860   if assigned( fBrush ) then\r
16861     Windows.FillRgn(FHandle, Rgn, fBrush.Handle )\r
16862     else\r
16863   if assigned( fOwnerControl ) then\r
16864   begin\r
16865     if Assigned( PControl( fOwnerControl ).fBrush ) then\r
16866       Windows.FillRgn( FHandle, Rgn, PControl( fOwnerControl ).fBrush.Handle )\r
16867     else\r
16868     begin\r
16869       Br := CreateSolidBrush( Color2RGB(PControl(fOwnerControl).fColor) );\r
16870       Windows.FillRgn( fHandle, Rgn, Br );\r
16871       DeleteObject( Br );\r
16872     end;\r
16873   end\r
16874      else\r
16875   begin\r
16876     Br := CreateSolidBrush( DWORD(clWindow) );\r
16877     Windows.FillRgn( fHandle, Rgn, Br );\r
16878     DeleteObject( Br );\r
16879   end;\r
16880 end;\r
16881 {$ENDIF ASM_VERSION}\r
16883 {$IFDEF ASM_!VERSION}\r
16884 //[procedure TCanvas.FloodFill]\r
16885 procedure TCanvas.FloodFill(X, Y: Integer; Color: TColor;\r
16886   FillStyle: TFillStyle);\r
16887 asm\r
16888         PUSH     EBX\r
16889         MOV      EBX, EAX\r
16891         MOVZX    EAX, [FillStyle]\r
16892         TEST     EAX, EAX\r
16893         MOV      EAX, FLOODFILLSURFACE   // = 1\r
16894         JZ       @@1\r
16895         //MOV      EAX, FLOODFILLBORDER  // = 0\r
16896         DEC      EAX\r
16897 @@1:\r
16898         PUSH     EAX\r
16899         PUSH     [Color]\r
16900         PUSH     ECX\r
16901         PUSH     EDX\r
16903         PUSH     HandleValid or BrushValid or ChangingCanvas\r
16904         PUSH     EBX\r
16905         CALL     RequiredState\r
16906         PUSH     EAX\r
16907         CALL     Windows.ExtFloodFill\r
16909         POP      EBX\r
16910 end;\r
16911 {$ELSE ASM_VERSION} //Pascal\r
16912 procedure TCanvas.FloodFill(X, Y: Integer; Color: TColor;\r
16913   FillStyle: TFillStyle);\r
16914 const\r
16915   FillStyles: array[TFillStyle] of Word =\r
16916     (FLOODFILLSURFACE, FLOODFILLBORDER);\r
16917 begin\r
16918   RequiredState( HandleValid or BrushValid or ChangingCanvas );\r
16919   Windows.ExtFloodFill(FHandle, X, Y, Color, FillStyles[FillStyle]);\r
16920 end;\r
16921 {$ENDIF ASM_VERSION}\r
16923 {$IFDEF ASM_VERSION}\r
16924 //[procedure TCanvas.FrameRect]\r
16925 procedure TCanvas.FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);\r
16926 asm\r
16927         PUSH     EBX\r
16928         XCHG     EBX, EAX\r
16929         PUSH     EDX\r
16931         MOV      ECX, [EBX].TCanvas.fBrush\r
16932         JECXZ    @@1\r
16934         PUSH     [ECX].TGraphicTool.fData.Color\r
16935         JMP      @@cr_br\r
16937 @@1:    MOV      ECX, [EBX].TCanvas.fOwnerControl\r
16938         JECXZ    @@2\r
16940         PUSH     [ECX].TControl.fColor\r
16941         JMP      @@cr_br\r
16943 @@2:    PUSH     clWhite\r
16944 @@cr_br:POP      EAX                  // @Rect\r
16945         CALL     Color2RGB\r
16946         PUSH     EAX\r
16947         CALL     CreateSolidBrush\r
16948         POP      EDX\r
16949           PUSH     EAX\r
16950         PUSH     EAX\r
16951         PUSH     EDX\r
16953         PUSH     HandleValid or ChangingCanvas\r
16954         PUSH     EBX\r
16955         ///MOV      EBX, EDX\r
16956         CALL     RequiredState\r
16958         PUSH     EAX\r
16959         CALL     Windows.FrameRect\r
16961         ///PUSH     EBX\r
16962         CALL     DeleteObject\r
16964         POP      EBX\r
16965 end;\r
16966 {$ELSE ASM_VERSION} //Pascal\r
16967 procedure TCanvas.FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);\r
16968 var SolidBr : HBrush;\r
16969 begin\r
16970   RequiredState( HandleValid or ChangingCanvas );\r
16971   if assigned( fBrush ) then\r
16972     SolidBr := CreateSolidBrush( Color2RGB( fBrush.fData.Color ) )\r
16973   else\r
16974   if assigned( fOwnerControl ) then\r
16975     SolidBr := CreateSolidBrush( PControl(fOwnerControl).fColor )\r
16976   else\r
16977     SolidBr := CreateSolidBrush( clWhite );\r
16978   Windows.FrameRect(FHandle, Rect, SolidBr);\r
16979   DeleteObject( SolidBr );\r
16980 end;\r
16981 {$ENDIF ASM_VERSION}\r
16983 {$IFDEF ASM_VERSION}\r
16984 //[procedure TCanvas.LineTo]\r
16985 procedure TCanvas.LineTo(X, Y: Integer);\r
16986 asm\r
16987         PUSH     ECX\r
16988         PUSH     EDX\r
16989         PUSH     HandleValid or PenValid or BrushValid or ChangingCanvas\r
16990         PUSH     EAX\r
16991         CALL     RequiredState\r
16992         PUSH     EAX  //Canvas.fHandle\r
16993         CALL     Windows.LineTo\r
16994 end;\r
16995 {$ELSE ASM_VERSION} //Pascal\r
16996 procedure TCanvas.LineTo(X, Y: Integer);\r
16997 begin\r
16998   RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );\r
16999   Windows.LineTo( fHandle, X, Y );\r
17000 end;\r
17001 {$ENDIF ASM_VERSION}\r
17003 {$IFDEF ASM_VERSION}\r
17004 //[procedure TCanvas.MoveTo]\r
17005 procedure TCanvas.MoveTo(X, Y: Integer);\r
17006 asm\r
17007         PUSH     0\r
17008         PUSH     ECX\r
17009         PUSH     EDX\r
17010         PUSH     HandleValid\r
17011         PUSH     EAX\r
17012         CALL     RequiredState\r
17013         PUSH     EAX  //Canvas.fHandle\r
17014         CALL     Windows.MoveToEx\r
17015 end;\r
17016 {$ELSE ASM_VERSION} //Pascal\r
17017 procedure TCanvas.MoveTo(X, Y: Integer);\r
17018 begin\r
17019   RequiredState( HandleValid );\r
17020   Windows.MoveToEx( fHandle, X, Y, nil );\r
17021 end;\r
17022 {$ENDIF ASM_VERSION}\r
17024 //[procedure TCanvas.ObjectChanged]\r
17025 procedure TCanvas.ObjectChanged(Sender: PGraphicTool);\r
17026 begin\r
17027   DeselectHandles;\r
17028   //if Assigned( GlobalCanvas_OnObjectChanged ) then\r
17029   //   GlobalCanvas_OnObjectChanged( Sender );\r
17030 end;\r
17032 {$IFDEF ASM_VERSION}\r
17033 //[procedure TCanvas.Pie]\r
17034 procedure TCanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;\r
17035 asm\r
17036         PUSH     HandleValid or PenValid or BrushValid or ChangingCanvas\r
17037         PUSH     dword ptr [EBP + 8]\r
17038         CALL     RequiredState\r
17040         MOV      EDX, EAX\r
17042         PUSH     ESI\r
17043         LEA      ESI, [Y4]\r
17044         STD\r
17046         XOR      ECX, ECX\r
17047         MOV      CL, 8\r
17048 @@1:\r
17049         LODSD\r
17050         PUSH     EAX\r
17052         LOOP     @@1\r
17054         CLD\r
17055         PUSH     EDX  //Canvas.fHandle\r
17056         CALL     Windows.Pie\r
17057         POP      ESI\r
17058 end;\r
17059 {$ELSE ASM_VERSION} //Pascal\r
17060 procedure TCanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;\r
17061 begin\r
17062   RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );\r
17063   Windows.Pie( fHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);\r
17064 end;\r
17065 {$ENDIF ASM_VERSION}\r
17067 {++}(*\r
17068 {$IFDEF F_P}\r
17069 //[Windows API FUNCTIONS ADDITIONAL DECLARATIONS FOR Free Pascal]\r
17070 function Windows_Polygon; external gdi32 name 'Polygon';\r
17071 function Windows_Polyline; external gdi32 name 'Polyline';\r
17072 function FillRect; external user32 name 'FillRect';\r
17073 function OffsetRect; external user32 name 'OffsetRect';\r
17074 function CreateAcceleratorTable; external user32 name 'CreateAcceleratorTableA';\r
17075 function TrackPopupMenu; external user32 name 'TrackPopupMenu';\r
17076 function AdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BOOL;\r
17077   const NewState: TTokenPrivileges; BufferLength: DWORD;\r
17078   var PreviousState: TTokenPrivileges; var ReturnLength: DWORD): BOOL; external advapi32 name 'AdjustTokenPrivileges';\r
17079 function InflateRect; external user32 name 'InflateRect';\r
17080 {$IFDEF F_P105ORBELOW}\r
17081 function InvalidateRect; external user32 name 'InvalidateRect';\r
17082 function ValidateRect; external user32 name 'ValidateRect';\r
17083 {$ENDIF F_P105ORBELOW}\r
17084 //[END OF Windows API FUNCTIONS ADDITIONAL DECLARATIONS FOR Free Pascal]\r
17085 {$ENDIF}\r
17086 *){--}\r
17088 {$IFDEF ASM_VERSION}\r
17089 //[procedure TCanvas.Polygon]\r
17090 procedure TCanvas.Polygon(const Points: array of TPoint);\r
17091 asm\r
17092         INC      ECX\r
17093         PUSH     ECX\r
17094         PUSH     EDX\r
17096         PUSH     HandleValid or PenValid or BrushValid or ChangingCanvas\r
17097         PUSH     EAX\r
17098         CALL     RequiredState\r
17100         PUSH     EAX\r
17101         CALL     Windows.Polygon\r
17102 end;\r
17103 {$ELSE ASM_VERSION} //Pascal\r
17104 procedure TCanvas.Polygon(const Points: array of TPoint);\r
17105 type\r
17106   PPoints = ^TPoints;\r
17107   TPoints = array[0..0] of TPoint;\r
17108 begin\r
17109   RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );\r
17110   {$IFDEF F_P} Windows_Polygon\r
17111   {$ELSE DELPHI} Windows.Polygon\r
17112   {$ENDIF}( fHandle, PPoints(@Points)^, High(Points) + 1);\r
17113 end;\r
17114 {$ENDIF ASM_VERSION}\r
17116 {$IFDEF ASM_VERSION}\r
17117 //[procedure TCanvas.Polyline]\r
17118 procedure TCanvas.Polyline(const Points: array of TPoint);\r
17119 asm\r
17120         INC      ECX\r
17121         PUSH     ECX\r
17122         PUSH     EDX\r
17124         PUSH     HandleValid or PenValid or BrushValid or ChangingCanvas\r
17125         PUSH     EAX\r
17126         CALL     RequiredState\r
17128         PUSH     EAX\r
17129         CALL     Windows.Polyline\r
17130 end;\r
17131 {$ELSE ASM_VERSION} //Pascal\r
17132 procedure TCanvas.Polyline(const Points: array of TPoint);\r
17133 type\r
17134   PPoints = ^TPoints;\r
17135   TPoints = array[0..0] of TPoint;\r
17136 begin\r
17137   RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );\r
17138   {$IFDEF F_P}Windows_Polyline\r
17139   {$ELSE DELPHI}Windows.Polyline\r
17140   {$ENDIF}( fHandle, PPoints(@Points)^, High(Points) + 1);\r
17141 end;\r
17142 {$ENDIF ASM_VERSION}\r
17144 {$IFDEF ASM_VERSION}\r
17145 //[procedure TCanvas.Rectangle]\r
17146 procedure TCanvas.Rectangle(X1, Y1, X2, Y2: Integer);\r
17147 asm\r
17148         PUSH     [Y2]\r
17149         PUSH     [X2]\r
17150         PUSH     ECX\r
17151         PUSH     EDX\r
17153         PUSH     HandleValid or BrushValid or PenValid or ChangingCanvas\r
17154         PUSH     EAX\r
17155         CALL     RequiredState\r
17157         PUSH     EAX\r
17158         CALL     Windows.Rectangle\r
17159 end;\r
17160 {$ELSE ASM_VERSION} //Pascal\r
17161 procedure TCanvas.Rectangle(X1, Y1, X2, Y2: Integer);\r
17162 begin\r
17163   RequiredState( HandleValid or BrushValid or PenValid or ChangingCanvas );\r
17164   Windows.Rectangle( fHandle, X1, Y1, X2, Y2);\r
17165 end;\r
17166 {$ENDIF ASM_VERSION}\r
17168 {$IFDEF ASM_VERSION}\r
17169 //[procedure TCanvas.RoundRect]\r
17170 procedure TCanvas.RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);\r
17171 asm\r
17172         PUSH     [Y3]\r
17173         PUSH     [X3]\r
17174         PUSH     [Y2]\r
17175         PUSH     [X2]\r
17176         PUSH     ECX\r
17177         PUSH     EDX\r
17179         PUSH     HandleValid or BrushValid or PenValid or ChangingCanvas\r
17180         PUSH     EAX\r
17181         CALL     RequiredState\r
17183         PUSH     EAX\r
17184         CALL     Windows.RoundRect\r
17185 end;\r
17186 {$ELSE ASM_VERSION} //Pascal\r
17187 procedure TCanvas.RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);\r
17188 begin\r
17189   RequiredState( HandleValid or BrushValid or PenValid or ChangingCanvas );\r
17190   Windows.RoundRect( fHandle, X1, Y1, X2, Y2, X3, Y3);\r
17191 end;\r
17192 {$ENDIF ASM_VERSION}\r
17194 {$IFDEF ASM_VERSION}\r
17195 //[procedure TCanvas.TextArea]\r
17196 procedure TCanvas.TextArea(const Text: String; var Sz: TSize;\r
17197   var P0: TPoint);\r
17198 asm\r
17199         PUSH     EBX\r
17200         MOV      EBX, EAX\r
17202         PUSH     ECX\r
17203         CALL     TextExtent\r
17204         POP      EDX\r
17206         MOV      ECX, [P0]\r
17207         XOR      EAX, EAX\r
17208         MOV      [ECX].TPoint.x, EAX\r
17209         MOV      [ECX].TPoint.y, EAX\r
17211         CMP      [GlobalCanvas_OnTextArea], EAX\r
17212         JZ       @@exit\r
17213         MOV      EAX, EBX\r
17214         CALL     [GlobalCanvas_OnTextArea]\r
17216 @@exit:\r
17217         POP      EBX\r
17218 end;\r
17219 {$ELSE ASM_VERSION} //Pascal\r
17220 procedure TCanvas.TextArea(const Text: String; var Sz: TSize;\r
17221   var P0: TPoint);\r
17222 begin\r
17223   Sz := TextExtent( Text );\r
17224   P0.x := 0; P0.y := 0;\r
17225   if Assigned( GlobalCanvas_OnTextArea ) then\r
17226      GlobalCanvas_OnTextArea( @Self, Sz, P0 );\r
17227 end;\r
17228 {$ENDIF ASM_VERSION}\r
17230 {$IFDEF ASM_VERSION}\r
17231 //[function TCanvas.TextExtent]\r
17232 function TCanvas.TextExtent(const Text: string): TSize;\r
17233 asm\r
17234         PUSH     EBX\r
17235         PUSH     ESI\r
17236         MOV      EBX, EAX\r
17238         PUSH     ECX               // prepare @Result\r
17240         MOV      EAX, EDX\r
17241         CALL     System.@LStrLen\r
17242         PUSH     EAX               // prepare Length(Text)\r
17244         CALL     EDX2PChar\r
17245         PUSH     EDX               // prepare PChar(Text)\r
17247         PUSH     HandleValid or FontValid\r
17248         PUSH     EBX\r
17249         CALL     RequiredState\r
17251         XCHG     ESI, EAX\r
17252         TEST     ESI, ESI          // ESI = fHandle before\r
17253         JNZ      @@1\r
17255         PUSH     ESI\r
17256         CALL     CreateCompatibleDC\r
17258         MOV      EDX, EBX\r
17259         XCHG     EAX, EDX // EAX := @Self; EDX := DC\r
17260         CALL     SetHandle\r
17261 @@1:\r
17262 //********************************************************** // Added By M.Gerasimov\r
17263 //*\r
17264         CMP      [EBX].TCanvas.fIsPaintDC, 1\r
17265         JZ       @@2\r
17266         XOR      ESI,ESI\r
17267 @@2:\r
17268 //*\r
17269 //********************************************************** // Added By M.Gerasimov\r
17270         PUSH     HandleValid or FontValid\r
17271         PUSH     EBX\r
17272         CALL     RequiredState\r
17273         PUSH     EAX               // prepare DC\r
17275         CALL     Windows.GetTextExtentPoint32\r
17277         TEST     ESI, ESI\r
17278         JNZ      @@exit\r
17280         XOR      EDX, EDX\r
17281         XCHG     EAX, EBX\r
17282         CALL     SetHandle\r
17284 @@exit:\r
17285         POP      ESI\r
17286         POP      EBX\r
17287 end;\r
17288 {$ELSE ASM_VERSION} //Pascal\r
17289 function TCanvas.TextExtent(const Text: string): TSize;\r
17290 var DC : HDC;\r
17291     ClearHandle : Boolean;\r
17292 begin\r
17293   //Result.cX := 0;\r
17294   //Result.cY := 0;\r
17295   ClearHandle := False;\r
17296   RequiredState( HandleValid or FontValid );\r
17297   DC := fHandle;\r
17298   if DC = 0 then\r
17299   begin\r
17300      DC := CreateCompatibleDC( 0 );\r
17301      ClearHandle := True;\r
17302      SetHandle( DC );\r
17303   end;\r
17304 //********************************************************** // Added By Gerasimov\r
17305 //*\r
17306   If Not fIsPaintDC then ClearHandle := True;\r
17307 //*\r
17308 //********************************************************** // Added By Gerasimov\r
17309   RequiredState( HandleValid or FontValid );\r
17310   Windows.GetTextExtentPoint32( fHandle, PChar(Text), Length(Text), Result);\r
17311   if ClearHandle then\r
17312     SetHandle( 0 );\r
17313     { DC must be freed here automatically (never leaks):\r
17314       if Canvas created on base of existing DC, no memDC created,\r
17315       if Canvas has fHandle:HDC = 0, it is not fIsPaintDC always. }\r
17316 end;\r
17317 {$ENDIF ASM_VERSION}\r
17319 //[function TCanvas.TextHeight]\r
17320 function TCanvas.TextHeight(const Text: string): Integer;\r
17321 begin\r
17322   Result := TextExtent(Text).cY;\r
17323 end;\r
17325 {$IFDEF ASM_VERSION}\r
17326 //[procedure TCanvas.TextOut]\r
17327 procedure TCanvas.TextOut(X, Y: Integer; const Text: String); stdcall;\r
17328 asm\r
17329         PUSH     EBX\r
17330         MOV      EBX, [EBP+8]\r
17332         MOV      EAX, [Text]\r
17333         PUSH     EAX\r
17334         CALL     System.@LStrLen\r
17335         XCHG     EAX, [ESP]             // prepare Length(Text)\r
17337         //CALL     System.@LStrToPChar  // string does not need to be null-terminated !\r
17338         PUSH     EAX                    // prepare PChar(Text)\r
17339         PUSH     [Y]                    // prepare Y\r
17340         PUSH     [X]                    // prepare X\r
17342         PUSH     HandleValid or FontValid or BrushValid or ChangingCanvas\r
17343         PUSH     EBX\r
17344         CALL     RequiredState\r
17345         PUSH     EAX                    // prepare fHandle\r
17346         CALL     Windows.TextOut\r
17348         { -- by suggetion of Alexey (Lecha2002)\r
17349         MOV      EAX, EBX\r
17350         MOV      EDX, [Text]\r
17351         CALL     TextWidth\r
17352         MOV      EDX, [X]\r
17353         ADD      EDX, EAX\r
17355         MOV      ECX, [Y]\r
17356         MOV      EAX, EBX\r
17357         CALL     MoveTo\r
17358         }\r
17360         POP      EBX\r
17361 end;\r
17362 {$ELSE ASM_VERSION} //Pascal\r
17363 procedure TCanvas.TextOut(X, Y: Integer; const Text: String); stdcall;\r
17364 begin\r
17365   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
17366   Windows.TextOut(FHandle, X, Y, PChar(Text), Length(Text));\r
17367   //MoveTo(X + TextWidth(Text), Y); -- by suggestion of Alexey (Lecha2002)\r
17368 end;\r
17369 {$ENDIF ASM_VERSION}\r
17371 {$IFDEF ASM_VERSION}\r
17372 //[procedure TCanvas.TextRect]\r
17373 procedure TCanvas.TextRect(const Rect: TRect; X, Y: Integer; const Text: string);\r
17374 asm\r
17375         PUSH     EBX\r
17376         XCHG     EBX, EAX\r
17378         PUSH     0              // prepare 0\r
17380         PUSH     EDX\r
17381         PUSH     ECX\r
17383         MOV      EAX, [Text]\r
17384         //CALL     System.@LStrToPChar\r
17385         PUSH     EAX\r
17387         //MOV      EAX, [Text]\r
17388         CALL     System.@LStrLen\r
17390         POP      ECX            // ECX = @Text[1]\r
17392         POP      EDX            // EDX = X\r
17393         XCHG     EAX, [ESP]     // prepare Length(Text), EAX = @Rect\r
17394         PUSH     ECX            // prepare PChar(Text)\r
17395         PUSH     EAX            // prepare @Rect\r
17397         XOR      EAX, EAX\r
17398         MOV      AL, ETO_CLIPPED // = 4\r
17399         MOV      ECX, [EBX].fBrush\r
17400         JECXZ    @@opaque\r
17402         CMP      [ECX].TGraphicTool.fData.Brush.Style, bsClear\r
17403         JZ       @@txtout\r
17405 @@opaque:\r
17406         DB $0C, ETO_OPAQUE //OR       AL, ETO_OPAQUE\r
17407 @@txtout:\r
17408         PUSH     EAX            // prepare Options\r
17409         PUSH     [Y]            // prepare Y\r
17410         PUSH     EDX            // prepare X\r
17412         PUSH     HandleValid or FontValid or BrushValid or ChangingCanvas\r
17413         PUSH     EBX\r
17414         CALL     RequiredState  // EAX = fHandle\r
17415         PUSH     EAX            // prepare fHandle\r
17417         CALL     Windows.ExtTextOut\r
17419         POP      EBX\r
17420 end;\r
17421 {$ELSE ASM_VERSION} //Pascal\r
17422 procedure TCanvas.TextRect(const Rect: TRect; X, Y: Integer; const Text: string);\r
17423 var\r
17424   Options: Integer;\r
17425 begin\r
17426   //Changing;\r
17427   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
17428   Options := ETO_CLIPPED;\r
17429   if assigned( fBrush ) and (fBrush.fData.Brush.Style <> bsClear)\r
17430   or not assigned( fBrush ) then Inc(Options, ETO_OPAQUE);\r
17431   Windows.ExtTextOut( fHandle, X, Y, Options,\r
17432                       @Rect, PChar(Text),\r
17433                       Length(Text), nil);\r
17434 end;\r
17435 {$ENDIF ASM_VERSION}\r
17437 //[procedure TCanvas.ExtTextOut]\r
17438 procedure TCanvas.ExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect; const Text: String;\r
17439           const Spacing: array of Integer );\r
17440 begin\r
17441   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
17442   Windows.ExtTextOut(FHandle, X, Y, Options, @Rect, PChar(Text), Length(Text), @Spacing[ 0 ]);\r
17443 end;\r
17445 //[procedure TCanvas.DrawText]\r
17446 procedure TCanvas.DrawText(Text:String; var Rect:TRect; Flags:DWord);\r
17447 begin\r
17448   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
17449   Windows.DrawText(Handle,PChar(Text),Length(Text),Rect,Flags);\r
17450 end;\r
17452 //[function TCanvas.ClipRect]\r
17453 function TCanvas.ClipRect: TRect;\r
17454 begin\r
17455   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
17456   GetClipBox(Handle, Result);\r
17457 end;\r
17459 //[function TCanvas.TextWidth]\r
17460 function TCanvas.TextWidth(const Text: string): Integer;\r
17461 begin\r
17462   Result := TextExtent(Text).cX;\r
17463 end;\r
17465 {$IFDEF ASM_VERSION}\r
17466 //[function TCanvas.GetBrush]\r
17467 function TCanvas.GetBrush: PGraphicTool;\r
17468 asm\r
17469         MOV      ECX, [EAX].fBrush\r
17470         INC      ECX\r
17471         LOOP     @@exit\r
17473         PUSH     EAX\r
17474         CALL     NewBrush\r
17475         POP      EDX\r
17476         PUSH     EAX\r
17478         MOV      [EDX].fBrush, EAX\r
17480         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Code, Offset[TCanvas.ObjectChanged]\r
17481         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX\r
17482         MOV      ECX, [EDX].fOwnerControl\r
17483         JECXZ    @@1\r
17485         PUSH     [ECX].TControl.fBrush\r
17486         MOV      ECX, [ECX].TControl.fColor\r
17487         MOV      [EAX].TGraphicTool.fData.Color, ECX\r
17488         POP      EDX\r
17489         TEST     EDX, EDX\r
17490         JZ       @@1\r
17492         CALL     TGraphicTool.Assign\r
17494 @@1:    POP      ECX\r
17496 @@exit: XCHG     EAX, ECX\r
17497 end;\r
17498 {$ELSE ASM_VERSION} //Pascal\r
17499 function TCanvas.GetBrush: PGraphicTool;\r
17500 begin\r
17501   if not assigned( fBrush ) then\r
17502   begin\r
17503     fBrush := NewBrush;\r
17504     if assigned( fOwnerControl ) then\r
17505     begin\r
17506       fBrush.fData.Color := PControl(fOwnerControl).fColor;\r
17507       if assigned( PControl(fOwnerControl).fBrush ) then\r
17508          {fBrush := }fBrush.Assign( PControl(fOwnerControl).fBrush );\r
17509       // both statements above needed\r
17510     end;\r
17511     //fBrush.OnChange := ObjectChanged;\r
17512     AssignChangeEvents;\r
17513   end;\r
17514   Result := fBrush;\r
17515 end;\r
17516 {$ENDIF ASM_VERSION}\r
17518 {$IFDEF ASM_VERSION}\r
17519 //[function TCanvas.GetFont]\r
17520 function TCanvas.GetFont: PGraphicTool;\r
17521 asm\r
17522         MOV      ECX, [EAX].TCanvas.fFont\r
17523         INC      ECX\r
17524         LOOP     @@exit\r
17526         PUSH     EAX\r
17527         CALL     NewFont\r
17528         POP      EDX\r
17529         PUSH     EAX\r
17531         MOV      [EDX].TCanvas.fFont, EAX\r
17532         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Code, Offset[TCanvas.ObjectChanged]\r
17533         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX\r
17535         MOV      ECX, [EDX].fOwnerControl\r
17536         JECXZ    @@1\r
17538         PUSH     [ECX].TControl.fFont\r
17539         MOV      ECX, [ECX].TControl.fTextColor\r
17540         MOV      [EAX].TGraphicTool.fData.Color, ECX\r
17541         POP      EDX\r
17542         TEST     EDX, EDX\r
17543         JZ       @@1\r
17545         CALL     TGraphicTool.Assign\r
17547 @@1:    POP      ECX\r
17549 @@exit: MOV      EAX, ECX\r
17550 end;\r
17551 {$ELSE ASM_VERSION} //Pascal\r
17552 function TCanvas.GetFont: PGraphicTool;\r
17553 begin\r
17554   if not assigned( fFont ) then\r
17555   begin\r
17556     fFont := NewFont;\r
17557     if assigned( fOwnerControl ) then\r
17558     begin\r
17559       fFont.Color := PControl(fOwnerControl).fTextColor;\r
17560       if assigned( PControl(fOwnerControl).fFont ) then\r
17561         {fFont := }fFont.Assign( PControl(fOwnerControl).fFont );\r
17562     end;\r
17563     //fFont.OnChange := ObjectChanged;\r
17564     AssignChangeEvents;\r
17565   end;\r
17566   Result := fFont;\r
17567 end;\r
17568 {$ENDIF ASM_VERSION}\r
17570 {$IFDEF ASM_VERSION}\r
17571 //[function TCanvas.GetPen]\r
17572 function TCanvas.GetPen: PGraphicTool;\r
17573 asm\r
17574         MOV      ECX, [EAX].TCanvas.fPen\r
17575         INC      ECX\r
17576         LOOP     @@exit\r
17578         PUSH     EAX\r
17579         CALL     NewPen\r
17580         POP      EDX\r
17581         MOV      [EDX].fPen, EAX\r
17582         PUSH     EAX\r
17583         MOV      EAX, EDX\r
17584         CALL     AssignChangeEvents\r
17585         POP      ECX\r
17587 @@exit: MOV      EAX, ECX\r
17588 end;\r
17589 {$ELSE ASM_VERSION} //Pascal\r
17590 function TCanvas.GetPen: PGraphicTool;\r
17591 begin\r
17592   if not assigned( fPen ) then\r
17593   begin\r
17594     fPen := NewPen;\r
17595     AssignChangeEvents;\r
17596   end;\r
17597   Result := fPen;\r
17598 end;\r
17599 {$ENDIF ASM_VERSION}\r
17601 {$IFDEF ASM_VERSION}\r
17602 //[function TCanvas.GetHandle]\r
17603 function TCanvas.GetHandle: HDC;\r
17604 asm\r
17605         CMP      word ptr[EAX].fOnGetHandle.TMethod.Code+2, 0\r
17606         MOV      EDX, EAX\r
17607         MOV      EAX, [EDX].fHandle\r
17608         JZ       @@exit\r
17609         MOV      EAX, [EDX].fOnGetHandle.TMethod.Data\r
17610         PUSH     EDX\r
17611         CALL     [EDX].fOnGetHandle.TMethod.Code\r
17612         XCHG     EAX, [ESP]\r
17613         POP      EDX\r
17614         PUSH     EDX\r
17615         CALL     SetHandle\r
17616         POP      EAX\r
17617 @@exit:\r
17618 end;\r
17619 {$ELSE ASM_VERSION} //Pascal\r
17620 function TCanvas.GetHandle: HDC;\r
17621 begin\r
17622   if assigned( fOnGetHandle ) then\r
17623   begin\r
17624     Result := fOnGetHandle( @Self );\r
17625     //fHandle := Result;\r
17626     SetHandle( Result );\r
17627   end\r
17628   else\r
17629     Result := fHandle;\r
17630 end;\r
17631 {$ENDIF ASM_VERSION}\r
17633 {$IFDEF ASM_VERSION}\r
17634 //[procedure TCanvas.AssignChangeEvents]\r
17635 procedure TCanvas.AssignChangeEvents;\r
17636 asm\r
17637         PUSH     ESI\r
17638         LEA      ESI, [EAX].fBrush\r
17639         MOV      CL, 3\r
17640         MOV      EDX, EAX\r
17641 @@1:    LODSD\r
17642         TEST     EAX, EAX\r
17643         JZ       @@nxt\r
17644         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX\r
17645         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[ ObjectChanged ]\r
17646 @@nxt:  DEC      CL\r
17647         JNZ      @@1\r
17648         POP      ESI\r
17649 end;\r
17650 {$ELSE ASM_VERSION} //Pascal\r
17651 procedure TCanvas.AssignChangeEvents;\r
17652 begin\r
17653   if assigned( fFont ) then\r
17654      fFont.fOnChange := ObjectChanged;\r
17655   if assigned( fBrush ) then\r
17656      fBrush.fOnChange := ObjectChanged;\r
17657   if assigned( fPen ) then\r
17658      fPen.fOnChange := ObjectChanged;\r
17659 end;\r
17660 {$ENDIF ASM_VERSION}\r
17662 {$IFNDEF _FPC}\r
17663 {$IFNDEF _D2}\r
17664 //[procedure TCanvas.WDrawText]\r
17665 procedure TCanvas.WDrawText(WText: WideString; var Rect: TRect;\r
17666   Flags: DWord);\r
17667 begin\r
17668   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
17669   Windows.DrawTextW(Handle,PWideChar(WText),Length(WText),Rect,Flags);\r
17670 end;\r
17672 //[procedure TCanvas.WExtTextOut]\r
17673 procedure TCanvas.WExtTextOut(X, Y: Integer; Options: DWORD;\r
17674   const Rect: TRect; const WText: WideString;\r
17675   const Spacing: array of Integer);\r
17676 begin\r
17677   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
17678   Windows.ExtTextOutW(FHandle, X, Y, Options, @Rect, PWideChar(WText), Length(WText), @Spacing[ 0 ]);\r
17679 end;\r
17681 //[procedure TCanvas.WTextOut]\r
17682 procedure TCanvas.WTextOut(X, Y: Integer; const WText: WideString);\r
17683 begin\r
17684   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
17685   Windows.TextOutW(FHandle, X, Y, PWideChar(WText), Length(WText));\r
17686   MoveTo(X + WTextWidth(WText), Y);\r
17687 end;\r
17689 //[procedure TCanvas.WTextRect]\r
17690 procedure TCanvas.WTextRect(const Rect: TRect; X, Y: Integer;\r
17691   const WText: WideString);\r
17692 var\r
17693   Options: Integer;\r
17694 begin\r
17695   //Changing;\r
17696   RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
17697   Options := ETO_CLIPPED;\r
17698   if assigned( fBrush ) and (fBrush.fData.Brush.Style <> bsClear)\r
17699   or not assigned( fBrush ) then Inc(Options, ETO_OPAQUE);\r
17700   Windows.ExtTextOutW( fHandle, X, Y, Options,\r
17701                       @Rect, PWideChar(WText),\r
17702                       Length(WText), nil);\r
17703 end;\r
17705 //[function TCanvas.WTextExtent]\r
17706 function TCanvas.WTextExtent(const WText: WideString): TSize;\r
17707 var DC : HDC;\r
17708     ClearHandle : Boolean;\r
17709 begin\r
17710   ClearHandle := False;\r
17711   RequiredState( HandleValid or FontValid );\r
17712   DC := fHandle;\r
17713   if DC = 0 then\r
17714   begin\r
17715      DC := CreateCompatibleDC( 0 );\r
17716      ClearHandle := True;\r
17717      SetHandle( DC );\r
17718   end;\r
17719   RequiredState( HandleValid or FontValid );\r
17720   Windows.GetTextExtentPoint32W( fHandle, PWideChar(WText), Length(WText), Result);\r
17721   if ClearHandle then\r
17722     SetHandle( 0 );\r
17723 end;\r
17725 //[function TCanvas.WTextHeight]\r
17726 function TCanvas.WTextHeight(const WText: WideString): Integer;\r
17727 begin\r
17728   Result := WTextExtent( WText ).cy;\r
17729 end;\r
17731 //[function TCanvas.WTextWidth]\r
17732 function TCanvas.WTextWidth(const WText: WideString): Integer;\r
17733 begin\r
17734   Result := WTextExtent( WText ).cx;\r
17735 end;\r
17736 {$ENDIF _D2}\r
17737 {$ENDIF _FPC}\r
17748 {-}\r
17749 //[function MakeInt64]\r
17750 function MakeInt64( Lo, Hi: DWORD ): I64;\r
17751 begin\r
17752   Result.Lo := Lo;\r
17753   Result.Hi := Hi;\r
17754 end;\r
17756 //[function Int2Int64]\r
17757 function Int2Int64( X: Integer ): I64;\r
17758 asm\r
17759   MOV  [EDX], EAX\r
17760   MOV  ECX, EDX\r
17761   CDQ\r
17762   MOV  [ECX+4], EDX\r
17763 end;\r
17765 //[procedure IncInt64]\r
17766 procedure IncInt64( var I64: I64; Delta: Integer );\r
17767 asm\r
17768   ADD  [EAX], EDX\r
17769   ADC  dword ptr [EAX+4], 0\r
17770 end;\r
17772 //[procedure DecInt64]\r
17773 procedure DecInt64( var I64: I64; Delta: Integer );\r
17774 asm\r
17775   SUB  [EAX], EDX\r
17776   SBB  dword ptr [EDX], 0\r
17777 end;\r
17779 //[function Add64]\r
17780 function Add64( const X, Y: I64 ): I64;\r
17781 asm\r
17782   PUSH  ESI\r
17783   XCHG  ESI, EAX\r
17784   LODSD\r
17785   ADD   EAX, [EDX]\r
17786   MOV   [ECX], EAX\r
17787   LODSD\r
17788   ADC   EAX, [EDX+4]\r
17789   MOV   [ECX+4], EAX\r
17790   POP   ESI\r
17791 end;\r
17793 //[function Sub64]\r
17794 function Sub64( const X, Y: I64 ): I64;\r
17795 asm\r
17796   PUSH  ESI\r
17797   XCHG  ESI, EAX\r
17798   LODSD\r
17799   SUB   EAX, [EDX]\r
17800   MOV   [ECX], EAX\r
17801   LODSD\r
17802   SBB   EAX, [EDX+4]\r
17803   MOV   [ECX+4], EAX\r
17804   POP   ESI\r
17805 end;\r
17807 //[function Neg64]\r
17808 function Neg64( const X: I64 ): I64;\r
17809 asm\r
17810   MOV  ECX, [EAX]\r
17811   NEG  ECX\r
17812   MOV  [EDX], ECX\r
17813   MOV  ECX, 0\r
17814   SBB  ECX, [EAX+4]\r
17815   MOV  [EDX+4], ECX\r
17816 end;\r
17818 //[function Mul64EDX]\r
17819 function Mul64EDX( const X: I64; M: Integer ): I64;\r
17820 asm\r
17821   PUSH  ESI\r
17822   PUSH  EDI\r
17823   XCHG  ESI, EAX\r
17824   MOV   EDI, ECX\r
17825   MOV   ECX, EDX\r
17826   LODSD\r
17827   MUL   ECX\r
17828   STOSD\r
17829   XCHG  EDX, ECX\r
17830   LODSD\r
17831   MUL  EDX\r
17832   ADD   EAX, ECX\r
17833   STOSD\r
17834   POP   EDI\r
17835   POP   ESI\r
17836 end;\r
17838 //[FUNCTION Mul64i]\r
17839 {$IFDEF ASM_VERSION}\r
17840 function Mul64i( const X: I64; Mul: Integer ): I64;\r
17841 asm     //cmd    //opd\r
17842         TEST     EDX, EDX\r
17843         PUSHFD\r
17844         JGE      @@1\r
17845         NEG      EDX\r
17846 @@1:    PUSH     ECX\r
17847         CALL     Mul64EDX\r
17848         POP      EAX\r
17849         POPFD\r
17850         JGE      @@2\r
17851         MOV      EDX, EAX\r
17852         CALL     Neg64\r
17853 @@2:\r
17854 end;\r
17855 {$ELSE ASM_VERSION} //Pascal\r
17856 function Mul64i( const X: I64; Mul: Integer ): I64;\r
17857 var Minus: Boolean;\r
17858 begin\r
17859   Minus := FALSE;\r
17860   if Mul < 0 then\r
17861   begin\r
17862     Minus := TRUE;\r
17863     Mul := -Mul;\r
17864   end;\r
17865   Result := Mul64EDX( X, Mul );\r
17866   if Minus then\r
17867     Result := Neg64( Result );\r
17868 end;\r
17869 {$ENDIF ASM_VERSION}\r
17870 //[END Mul64i]\r
17872 //[function Div64EDX]\r
17873 function Div64EDX( const X: I64; D: Integer ): I64;\r
17874 asm\r
17875   PUSH  ESI\r
17876   PUSH  EDI\r
17877   XCHG  ESI, EAX\r
17878   MOV   EDI, ECX\r
17879   MOV   ECX, EDX\r
17880   MOV   EAX, [ESI+4]\r
17881   CDQ\r
17882   DIV  ECX\r
17883   MOV   [EDI+4], EAX\r
17884   LODSD\r
17885   DIV  ECX\r
17886   STOSD\r
17887   POP   EDI\r
17888   POP   ESI\r
17889 end;\r
17891 //[FUNCTION Div64i]\r
17892 {$IFDEF ASM_VERSION}\r
17893 function Div64i( const X: I64; D: Integer ): I64;\r
17894 asm     //cmd    //opd\r
17895         PUSH     EBX\r
17896         XOR      EBX, EBX\r
17897         PUSH     ESI\r
17898         XCHG     ESI, EAX\r
17899         LODSD\r
17900         MOV      [ECX], EAX\r
17901         LODSD\r
17902         MOV      [ECX+4], EAX\r
17903         MOV      ESI, ECX\r
17904         PUSH     EDX\r
17905         XCHG     EAX, ECX\r
17906         CALL     Sgn64\r
17907         TEST     EAX, EAX\r
17908         JGE      @@1\r
17909         INC      EBX\r
17910         MOV      EAX, ESI\r
17911         MOV      EDX, ESI\r
17912         CALL     Neg64\r
17913 @@1:    POP      EDX\r
17914         TEST     EDX, EDX\r
17915         JGE      @@2\r
17916         XOR      EBX, 1\r
17917         NEG      EDX\r
17918 @@2:    MOV      EAX, ESI\r
17919         MOV      ECX, ESI\r
17920         CALL     Div64EDX\r
17921         DEC      EBX\r
17922         JNZ      @@3\r
17923         MOV      EDX, ESI\r
17924         XCHG     EAX, ESI\r
17925         CALL     Neg64\r
17926 @@3:    POP      ESI\r
17927         POP      EBX\r
17928 end;\r
17929 {$ELSE ASM_VERSION} //Pascal\r
17930 function Div64i( const X: I64; D: Integer ): I64;\r
17931 var Minus: Boolean;\r
17932 begin\r
17933   Minus := FALSE;\r
17934   if D < 0 then\r
17935   begin\r
17936     D := -D;\r
17937     Minus := TRUE;\r
17938   end;\r
17939   Result := X;\r
17940   if Sgn64( Result ) < 0 then\r
17941   begin\r
17942     Result := Neg64( Result );\r
17943     Minus := not Minus;\r
17944   end;\r
17945   Result := Div64EDX( Result, D );\r
17946   if Minus then\r
17947     Result := Neg64( Result );\r
17948 end;\r
17949 {$ENDIF ASM_VERSION}\r
17950 //[END Div64i]\r
17952 //[function Mod64i]\r
17953 function Mod64i( const X: I64; D: Integer ): Integer;\r
17954 begin\r
17955   Result := Sub64( X, Mul64i( Div64i( X, D ), D ) ).Lo;\r
17956 end;\r
17958 //[function Sgn64]\r
17959 function Sgn64( const X: I64 ): Integer;\r
17960 asm\r
17961   XOR  EDX, EDX\r
17962   CMP  [EAX+4], EDX\r
17963   XCHG EAX, EDX\r
17964   JG   @@ret_1\r
17965   JL   @@ret_neg\r
17966   CMP  [EDX], EAX\r
17967   JZ   @@exit\r
17968 @@ret_1:\r
17969   INC  EAX\r
17970   RET\r
17971 @@ret_neg:\r
17972   DEC  EAX\r
17973 @@exit:\r
17974 end;\r
17976 //[function Cmp64]\r
17977 function Cmp64( const X, Y: I64 ): Integer;\r
17978 begin\r
17979   Result := Sgn64( Sub64( X, Y ) );\r
17980 end;\r
17982 //[function Int64_2Str]\r
17983 function Int64_2Str( X: I64 ): String;\r
17984 var M: Boolean;\r
17985     Y: Integer;\r
17986     Buf: array[ 0..31 ] of Char;\r
17987     I: Integer;\r
17988 begin\r
17989   M := FALSE;\r
17990   case Sgn64( X ) of\r
17991   -1: begin M := TRUE; X := Neg64( X ); end;\r
17992   0:  begin Result := '0'; Exit; end;\r
17993   end;\r
17994   I := 31;\r
17995   Buf[ 31 ] := #0;\r
17996   while Sgn64( X ) > 0 do\r
17997   begin\r
17998     Dec( I );\r
17999     Y := Mod64i( X, 10 );\r
18000     Buf[ I ] := Char( Y + Integer( '0' ) );\r
18001     X := Div64i( X, 10 );\r
18002   end;\r
18003   if M then\r
18004   begin\r
18005     Dec( I );\r
18006     Buf[ I ] := '-';\r
18007   end;\r
18008   Result := PChar( @Buf[ I ] );\r
18009 end;\r
18011 //[function Str2Int64]\r
18012 function Str2Int64( const S: String ): I64;\r
18013 var I: Integer;\r
18014     M: Boolean;\r
18015 begin\r
18016   Result.Lo := 0;\r
18017   Result.Hi := 0;\r
18018   I := 1;\r
18019   if S = '' then Exit;\r
18020   M := FALSE;\r
18021   if S[ 1 ] = '-' then\r
18022   begin\r
18023     M := TRUE;\r
18024     Inc( I );\r
18025   end\r
18026     else\r
18027   if S[ 1 ] = '+' then\r
18028     Inc( I );\r
18029   while I <= Length( S ) do\r
18030   begin\r
18031     if not( S[ I ] in [ '0'..'9' ] ) then\r
18032       break;\r
18033     Result := Mul64i( Result, 10 );\r
18034     IncInt64( Result, Integer( S[ I ] ) - Integer( '0' ) );\r
18035     Inc( I );\r
18036   end;\r
18037   if M then\r
18038     Result := Neg64( Result );\r
18039 end;\r
18041 //[function Int64_2Double]\r
18042 function Int64_2Double( const X: I64 ): Double;\r
18043 asm\r
18044   FILD qword ptr [EAX]\r
18045   FSTP @Result\r
18046 end;\r
18048 //[function Double2Int64]\r
18049 function Double2Int64( D: Double ): I64;\r
18050 asm\r
18051   FLD   D\r
18052   FISTP qword ptr [EAX]\r
18053 end;\r
18055 {+}\r
18056 function IsNan(const AValue: Double): Boolean;\r
18057 {$IFDEF _D2orD3}\r
18058 type PI64 = ^I64;\r
18059 {$ENDIF}\r
18060 begin\r
18061   {-}\r
18062   Result := (PI64(@AValue).Hi and $7FF00000 = $7FF00000) and\r
18063             ((PI64(@AValue).Hi and $000FFFFF <> 0) or (PI64(@AValue).Lo <> 0));\r
18064   {+}{++}(*Result := AValue = NAN;*){--}\r
18065 end;\r
18067 //[function IntPower]\r
18068 function IntPower(Base: Extended; Exponent: Integer): Extended;\r
18069 {$IFDEF F_P}\r
18070 begin\r
18071   if Exponent = 0 then\r
18072   begin\r
18073     Result := 1.0;\r
18074     Exit;\r
18075   end;\r
18076   if Exponent < 0 then\r
18077   begin\r
18078     Exponent := -Exponent;\r
18079     Base := 1.0 / Base;\r
18080   end;\r
18081   Result := Base;\r
18082   REPEAT\r
18083     Result := Result * Base;\r
18084     Dec( Exponent );\r
18085   UNTIL Exponent <= 0;\r
18086 end;\r
18087 {$ELSE DELPHI}\r
18088 // This version of code by Galkov:\r
18089 // Changes in comparison to Delphi standard:\r
18090 // no Overflow exception if Exponent is very big negative value\r
18091 // (just 0 in result in such case).\r
18092 asm\r
18093         fld1             { Result := 1 }\r
18094         test    eax,eax  // check Exponent for 0, return 0 ** 0 = 1\r
18095         jz      @@3      // (though Mathematics says that this is not so...)\r
18096         fld     Base\r
18097         jg      @@2\r
18098         fdivr   ST,ST(1) { Base := 1 / Base }\r
18099         neg     eax\r
18100         jmp     @@2\r
18101 @@1:    fmul    ST,ST    { X := Base * Base }\r
18102 @@2:    shr     eax,1\r
18103         jnc     @@1\r
18104         fmul    ST(1),ST { Result := Result * X }\r
18105         jnz     @@1\r
18106         fstp    st       { pop X from FPU stack }\r
18107 @@3:    fwait\r
18108 end;\r
18109 (* version of code by Borland:\r
18110 asm\r
18111         mov     ecx, eax\r
18112         cdq\r
18113         fld1                      { Result := 1 }\r
18114         xor     eax, edx\r
18115         sub     eax, edx          { eax := Abs(Exponent) }\r
18116         jz      @@3\r
18117         fld     Base\r
18118         jmp     @@2\r
18119 @@1:    fmul    ST, ST            { X := Base * Base }\r
18120 @@2:    shr     eax,1\r
18121         jnc     @@1\r
18122         fmul    ST(1),ST          { Result := Result * X }\r
18123         jnz     @@1\r
18124         fstp    st                { pop X from FPU stack }\r
18125         cmp     ecx, 0\r
18126         jge     @@3\r
18127         fld1\r
18128         fdivrp                    { Result := 1 / Result }\r
18129 @@3:\r
18130         fwait\r
18131 end;*)\r
18132 {$ENDIF F_P/DELPHI}\r
18134 //[function Str2Double]\r
18135 function Str2Double( const S: String ): Double;\r
18136 var I: Integer;\r
18137     M, Pt: Boolean;\r
18138     D: Double;\r
18139     Ex: Integer;\r
18140 begin\r
18141   Result := 0.0;\r
18142   if S = '' then Exit;\r
18143   M := FALSE;\r
18144   I := 1;\r
18145   if S[ 1 ] = '-' then\r
18146   begin\r
18147     M := TRUE;\r
18148     Inc( I );\r
18149   end;\r
18150   Pt := FALSE;\r
18151   D := 1.0;\r
18152   while I <= Length( S ) do\r
18153   begin\r
18154     case S[ I ] of\r
18155     '.': if not Pt then Pt := TRUE else break;\r
18156     '0'..'9': if not Pt then\r
18157                  Result := Result * 10.0 + Integer( S[ I ] ) - Integer( '0' )\r
18158               else\r
18159               begin\r
18160                 D := D * 0.1;\r
18161                 Result := Result + (Integer( S[ I ] ) - Integer( '0' )) * D;\r
18162               end;\r
18163     'e', 'E': begin\r
18164                 Ex := Str2Int( CopyEnd( S, I + 1 ) );\r
18165                 Result := Result * IntPower( 10.0, Ex );\r
18166                 break;\r
18167               end;\r
18168     end;\r
18169     Inc( I );\r
18170   end;\r
18171   if M then\r
18172     Result := -Result;\r
18173 end;\r
18175 //[function TruncD]\r
18176 function TruncD( D: Double ): Double;\r
18177 {-}\r
18178 asm\r
18179   FLD    D\r
18180   PUSH   ECX\r
18181   FNSTCW [ESP]\r
18182   POP    ECX\r
18183   PUSH   ECX\r
18184   OR     byte ptr [ESP+1], $0C\r
18185   FLDCW  [ESP]\r
18186   PUSH   ECX\r
18187   FRNDINT\r
18188   FSTP   @Result\r
18189   FLDCW  [ESP]\r
18190   POP    ECX\r
18191   POP    ECX\r
18192 end;\r
18193 {+}{++}(*\r
18194 begin\r
18195   Result := Trunc( D );\r
18196 end;\r
18197 *){--}\r
18199 // Precision 15\r
18200 //[function Extended2Str]\r
18201 function Extended2Str( E: Extended ): String;\r
18202     function UnpackFromBuf( const Buf: array of Byte; N: Integer ): String;\r
18203     var I, J, K, L: Integer;\r
18204     begin\r
18205       SetLength( Result, 16 );\r
18206       J := 1;\r
18207       for I := 7 downto 0 do\r
18208       begin\r
18209         K := Buf[ I ] shr 4;\r
18210         Result[ J ] := Char( Ord('0') + K );\r
18211         Inc( J );\r
18212         K := Buf[ I ] and $F;\r
18213         Result[ J ] := Char( Ord('0') + K );\r
18214         Inc( J );\r
18215       end;\r
18217       Assert( Result[ 1 ] = '0', 'error!' );\r
18218       Delete( Result, 1, 1 );\r
18220       if N <= 0 then\r
18221       begin\r
18222         while N < 0 do\r
18223         begin\r
18224           Result := '0' + Result;\r
18225           Inc( N );\r
18226         end;\r
18227         Result := '0.' + Result;\r
18228       end\r
18229         else\r
18230       if N < Length( Result ) then\r
18231       begin\r
18232         Result := Copy( Result, 1, N ) + '.' + CopyEnd( Result, N + 1 );\r
18233       end\r
18234         else\r
18235       begin\r
18236         while N > Length( Result ) do\r
18237         begin\r
18238           Result := Result + '0';\r
18239         end;\r
18240         Exit;\r
18241       end;\r
18243       L := Length( Result );\r
18244       while L > 1 do\r
18245       begin\r
18246         if not (Result[ L ] in ['0','.']) then break;\r
18247         Dec( L );\r
18248         if Result[ L + 1 ] = '.' then break;\r
18249       end;\r
18250       if L < Length( Result ) then Delete( Result, L + 1, MaxInt );\r
18252     end;\r
18254 var\r
18255   S: Boolean;\r
18256 var F: Extended;\r
18257     N: Integer;\r
18258     Buf1: array[ 0..9 ] of Byte;\r
18259     I10: Integer;\r
18260 begin\r
18261   Result := '0';\r
18262   if E = 0 then Exit;\r
18263   S := E < 0;\r
18264   if S then E := -E;\r
18266   N := 15;\r
18267   F := 5E12;\r
18268   I10 := 10;\r
18269   while E < F do\r
18270   begin\r
18271     Dec( N );\r
18272     E := E * I10;\r
18273   end;\r
18274   if N = 15 then\r
18275   while E >= 1E13 do\r
18276   begin\r
18277     Inc( N );\r
18278     E := E / I10;\r
18279   end;\r
18281   while TRUE do\r
18282   begin\r
18283     asm\r
18284       FLD    [E]\r
18285       FBSTP  [Buf1]\r
18286     end;\r
18287     if Buf1[ 7 ] <> 0 then break;\r
18288     E := E * I10;\r
18289     Dec( N );\r
18290   end;\r
18292   Result := UnpackFromBuf( Buf1, N );\r
18294   if S then Result := '-' + Result;\r
18295 end;\r
18297 //[function Double2Str]\r
18298 function Double2Str( D: Double ): String;\r
18299 begin\r
18300   Result := Extended2Str( D );\r
18301 end;\r
18303 //[function Double2StrEx]\r
18304 function Double2StrEx( D: Double ): String;\r
18305 var E, E1, E2: Double;\r
18306     S: String;\r
18307 begin\r
18308   Result := Double2Str( D );\r
18309   E := Str2Double( Result );\r
18310   E1 := E - D;\r
18311   if E1 < 0.0 then E1 := -E1;\r
18312   if E1 < 1e-307 then Exit;\r
18313   while TRUE do\r
18314   begin\r
18315     E := D - (E - D) * 0.3;\r
18316     S := Double2Str( E );\r
18317     if S = Result then break;\r
18318     E := Str2Double( S );\r
18319     E2 := E - D;\r
18320     if E2 < 0.0 then E2 := -E2;\r
18321     if E2 > E1 * 0.75 then break;\r
18322     Result := S;\r
18323     if E2 < E1 * 0.1 then break;\r
18324   end;\r
18325 end;\r
18327 //[function GetBits]\r
18328 function GetBits( N: DWORD; first, last: Byte ): DWord;\r
18329 {$IFDEF F_P}\r
18330 begin\r
18331   Result := 0;\r
18332   if last > 31 then last := 31;\r
18333   if first > last then Exit;\r
18334   Result := (N and not ($FFFFFFFF shl last)) shr first;\r
18335 end;\r
18336 {$ELSE DELPHI}\r
18337 asm\r
18338    XCHG EAX, EDX  // (1) EDX=N, AL=first\r
18339    {$IFDEF PARANOIA}\r
18340    DB $3C, 31\r
18341    {$ELSE}\r
18342    CMP AL, 31 // first(AL) > 31 ?\r
18343    {$ENDIF}\r
18344    JBE  @@1       // (2) åñëè äà, òî Result := 0;\r
18345 @@0:\r
18346    XOR  EAX, EAX  // (2)\r
18347    RET            // (1)\r
18348 @@1:\r
18350    XCHG EAX, ECX  // (1) AL = last CL = first\r
18351    SHR  EDX, CL   // (2) EDX = N shr first\r
18352    SUB  AL,  CL   // (2) AL = last - first\r
18353    JL @@0         // (2) åñëè last < first òî Result := 0;\r
18355    {$IFDEF PARANOIA}\r
18356    DB $3C, 32\r
18357    {$ELSE}\r
18358    CMP AL, 32     // (2) last - first >= 32 ?\r
18359    {$ENDIF}\r
18360    XCHG ECX, EAX  // (1) CL = last - first\r
18361    XCHG EAX, EDX  // (1) EAX = N shr first\r
18362    JAE  @@exit    // (2) åñëè last - first > 31, òî Result := EAX;\r
18363    SBB  EDX, EDX  // (2) EDX = -1\r
18364    DEC  EDX       // (1) EDX = 1111...10 = -2\r
18365    SHL  EDX, CL   // (2) EDX = 111...100..0 (ãäå n(0)=last-first+1)\r
18366    NOT  EDX       // (2) EDX = ìàñêà 000..0111...1 (ãäå n(1)=last-first+1)\r
18367    AND  EAX, EDX  // (2)\r
18368 @@exit:\r
18369    // EAX = ðåçóëüòàò, (1 áàéò íà êîìàíäó RET)\r
18370 end;\r
18371 {$ENDIF F_P/DELPHI}\r
18373 //[function GetBitsL]\r
18374 function GetBitsL( N: DWORD; from, len: Byte ): DWord;\r
18375 {$IFDEF F_P}\r
18376 begin\r
18377   Result := GetBits( N, from, from + len - 1 );\r
18378 end;\r
18379 {$ELSE DELPHI}\r
18380 asm\r
18381    ADD  CL, DL\r
18382    DEC  CL\r
18383    JMP  GetBits\r
18384 end;\r
18385 {$ENDIF F_P/DELPHI}\r
18387 //[FUNCTION Int2Hex]\r
18388 {$IFDEF ASM_VERSION}\r
18389 function Int2Hex( Value : DWord; Digits : Integer ) : String;\r
18390 asm\r
18392         // EAX = Value\r
18393         // EDX = Digits (actually DL needed)\r
18394         // ECX = @Result\r
18396         PUSH      0\r
18397         ADD       ESP, -0Ch\r
18399         PUSH      EBX\r
18400         PUSH      ECX\r
18402         LEA       EBX, [ESP+8+0Fh]  // EBX := @Buf[ 15 ]\r
18403         AND       EDX, $F\r
18405 @@loop: DEC       EBX\r
18406         DEC       EDX\r
18408         PUSH      EAX\r
18409         {$IFDEF PARANOIA}\r
18410         DB $24, $0F\r
18411         {$ELSE}\r
18412         AND       AL, 0Fh\r
18413         {$ENDIF}\r
18414         {$IFDEF PARANOIA}\r
18415         DB $3C, 9\r
18416         {$ELSE}\r
18417         CMP       AL, 9\r
18418         {$ENDIF}\r
18419         JA        @@10\r
18420         {$IFDEF PARANOIA}\r
18421         DB $04, 30h-41h+0Ah\r
18422         {$ELSE}\r
18423         ADD       AL,30h-41h+0Ah\r
18424         {$ENDIF}\r
18425 @@10:\r
18426         {$IFDEF PARANOIA}\r
18427         DB $04, 41h-0Ah\r
18428         {$ELSE}\r
18429         ADD       AL,41h-0Ah\r
18430         {$ENDIF}\r
18431         MOV       byte ptr [EBX], AL\r
18432         POP       EAX\r
18433         SHR       EAX, 4\r
18435         JNZ       @@loop\r
18437         TEST      EDX, EDX\r
18438         JG        @@loop\r
18440         POP       EAX      // EAX = @Result\r
18441         MOV       EDX, EBX // EDX = @resulting string\r
18442         CALL      System.@LStrFromPChar\r
18444         POP       EBX\r
18445         ADD       ESP, 10h\r
18447 {== by KSer - to test it only.\r
18448 function Int2Hex( Value : DWord; Digits : Integer ) : shortString;\r
18449 asm\r
18450         MOV       [ECX], DL\r
18451         XADD      EDX, ECX\r
18452 @@loop1:\r
18453         PUSH      EAX\r
18454         db   $24, $0F    // and  al,$0F\r
18455         AAM\r
18456         //AAD\r
18457         DB $D5, $11\r
18458         db   $04, $30    // add  al,$30\r
18459         MOV       [EDX], AL\r
18460         POP       EAX\r
18461         SHR       EAX, 4\r
18462         DEC       EDX\r
18463         LOOP      @@loop1\r
18465 end;\r
18466 {$ELSE ASM_VERSION} //Pascal (mixed)\r
18467 function Int2Hex( Value : DWord; Digits : Integer ) : String;\r
18468 var Buf: array[ 0..8 ] of Char;\r
18469     Dest : PChar;\r
18471     function HexDigit( B : Byte ) : Char;\r
18472     {$IFDEF F_P}\r
18473     const\r
18474       HexDigitChr: array[ 0..15 ] of Char = ( '0','1','2','3','4','5','6','7',\r
18475                                               '8','9','A','B','C','D','E','F' );\r
18476     begin\r
18477       Result := HexDigitChr[ B and $F ];\r
18478     end;\r
18479     {$ELSE DELPHI}\r
18480     asm\r
18481             {$IFDEF PARANOIA}\r
18482              DB $3C,9\r
18483              {$ELSE}\r
18484              CMP  AL,9\r
18485              {$ENDIF}\r
18486              JA   @@1\r
18487              {$IFDEF PARANOIA}\r
18488              DB $04, $30-$41+$0A\r
18489              {$ELSE}\r
18490              ADD  AL,30h-41h+0Ah\r
18491              {$ENDIF}\r
18492     @@1:\r
18493              {$IFDEF PARANOIA}\r
18494              DB $04, $41-$0A\r
18495              {$ELSE}\r
18496              ADD  AL,41h-0Ah\r
18497              {$ENDIF}\r
18498     end;\r
18499     {$ENDIF F_P/DELPHI}\r
18500 begin\r
18501   Dest := @Buf[ 8 ];\r
18502   Dest^ := #0;\r
18503   repeat\r
18504     Dec( Dest );\r
18505     Dest^ := '0';\r
18506     if Value <> 0 then\r
18507     begin\r
18508       Dest^ := HexDigit( Value and $F );\r
18509       Value := Value shr 4;\r
18510     end;\r
18511     Dec( Digits );\r
18512   until (Value = 0) and (Digits <= 0);\r
18513   Result := Dest;\r
18514 end;\r
18515 {$ENDIF ASM_VERSION}\r
18516 //[END Int2Hex]\r
18518 //[FUNCTION Hex2Int]\r
18519 {$IFDEF ASM_VERSION}\r
18520 function Hex2Int( const Value : String) : Integer;\r
18521 asm\r
18522         CALL     EAX2PChar\r
18523         PUSH     ESI\r
18524         XCHG     ESI, EAX\r
18525         XOR      EDX, EDX\r
18526         TEST     ESI, ESI\r
18527         JE       @@exit\r
18528         LODSB\r
18529         {$IFDEF PARANOIA}\r
18530         DB $3C, '$'\r
18531         {$ELSE}\r
18532         CMP      AL, '$'\r
18533         {$ENDIF}\r
18534         JNE      @@1\r
18535 @@0:    LODSB\r
18536 @@1:    TEST     AL, AL\r
18537         JE       @@exit\r
18538         {$IFDEF PARANOIA}\r
18539         DB $2C, '0'\r
18540         {$ELSE}\r
18541         SUB      AL, '0'\r
18542         {$ENDIF}\r
18543         {$IFDEF PARANOIA}\r
18544         DB $3C, 9\r
18545         {$ELSE}\r
18546         CMP      AL, '9' - '0'\r
18547         {$ENDIF}\r
18548         JBE      @@3\r
18550         {$IFDEF PARANOIA}\r
18551         DB $2C, $11\r
18552         {$ELSE}\r
18553         SUB      AL, 'A' - '0'\r
18554         {$ENDIF}\r
18555         {$IFDEF PARANOIA}\r
18556         DB $3C, 5\r
18557         {$ELSE}\r
18558         CMP      AL, 'F' - 'A'\r
18559         {$ENDIF}\r
18560         JBE      @@2\r
18562         {$IFDEF PARANOIA}\r
18563         DB $2C, 32\r
18564         {$ELSE}\r
18565         SUB      AL, 32\r
18566         {$ENDIF}\r
18567         {$IFDEF PARANOIA}\r
18568         DB $3C, 5\r
18569         {$ELSE}\r
18570         CMP      AL, 'F' - 'A'\r
18571         {$ENDIF}\r
18572         JA       @@exit\r
18573 @@2:\r
18574         {$IFDEF PARANOIA}\r
18575         DB $04, 0Ah\r
18576         {$ELSE}\r
18577         ADD      AL, 0Ah\r
18578         {$ENDIF}\r
18579 @@3:\r
18580         SHL      EDX, 4\r
18581         ADD      DL, AL\r
18582         JMP      @@0\r
18584 @@exit: XCHG     EAX, EDX\r
18585         POP      ESI\r
18586 end;\r
18587 {$ELSE ASM_VERSION} //Pascal\r
18588 function Hex2Int( const Value : String) : Integer;\r
18589 var I : Integer;\r
18590 begin\r
18591   Result := 0;\r
18592   I := 1;\r
18593   if Value = '' then Exit;\r
18594   if Value[ 1 ] = '$' then Inc( I );\r
18595   while I <= Length( Value ) do\r
18596   begin\r
18597     if Value[ I ] in [ '0'..'9' ] then\r
18598        Result := (Result shl 4) or (Ord(Value[I]) - Ord('0'))\r
18599     else\r
18600     if Value[ I ] in [ 'A'..'F' ] then\r
18601        Result := (Result shl 4) or (Ord(Value[I]) - Ord('A') + 10)\r
18602     else\r
18603     if Value[ I ] in [ 'a'..'f' ] then\r
18604        Result := (Result shl 4) or (Ord(Value[I]) - Ord('a') + 10)\r
18605     else\r
18606       break;\r
18607     Inc( I );\r
18608   end;\r
18609 end;\r
18610 {$ENDIF ASM_VERSION}\r
18611 //[END Hex2Int]\r
18613 //[FUNCTION Octal2Int]\r
18614 function Octal2Int( const Value: String ) : Integer;\r
18615 var I: Integer;\r
18616 begin\r
18617   Result := 0;\r
18618   for I := 1 to Length( Value ) do\r
18619   begin\r
18620     if Value[ I ] in [ '0'..'7' ] then\r
18621       Result := Result * 8 + Ord( Value[ I ] ) - Ord( '0' )\r
18622     else break;\r
18623   end;\r
18624 end;\r
18625 //[END Octal2Int]\r
18627 //[FUNCTION Binary2Int]\r
18628 function Binary2Int( const Value: String ) : Integer;\r
18629 var I: Integer;\r
18630 begin\r
18631   Result := 0;\r
18632   for I := 1 to Length( Value ) do\r
18633   begin\r
18634     if Value[ I ] in [ '0'..'1' ] then\r
18635       Result := Result * 2 + Ord( Value[ I ] ) - Ord( '0' )\r
18636     else break;\r
18637   end;\r
18638 end;\r
18639 //[END Binary2Int]\r
18641 //[FUNCTION cHex2Int]\r
18642 {$IFDEF ASM_VERSION}\r
18643 function cHex2Int( const Value : String) : Integer;\r
18644 asm\r
18645      TEST  EAX, EAX\r
18646      JZ    @@exit\r
18647      CMP   word ptr [EAX], '0x'\r
18648      JZ    @@skip_2_chars\r
18649      CMP   word ptr [EAX], '0X'\r
18650      JNZ   @@2Hex2Int\r
18651 @@skip_2_chars:\r
18652      INC   EAX\r
18653      INC   EAX\r
18654 @@2Hex2Int:\r
18655      JMP   Hex2Int\r
18656 @@exit:\r
18657 end;\r
18658 {$ELSE ASM_VERSION}\r
18659 function cHex2Int( const Value : String) : Integer;\r
18660 begin\r
18661   if StrEq( Copy( Value, 1, 2 ), '0x' ) then\r
18662     Result := Hex2Int( CopyEnd( Value, 3 ) )\r
18663   else Result := Hex2Int( Value );\r
18664 end;\r
18665 {$ENDIF ASM_VERSION}\r
18666 //[END cHex2Int]\r
18668 //[FUNCTION Int2Str]\r
18669 {$IFDEF ASM_VERSION}\r
18670 function Int2Str( Value : Integer ) : String;\r
18671 asm\r
18672         XOR       ECX, ECX\r
18673         PUSH      ECX\r
18674         ADD       ESP, -0Ch\r
18676         PUSH      EBX\r
18677         LEA       EBX, [ESP + 15 + 4]\r
18678         PUSH      EDX\r
18679         CMP       EAX, ECX\r
18680         PUSHFD\r
18681         JGE       @@1\r
18682         NEG       EAX\r
18683 @@1:\r
18684         MOV       CL, 10\r
18686 @@2:\r
18687         DEC       EBX\r
18688         XOR       EDX, EDX\r
18689         DIV       ECX\r
18690         ADD       DL, 30h\r
18691         MOV       [EBX], DL\r
18692         TEST      EAX, EAX\r
18693         JNZ       @@2\r
18695         POPFD\r
18696         JGE       @@3\r
18698         DEC       EBX\r
18699         MOV       byte ptr [EBX], '-'\r
18700 @@3:\r
18701         POP       EAX\r
18702         MOV       EDX, EBX\r
18703         CALL      System.@LStrFromPChar\r
18705         POP       EBX\r
18706         ADD       ESP, 10h\r
18707 end;\r
18708 {$ELSE ASM_VERSION} //Pascal\r
18709 function Int2Str( Value : Integer ) : String;\r
18710 var Buf : array[ 0..15 ] of Char;\r
18711     Dst : PChar;\r
18712     Minus : Boolean;\r
18713     D: DWORD;\r
18714 begin\r
18715   Dst := @Buf[ 15 ];\r
18716   Dst^ := #0;\r
18717   Minus := False;\r
18718   if Value < 0 then\r
18719   begin\r
18720     Value := -Value;\r
18721     Minus := True;\r
18722   end;\r
18723   D := Value;\r
18724   repeat\r
18725     Dec( Dst );\r
18726     Dst^ := Char( (D mod 10) + Byte( '0' ) );\r
18727     D := D div 10;\r
18728   until D = 0;\r
18729   if Minus then\r
18730   begin\r
18731     Dec( Dst );\r
18732     Dst^ := '-';\r
18733   end;\r
18734   Result := Dst;\r
18735 end;\r
18736 {$ENDIF ASM_VERSION}\r
18737 //[END Int2Str]\r
18739 //[function UInt2Str]\r
18740 function UInt2Str( Value: DWORD ): String;\r
18741 var Buf : array[ 0..15 ] of Char;\r
18742     Dst : PChar;\r
18743     D: DWORD;\r
18744 begin\r
18745   Dst := @Buf[ 15 ];\r
18746   Dst^ := #0;\r
18747   D := Value;\r
18748   repeat\r
18749     Dec( Dst );\r
18750     Dst^ := Char( (D mod 10) + Byte( '0' ) );\r
18751     D := D div 10;\r
18752   until D = 0;\r
18753   Result := Dst;\r
18754 end;\r
18756 //[function Int2StrEx]\r
18757 function Int2StrEx( Value, MinWidth: Integer ): String;\r
18758 begin\r
18759   Result := Int2Str( Value );\r
18760   while Length( Result ) < MinWidth do\r
18761     Result := ' ' + Result;\r
18762 end;\r
18764 //[function Int2Rome]\r
18765 function Int2Rome( Value: Integer ): String;\r
18766 const RomeDigs: String = 'IVXLCDMT';\r
18767   function RomeNum( N, FromIdx: Integer ): String;\r
18768   begin\r
18769     CASE N OF\r
18770     1, 2, 3:    Result := StrRepeat( RomeDigs[ FromIdx ], N );\r
18771     4:          Result := RomeDigs[ FromIdx ] + RomeDigs[ FromIdx + 1 ];\r
18772     5, 6, 7, 8: Result := RomeDigs[ FromIdx + 1 ] + StrRepeat( RomeDigs[ FromIdx ],\r
18773                        N - 5 );\r
18774     9:          Result := RomeDigs[ FromIdx ] + RomeDigs[ FromIdx + 2 ]\r
18775     else Result := '';\r
18776     END;\r
18777   end;\r
18778 var I, J: Integer;\r
18779 begin\r
18780   Result := '';\r
18781   if Value < 1 then Exit;\r
18782   if Value > 8999 then Exit;\r
18783   // maximum possible is TMMMCMXCIX, i.e. 8999\r
18784   J := 1;\r
18785   for I := 1 to 3 do\r
18786   begin\r
18787     Result := RomeNum( Value mod 10, J ) + Result;\r
18788     Value := Value div 10;\r
18789     if Value = 0 then Exit;\r
18790     Inc( J, 2 );\r
18791   end;\r
18792 end;\r
18794 //[FUNCTION Int2Ths]\r
18795 {$IFDEF ASM_VERSION}\r
18796 function Int2Ths( I : Integer ) : String;\r
18797 asm\r
18798         PUSH     EBP\r
18799         MOV      EBP, ESP\r
18800         PUSH     EAX\r
18801         PUSH     EDX\r
18802         CALL     Int2Str\r
18803         POP      EDX\r
18804         POP      EAX\r
18805         CMP      EAX, 1000\r
18806         JL       @@Exit\r
18807         PUSH     EDX\r
18808         MOV      EAX, [EDX]\r
18809         PUSH     EAX\r
18810         CALL     System.@LStrLen         // EAX = Length(Result)\r
18811         POP      EDX\r
18812         PUSH     EDX                     // EDX = @Result[ 1 ]\r
18813         XOR      ECX, ECX\r
18815 @@1:\r
18816         ROL      ECX, 8\r
18817         DEC      EAX\r
18818         MOV      CL, [EDX+EAX]\r
18819         JZ       @@fin\r
18820         CMP      ECX, 300000h\r
18821         JL       @@1\r
18823         PUSH     ECX\r
18824         XOR      ECX, ECX\r
18825         MOV      CL, ','\r
18826         JMP      @@1\r
18828 @@fin:  CMP      CX, ',-'\r
18829         JNE      @@fin1\r
18830         MOV      CH, 0                   // this corrects -,ddd,...\r
18831 @@fin1: CMP      ECX, 01000000h\r
18832         JGE      @@fin2\r
18833         INC      EAX\r
18834         ROL      ECX, 8\r
18835         JMP      @@fin1\r
18836 @@fin2: PUSH     ECX\r
18838         LEA      EDX, [ESP+EAX]\r
18839         MOV      EAX, [EBP-4]\r
18840         CALL     System.@LStrFromPChar\r
18841 @@Exit:\r
18842         MOV      ESP, EBP\r
18843         POP      EBP\r
18844 end;\r
18845 {$ELSE ASM_VERSION} //Pascal\r
18846 function Int2Ths( I : Integer ) : String;\r
18847 var S : String;\r
18848 begin\r
18849   S := Int2Str( I );\r
18850   Result := '';\r
18851   while S <> '' do\r
18852   begin\r
18853     if Result <> '' then\r
18854        Result := ',' + Result;\r
18855     Result := CopyTail( S, 3 ) + Result;\r
18856     S := Copy( S, 1, Length( S ) - 3 );\r
18857   end;\r
18858   if Copy( Result, 1, 2 ) = '-,' then\r
18859      Result := '-' + CopyEnd( Result, 3 );\r
18860 end;\r
18861 {$ENDIF ASM_VERSION}\r
18862 //[END Int2Ths]\r
18864 //[FUNCTION Int2Digs]\r
18865 {$IFDEF ASM_VERSION}\r
18866 function Int2Digs( Value, Digits : Integer ) : String;\r
18867 asm\r
18868         PUSH     EBP\r
18869         MOV      EBP, ESP\r
18870         PUSH     EDX             // [EBP-4] = Digits\r
18871         PUSH     ECX\r
18872         MOV      EDX, ECX\r
18873         CALL     Int2Str\r
18874         POP      ECX\r
18875         PUSH     ECX             // [EBP-8] = @Result\r
18876         MOV      EAX, [ECX]\r
18877         PUSH     EAX\r
18878         CALL     System.@LStrLen\r
18879         POP      EDX             // EDX = @Result[1]\r
18880         MOV      ECX, EAX        // ECX = Length( Result )\r
18881         ADD      EAX, EAX\r
18882         SUB      ESP, EAX\r
18883         MOV      EAX, ESP\r
18884         PUSHAD\r
18885         CALL     StrCopy\r
18886         POPAD\r
18887         MOV      EDX, EAX\r
18888         ADD      ESP, -100\r
18889         CMP      byte ptr [EDX], '-'\r
18890         PUSHFD\r
18891         JNE      @@1\r
18892         INC      EDX\r
18893 @@1:\r
18894         MOV      EAX, [EBP-4]    // EAX = Digits\r
18895         CMP      ECX, EAX\r
18896         JGE      @@2\r
18897         DEC      EDX\r
18898         MOV      byte ptr [EDX], '0'\r
18899         INC      ECX\r
18900         JMP      @@1\r
18901 @@2:\r
18902         POPFD\r
18903         JNE      @@3\r
18904         DEC      EDX\r
18905         MOV      byte ptr [EDX], '-'\r
18906 @@3:\r
18907         MOV      EAX, [EBP-8]\r
18908         CALL     System.@LStrFromPChar\r
18909         MOV      ESP, EBP\r
18910         POP      EBP\r
18911 end;\r
18912 {$ELSE ASM_VERSION} //Pascal\r
18913 function Int2Digs( Value, Digits : Integer ) : String;\r
18914 var M : String;\r
18915 begin\r
18916   Result := Int2Str( Value );\r
18917   M := '';\r
18918   if Value < 0 then\r
18919   begin\r
18920     M := '-';\r
18921     Result := CopyEnd( Result, 2 );\r
18922   end;\r
18923   if Digits >= 0 then\r
18924     while Length( M + Result ) < Digits do\r
18925           Result := '0' + Result\r
18926   else\r
18927     while Length( Result ) < -Digits do\r
18928           Result := '0' + Result;\r
18929   Result := M + Result;\r
18930 end;\r
18931 {$ENDIF ASM_VERSION}\r
18932 //[END Int2Digs]\r
18934 //[FUNCTION Num2Bytes]\r
18935 {$IFDEF ASM_VERSION}\r
18936 function Num2Bytes( Value : Double ) : String;\r
18937 asm\r
18938         PUSH     EBX\r
18939         PUSH     ESI\r
18940         PUSH     EDI\r
18941         MOV      EBX, ESP\r
18942         MOV      ESI, EAX\r
18944         MOV      ECX, 4\r
18945         MOV      EDX, 'TGMk'\r
18946 @@1:\r
18947         FLD      [Value]\r
18948 @@10:\r
18949         FICOM    dword ptr [@@1024]\r
18950         FSTSW    AX\r
18951         SAHF\r
18952         JB       @@2\r
18954         FIDIV    dword ptr [@@1024]\r
18955         FST      [Value]\r
18956         WAIT\r
18958         TEST     DL, 20h\r
18959         JE       @@ror\r
18960         AND      DL, not 20h\r
18961         JMP      @@nxt\r
18962 @@1024: DD       1024\r
18963 @@100:  DD       100\r
18965 @@ror:\r
18966         ROR      EDX, 8\r
18967 @@nxt:\r
18968         LOOP     @@10\r
18969 @@2:\r
18970         TEST     DL, 20h\r
18971         JZ       @@3\r
18972         MOV      DL, 0\r
18973 @@3:    MOV      DH, 0\r
18974         PUSH     DX\r
18975         MOV      EDI, ESP\r
18977         FLD      ST(0)\r
18978         CALL     System.@TRUNC\r
18979         {$IFDEF _D2orD3}\r
18980         PUSH     0\r
18981         {$ELSE}\r
18982         PUSH     EDX\r
18983         {$ENDIF}\r
18984         PUSH     EAX\r
18985         FILD     qword ptr [ESP]\r
18986         POP      EDX\r
18987         POP      EDX\r
18989         MOV      EDX, ESI\r
18990         CALL     Int2Str\r
18992         FSUBP    ST(1), ST\r
18993         FIMUL    dword ptr [@@100]\r
18994         CALL     System.@TRUNC\r
18996         TEST     EAX, EAX\r
18997         JZ       @@4\r
18999         XOR      ECX, ECX\r
19000         MOV      CL, 0Ah\r
19001         CDQ\r
19002         IDIV     ECX\r
19003         TEST     EDX, EDX\r
19004         JZ       @@5\r
19006         MOV      AH, DL\r
19007         SHL      EAX, 16\r
19008         ADD      EAX, '00. '\r
19009         PUSH     EAX\r
19010         MOV      EDI, ESP\r
19011         INC      EDI\r
19012         JMP      @@4\r
19014 @@5:    SHL      EAX, 8\r
19015         ADD      AX, '0.'\r
19016         PUSH     AX\r
19017         MOV      EDI, ESP\r
19019 @@4:\r
19020         MOV      EAX, [ESI]\r
19021         CALL     System.@LStrLen\r
19022         ADD      ESP, -100\r
19024         SUB      EDI, EAX\r
19025         PUSH     ESI\r
19026         PUSH     EDI\r
19027         MOV      ESI, [ESI]\r
19028         MOV      ECX, EAX\r
19029         REP      MOVSB\r
19031         POP      EDX\r
19032         POP      EAX\r
19033         CALL     System.@LStrFromPChar\r
19035         MOV      ESP, EBX\r
19036         POP      EDI\r
19037         POP      ESI\r
19038         POP      EBX\r
19039 end;\r
19040 {$ELSE ASM_VERSION} //Pascal\r
19041 function Num2Bytes( Value : Double ) : String;\r
19042 const Suffix = 'KMGT';\r
19043 var V, I : Integer;\r
19044 begin\r
19045   Result := '';\r
19046   I := 0;\r
19047   while (Value >= 1024) and (I < 4) do\r
19048   begin\r
19049     Inc( I );\r
19050     Value := Value / 1024.0;\r
19051   end;\r
19052   Result := Int2Str( Trunc( Value ) );\r
19053   V := Trunc( (Value - Trunc( Value )) * 100 );\r
19054   if V <> 0 then\r
19055   begin\r
19056     if (V mod 10) = 0 then\r
19057        V := V div 10;\r
19058     Result := Result + ',' + Int2Str( V );\r
19059   end;\r
19060   if I > 0 then\r
19061      Result := Result + Suffix[ I ];\r
19062 end;\r
19063 {$ENDIF ASM_VERSION}\r
19064 //[END Num2Bytes]\r
19066 //[FUNCTION S2Int]\r
19067 {$IFDEF ASM_VERSION}\r
19068 function S2Int( S: PChar ): Integer;\r
19069 asm\r
19070         XCHG     EDX, EAX\r
19071         XOR      EAX, EAX\r
19072         TEST     EDX, EDX\r
19073         JZ       @@exit\r
19075         XOR      ECX, ECX\r
19076         MOV      CL, [EDX]\r
19077         INC      EDX\r
19078         CMP      CL, '-'\r
19079         PUSHFD\r
19080         JE       @@0\r
19081 @@1:    CMP      CL, '+'\r
19082         JNE      @@2\r
19083 @@0:    MOV      CL, [EDX]\r
19084         INC      EDX\r
19085 @@2:    SUB      CL, '0'\r
19086         CMP      CL, '9'-'0'\r
19087         JA       @@fin\r
19088         LEA      EAX, [EAX+EAX*4] //\r
19089         LEA      EAX, [ECX+EAX*2] //\r
19090         JMP      @@0\r
19091 @@fin:  POPFD\r
19092         JNE      @@exit\r
19093         NEG      EAX\r
19094 @@exit:\r
19095 end;\r
19096 {$ELSE ASM_VERSION} //Pascal\r
19097 function S2Int( S: PChar ): Integer;\r
19098 var M : Integer;\r
19099 begin\r
19100    Result := 0;\r
19101    if S = '' then Exit;\r
19102    M := 1;\r
19103    if S^ = '-' then\r
19104    begin\r
19105       M := -1;\r
19106       Inc( S );\r
19107    end\r
19108      else\r
19109    if S^ = '+' then\r
19110      Inc( S );\r
19111    while S^ in [ '0'..'9' ] do\r
19112    begin\r
19113       Result := Result * 10 + Integer( S^ ) - Integer( '0' );\r
19114       Inc( S );\r
19115    end;\r
19116    if M < 0 then\r
19117       Result := -Result;\r
19118 end;\r
19119 {$ENDIF ASM_VERSION}\r
19120 //[END S2Int]\r
19122 //[FUNCTION Str2Int]\r
19123 {$IFDEF ASM_VERSION}\r
19124 function Str2Int(const Value : String) : Integer;\r
19125 asm\r
19126         CALL     EAX2PChar\r
19127         CALL     S2Int\r
19128 end;\r
19129 {$ELSE ASM_VERSION} //Pascal\r
19130 function Str2Int(const Value : String) : Integer;\r
19131 begin\r
19132   Result := S2Int( PChar( Value ) );\r
19133 end;\r
19134 {$ENDIF ASM_VERSION}\r
19135 //[END Str2Int]\r
19137 //[function StrCopy]\r
19138 function StrCopy( Dest, Source: PChar ): PChar; assembler;\r
19139 asm\r
19140   {$IFDEF F_P}\r
19141         MOV     EAX, [Dest]\r
19142         MOV     EDX, [Source]\r
19143   {$ENDIF F_P}\r
19144         PUSH    EDI\r
19145         PUSH    ESI\r
19146         MOV     ESI,EAX\r
19147         MOV     EDI,EDX\r
19148         OR      ECX, -1\r
19149         XOR     AL,AL\r
19150         REPNE   SCASB\r
19151         NOT     ECX\r
19152         MOV     EDI,ESI\r
19153         MOV     ESI,EDX\r
19154         MOV     EDX,ECX\r
19155         MOV     EAX,EDI\r
19156         SHR     ECX,2\r
19157         REP     MOVSD\r
19158         MOV     ECX,EDX\r
19159         AND     ECX,3\r
19160         REP     MOVSB\r
19161         POP     ESI\r
19162         POP     EDI\r
19163 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
19165 function StrCat( Dest, Source: PChar ): PChar;\r
19166 begin\r
19167   StrCopy( StrScan( Dest, #0 ), Source );\r
19168   Result := Dest;\r
19169 end;\r
19171 //[function StrScan]\r
19172 function StrScan(Str: PChar; Chr: Char): PChar; assembler;\r
19173 asm\r
19174   {$IFDEF F_P}\r
19175   MOV   EAX, [Str]\r
19176   MOVZX EDX, [Chr]\r
19177   {$ENDIF}\r
19178         PUSH    EDI\r
19179         PUSH    EAX\r
19180         MOV     EDI,Str\r
19181         OR      ECX, -1\r
19182         XOR     AL,AL\r
19183         REPNE   SCASB\r
19184         NOT     ECX\r
19185         POP     EDI\r
19186         XCHG    EAX, EDX\r
19187         REPNE   SCASB\r
19189         XCHG    EAX, EDI\r
19190         POP     EDI\r
19192         JE      @@1\r
19193         XOR     EAX, EAX\r
19194         RET\r
19196 @@1:    DEC     EAX\r
19197 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
19199 //[function StrRScan]\r
19200 function StrRScan(const Str: PChar; Chr: Char): PChar; assembler;\r
19201 asm\r
19202   {$IFDEF F_P}\r
19203         MOV     EAX, [Str]\r
19204         MOVZX   EDX, [Chr]\r
19205   {$ENDIF F_P}\r
19206         PUSH    EDI\r
19207         MOV     EDI,Str\r
19208         MOV     ECX,0FFFFFFFFH\r
19209         XOR     AL,AL\r
19210         REPNE   SCASB\r
19211         NOT     ECX\r
19212         STD\r
19213         DEC     EDI\r
19214         MOV     AL,Chr\r
19215         REPNE   SCASB\r
19216         MOV     EAX,0\r
19217         JNE     @@1\r
19218         MOV     EAX,EDI\r
19219         INC     EAX\r
19220 @@1:    CLD\r
19221         POP     EDI\r
19222 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
19224 //[function StrScanLen]\r
19225 function StrScanLen(Str: PChar; Chr: Char; Len: Integer): PChar; assembler;\r
19226 asm\r
19227   {$IFDEF F_P}\r
19228         MOV     EAX, [Str]\r
19229         MOVZX   EDX, [Chr]\r
19230         MOV     ECX, [Len]\r
19231   {$ENDIF F_P}\r
19232         PUSH    EDI\r
19233         XCHG    EDI, EAX\r
19234         XCHG    EAX, EDX\r
19235         REPNE   SCASB\r
19237         XCHG    EAX, EDI\r
19238         POP     EDI\r
19239         { -> EAX => to next character after found or to the end of Str,\r
19240              ZF = 0 if character found. }\r
19241 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
19243 //[FUNCTION TrimLeft]\r
19244 {$IFDEF ASM_VERSION}\r
19245 function TrimLeft(const S: string): string;\r
19246 asm\r
19247         XCHG     EAX, EDX\r
19248         CALL     EDX2PChar\r
19249         DEC      EDX\r
19250 @@1:    INC      EDX\r
19251         MOVZX    ECX, byte ptr [EDX]\r
19252         JECXZ    @@fin\r
19253         CMP      CL, ' '\r
19254         JBE      @@1\r
19255 @@fin:\r
19256         CALL     System.@LStrFromPChar\r
19257 end;\r
19258 {$ELSE ASM_VERSION} //Pascal\r
19259 function TrimLeft(const S: string): string;\r
19260 var\r
19261   I, L: Integer;\r
19262 begin\r
19263   L := Length(S);\r
19264   I := 1;\r
19265   while (I <= L) and (S[I] <= ' ') do Inc(I);\r
19266   Result := Copy(S, I, Maxint);\r
19267 end;\r
19268 {$ENDIF ASM_VERSION}\r
19269 //[END TrimLeft]\r
19271 //[FUNCTION TrimRight]\r
19272 {$IFDEF ASM_VERSION}\r
19273 function TrimRight(const S: string): string;\r
19274 asm\r
19275         PUSH     EDX\r
19276         PUSH     EAX\r
19278         PUSH     EAX\r
19279         CALL     System.@LStrLen\r
19280         XCHG     EAX, [ESP]\r
19281         //CALL     System.@LStrToPChar\r
19282         CALL     EAX2PChar\r
19283         POP      ECX\r
19284         INC      ECX\r
19285 @@1:    DEC      ECX\r
19286         MOV      DL, [EAX+ECX]\r
19287         JL       @@fin\r
19288         CMP      DL, ' '\r
19289         JBE      @@1\r
19290 @@fin:\r
19291         INC      ECX\r
19292         POP      EAX\r
19293         XOR      EDX, EDX\r
19294         INC      EDX\r
19295         CALL     System.@LStrCopy\r
19296 end;\r
19297 {$ELSE ASM_VERSION} //Pascal\r
19298 function TrimRight(const S: string): string;\r
19299 var\r
19300   I: Integer;\r
19301 begin\r
19302   I := Length(S);\r
19303   while (I > 0) and (S[I] <= ' ') do Dec(I);\r
19304   Result := Copy(S, 1, I);\r
19305 end;\r
19306 {$ENDIF ASM_VERSION}\r
19307 //[END TrimRight]\r
19309 //[FUNCTION Trim]\r
19310 {$IFDEF ASM_VERSION}\r
19311 function Trim( const S : string): string;\r
19312 asm\r
19313         PUSH     EDX\r
19314         CALL     TrimRight\r
19315         POP      EDX\r
19316         MOV      EAX, [EDX]\r
19317         CALL     TrimLeft\r
19318 end;\r
19319 {$ELSE ASM_VERSION} //Pascal\r
19320 function Trim( const S : string): string;\r
19321 begin\r
19322    Result := TrimLeft( TrimRight( S ) );\r
19323 end;\r
19324 {$ENDIF ASM_VERSION}\r
19325 //[END Trim]\r
19327 //[function RemoveSpaces]\r
19328 function RemoveSpaces( const S: String ): String;\r
19329 var I: Integer;\r
19330 begin\r
19331   Result := S;\r
19332   for I := Length( S ) downto 1 do\r
19333     if S[ I ] <= ' ' then Delete( Result, I, 1 );\r
19334 end;\r
19336 //[procedure Str2LowerCase]\r
19337 procedure Str2LowerCase( S: PChar );\r
19338 asm\r
19339   {$IFDEF F_P}\r
19340         MOV      EAX, [S]\r
19341   {$ENDIF}\r
19342         XOR      ECX, ECX\r
19343 @@1:\r
19344         MOV      CL, byte ptr [EAX]\r
19345         JECXZ    @@exit\r
19346         SUB      CL, 'A'\r
19347         CMP      CL, 'Z'-'A'\r
19348         JA       @@2\r
19349         ADD      byte ptr [EAX], 32\r
19350 @@2:    INC      EAX\r
19351         JMP      @@1\r
19352 @@exit:\r
19353 end {$IFDEF F_P} [ 'EAX', 'ECX' ] {$ENDIF};\r
19355 //[FUNCTION LowerCase]\r
19356 {$IFDEF ASM_VERSION}\r
19357 function LowerCase(const S: string): string;\r
19358 asm\r
19359         PUSH     ESI\r
19360         XCHG     EAX, EDX\r
19361         PUSH     EAX\r
19362         CALL     System.@LStrAsg\r
19363         POP      EAX\r
19365         CALL     UniqueString\r
19367         PUSH     EAX\r
19368         CALL     System.@LStrLen\r
19369         POP      ESI\r
19371         XCHG     ECX, EAX\r
19373         JECXZ    @@exit\r
19375 @@go:\r
19376         LODSB\r
19377         {$IFDEF PARANOIA}\r
19378         DB $2C, 'A'\r
19379         {$ELSE}\r
19380         SUB      AL, 'A'\r
19381         {$ENDIF}\r
19382         {$IFDEF PARANOIA}\r
19383         DB $3C, 26\r
19384         {$ELSE}\r
19385         CMP      AL, 'Z'-'A'+1\r
19386         {$ENDIF}\r
19387         JNB      @@1\r
19389         ADD      byte ptr [ESI - 1], 20h\r
19390 @@1:\r
19391         LOOP     @@go\r
19392 @@exit:\r
19393         POP      ESI\r
19394 end;\r
19395 {$ELSE ASM_VERSION} //Pascal\r
19396 function LowerCase(const S: string): string;\r
19397 var I : Integer;\r
19398 begin\r
19399   Result := S;\r
19400   for I := 1 to Length( S ) do\r
19401     if Result[ I ] in [ 'A'..'Z' ] then\r
19402        Inc( Result[ I ], 32 );\r
19403 end;\r
19404 {$ENDIF ASM_VERSION}\r
19405 //[END LowerCase]\r
19407 //[FUNCTION UpperCase]\r
19408 {$IFDEF ASM_VERSION}\r
19409 function UpperCase(const S: string): string;\r
19410 asm\r
19411         PUSH     ESI\r
19412         XCHG     EAX, EDX\r
19413         PUSH     EAX\r
19414         CALL     System.@LStrAsg\r
19415         POP      EAX\r
19417         CALL     UniqueString\r
19419         PUSH     EAX\r
19420         CALL     System.@LStrLen\r
19421         POP      ESI\r
19423         XCHG     ECX, EAX\r
19425         JECXZ    @@exit\r
19427 @@go:\r
19428         LODSB\r
19429         {$IFDEF PARANOIA}\r
19430         DB $2C, 'a'\r
19431         {$ELSE}\r
19432         SUB      AL, 'a'\r
19433         {$ENDIF}\r
19434         {$IFDEF PARANOIA}\r
19435         DB $3C, $1A\r
19436         {$ELSE}\r
19437         CMP      AL, 'z'-'a'+1\r
19438         {$ENDIF}\r
19439         JNB      @@1\r
19441         SUB      byte ptr [ESI - 1], 20h\r
19442 @@1:\r
19443         LOOP     @@go\r
19444 @@exit:\r
19445         POP      ESI\r
19446 end;\r
19447 {$ELSE ASM_VERSION} //Pascal\r
19448 function UpperCase(const S: string): string;\r
19449 var I : Integer;\r
19450 begin\r
19451   Result := S;\r
19452   for I := 1 to Length( S ) do\r
19453     if Result[ I ] in [ 'a'..'z' ] then\r
19454        Dec( Result[ I ], 32 );\r
19455 end;\r
19456 {$ENDIF ASM_VERSION}\r
19457 //[END UpperCase]\r
19459 {$IFDEF F_P}\r
19460 //[function DummyStrFun]\r
19461 function DummyStrFun( const S: String ): String;\r
19462 begin\r
19463   Result := S;\r
19464 end;\r
19465 {$ENDIF F_P}\r
19467 //[FUNCTION CopyEnd]\r
19468 {$IFDEF ASM_VERSION}\r
19469 function CopyEnd( const S : String; Idx : Integer ) : String;\r
19470 asm\r
19471         PUSH     ECX\r
19472         PUSH     EAX\r
19473         PUSH     EDX\r
19475         CALL     System.@LStrLen\r
19477         POP      EDX\r
19478         TEST     EDX, EDX\r
19479         JG       @@1\r
19480         XOR      EDX, EDX\r
19481         INC      EDX\r
19482 @@1:\r
19483         SUB      EAX, EDX\r
19484         MOV      ECX, EAX\r
19486         POP      EAX\r
19487         JGE      @@ret_end\r
19489         POP      EAX\r
19490         JL       System.@LStrClr\r
19492 @@ret_end:\r
19493         INC      ECX\r
19494         CALL     System.@LStrCopy\r
19495 end;\r
19496 {$ELSE ASM_VERSION} //Pascal\r
19497 function CopyEnd( const S : String; Idx : Integer ) : String;\r
19498 begin\r
19499   Result := Copy( S, Idx, MaxInt );\r
19500 end;\r
19501 {$ENDIF ASM_VERSION}\r
19502 //[END CopyEnd]\r
19504 //[FUNCTION CopyTail]\r
19505 {$IFDEF ASM_VERSION}\r
19506 function CopyTail( const S : String; Len : Integer ) : String;\r
19507 asm\r
19508         PUSH     ECX\r
19509         PUSH     EAX\r
19510           PUSH     EDX\r
19511             CALL     System.@LStrLen\r
19512           POP      ECX\r
19513           CMP      ECX, EAX\r
19514           {$IFDEF USE_CMOV}\r
19515           CMOVG    ECX, EAX\r
19516           {$ELSE}\r
19517           JLE      @@1\r
19518           MOV      ECX, EAX\r
19519 @@1:      {$ENDIF}\r
19521         MOV      EDX, EAX\r
19522         SUB      EDX, ECX\r
19523         INC      EDX\r
19524         POP      EAX\r
19525         CALL     System.@LStrCopy\r
19526 end;\r
19527 {$ELSE ASM_VERSION} //Pascal\r
19528 function CopyTail( const S : String; Len : Integer ) : String;\r
19529 var L : Integer;\r
19530 begin\r
19531   L := Length( S );\r
19532   if L < Len then\r
19533      Len := L;\r
19534   Result := '';\r
19535   if Len = 0 then Exit;\r
19536   Result := Copy( S, L - Len + 1, Len );\r
19537 end;\r
19538 {$ENDIF ASM_VERSION}\r
19539 //[END CopyTail]\r
19541 //[PROCEDURE DeleteTail]\r
19542 {$IFDEF ASM_VERSION}\r
19543 procedure DeleteTail( var S : String; Len : Integer );\r
19544 asm\r
19545         PUSH     EAX\r
19546         PUSH     EDX\r
19547         MOV      EAX, [EAX]\r
19548         CALL     System.@LStrLen\r
19549         POP      ECX\r
19550         CMP      ECX, EAX\r
19551         {$IFDEF USE_CMOV}\r
19552         CMOVG    ECX, EAX\r
19553         {$ELSE}\r
19554         JLE      @@1\r
19555         MOV      ECX, EAX\r
19556 @@1:    {$ENDIF}\r
19558         MOV      EDX, EAX\r
19559         SUB      EDX, ECX\r
19560         INC      EDX\r
19561         POP      EAX\r
19562         CALL     System.@LStrDelete\r
19563 end;\r
19564 {$ELSE ASM_VERSION} //Pascal\r
19565 procedure DeleteTail( var S : String; Len : Integer );\r
19566 var L : Integer;\r
19567 begin\r
19568   L := Length( S );\r
19569   if Len > L then\r
19570      Len := L;\r
19571   Delete( S, L - Len + 1, Len );\r
19572 end;\r
19573 {$ENDIF ASM_VERSION}\r
19574 //[END DeleteTail]\r
19576 //[FUNCTION IndexOfChar]\r
19577 {$IFDEF ASM_VERSION}\r
19578 function IndexOfChar( const S : String; Chr : Char ) : Integer;\r
19579 asm\r
19580         //PUSH     EDX\r
19581         //CALL     System.@LStrToPChar\r
19582         //POP      EDX\r
19583         CALL     EAX2PChar\r
19584         PUSH     EAX\r
19585         CALL     StrScan\r
19586         POP      EDX\r
19587         TEST     EAX, EAX\r
19588         JE       @@exit__1\r
19589         SUB      EAX, EDX\r
19590         INC      EAX\r
19591         RET\r
19592 @@exit__1:\r
19593         DEC      EAX\r
19594 end;\r
19595 {$ELSE ASM_VERSION} //Pascal\r
19596 function IndexOfChar( const S : String; Chr : Char ) : Integer;\r
19597 var P, F : PChar;\r
19598 begin\r
19599    P := PChar( S );\r
19600    F := StrScan( P, Chr );\r
19601    Result := -1;\r
19602    if F = nil then Exit;\r
19603    Result := Integer( F ) - Integer( P ) + 1;\r
19604 end;\r
19605 {$ENDIF ASM_VERSION}\r
19606 //[END IndexOfChar]\r
19608 //[FUNCTION IndexOfCharsMin]\r
19609 {$IFDEF ASM_VERSION}\r
19610 function IndexOfCharsMin( const S, Chars : String ) : Integer;\r
19611 asm\r
19612         PUSH     ESI\r
19613         PUSH     EAX\r
19614         CALL     EDX2PChar\r
19615         MOV      ESI, EDX\r
19617         XOR      ECX, ECX\r
19618         DEC      ECX\r
19620 @@1:    LODSB\r
19621         TEST     AL, AL\r
19622         JZ       @@exit\r
19624         XCHG     EDX, EAX\r
19625         POP      EAX\r
19626         PUSH     EAX\r
19628         PUSH     ECX\r
19629         CALL     IndexOfChar\r
19630         POP      ECX\r
19631         TEST     EAX, EAX\r
19632         JLE      @@1\r
19634         TEST     ECX, ECX\r
19635         JLE      @@2\r
19636         CMP      EAX, ECX\r
19637         JGE      @@1\r
19638 @@2:    //XCHG     ECX, EAX\r
19639         //JMP      @@1\r
19641 @@exit: XCHG     EAX, ECX\r
19642           JL     @@1\r
19643         POP      ECX\r
19644         POP      ESI\r
19645 end;\r
19646 {$ELSE ASM_VERSION} //Pascal\r
19647 function IndexOfCharsMin( const S, Chars : String ) : Integer;\r
19648 var I, J : Integer;\r
19649 begin\r
19650   Result := -1;\r
19651   for I := 1 to Length( Chars ) do\r
19652   begin\r
19653     J := IndexOfChar( S, Chars[ I ] );\r
19654     if J > 0 then\r
19655     begin\r
19656       if (Result < 0) or (J < Result) then\r
19657          Result := J;\r
19658     end;\r
19659   end;\r
19660 end;\r
19661 {$ENDIF ASM_VERSION}\r
19662 //[END IndexOfCharsMin]\r
19664 {$IFNDEF _FPC}\r
19665 {$IFNDEF _D2}\r
19666 //[function IndexOfWideCharsMin]\r
19667 function IndexOfWideCharsMin( const S, Chars : WideString ) : Integer;\r
19668 var I, J : Integer;\r
19669 begin\r
19670   Result := -1;\r
19671   for I := 1 to Length( Chars ) do\r
19672   begin\r
19673     J := pos( Chars[ I ], S );\r
19674     if J > 0 then\r
19675     begin\r
19676       if (Result < 0) or (J < Result) then\r
19677          Result := J;\r
19678     end;\r
19679   end;\r
19680 end;\r
19681 {$ENDIF _D2}\r
19682 {$ENDIF _FPC}\r
19684 //[FUNCTION IndexOfStr]\r
19685 {$IFDEF ASM_VERSION}\r
19686 function IndexOfStr( const S, Sub : String ) : Integer;\r
19687 asm\r
19688         PUSH     EBX\r
19689         PUSH     ESI\r
19690         PUSH     EDI\r
19692         PUSH     EAX\r
19693         MOV      EAX, EDX\r
19694         PUSH     EDX\r
19695         CALL     System.@LStrLen\r
19696         MOV      EDI, EAX\r
19697         POP      EAX\r
19698         //CALL     System.@LStrToPChar\r
19699         CALL     EAX2PChar\r
19700         MOV      BL, [EAX]\r
19701         XCHG     EAX, [ESP]\r
19702         //CALL     System.@LStrToPChar\r
19703         CALL     EAX2PChar\r
19705         MOV      ESI, EAX\r
19707         DEC      EAX\r
19708 @@1:    INC      EAX\r
19709         MOV      DL, BL\r
19710         CALL     StrScan\r
19711         TEST     EAX, EAX\r
19712         JE       @@exit__1\r
19714         POP      EDX\r
19715         PUSH     EDX\r
19717         MOV      ECX, EDI\r
19718         PUSH     EAX\r
19719         CALL     StrLComp\r
19720         POP      EAX\r
19721         JNE      @@1\r
19723         SUB      EAX, ESI\r
19724         INC      EAX\r
19725         JMP      @@exit\r
19727 @@exit__1:\r
19728         DEC      EAX\r
19729 @@exit:\r
19730         POP      EDX\r
19731         POP      EDI\r
19732         POP      ESI\r
19733         POP      EBX\r
19734 end;\r
19735 {$ELSE ASM_VERSION} //Pascal\r
19736 function IndexOfStr( const S, Sub : String ) : Integer;\r
19737 var I : Integer;\r
19738 begin\r
19739   Result := Length( S );\r
19740   if Sub = '' then Exit;\r
19741   Result := 0;\r
19742   if S = '' then Exit;\r
19743   if Length( Sub ) > Length( S ) then Exit;\r
19744   Result := 1;\r
19745   while Result + Length( Sub ) - 1 <= Length( S ) do\r
19746   begin\r
19747     I := IndexOfChar( CopyEnd( S, Result ), Sub[ 1 ] );\r
19748     if I <= 0 then break;\r
19749     Result := Result + I - 1;\r
19750     if Result <= 0 then Exit;\r
19751     if Copy( S, Result, Length( Sub ) ) = Sub then Exit;\r
19752     Inc( Result );\r
19753   end;\r
19754   Result := -1;\r
19755 end;\r
19756 {$ENDIF ASM_VERSION}\r
19757 //[END IndexOfStr]\r
19759 //[FUNCTION Parse]\r
19760 {$IFDEF ASM_VERSION} //???\r
19761 function Parse( var S : String; const Separators : String ) : String;\r
19762 asm\r
19763          PUSH    EBX\r
19764          PUSH    EDI\r
19765          MOV     EBX, EAX\r
19767          PUSH    ECX\r
19768          MOV     EAX, [EBX]\r
19769          CALL    IndexOfCharsMin\r
19770          INC     EAX\r
19771          JNE     @@1\r
19772          MOV     EAX, [EBX]\r
19773          CALL    System.@LStrLen\r
19774          INC     EAX\r
19775          INC     EAX\r
19776 @@1:\r
19777          DEC     EAX\r
19778          MOV     EDI, EAX\r
19779          MOV     ECX, EAX\r
19780          DEC     ECX\r
19781          XOR     EDX, EDX\r
19782          INC     EDX\r
19783          MOV     EAX, [EBX]\r
19784          CALL    System.@LStrCopy\r
19786          MOV     EAX, [EBX]\r
19787          MOV     EDX, EDI\r
19788          INC     EDX\r
19789          MOV     ECX, EBX\r
19790          CALL    CopyEnd\r
19792          POP     EDI\r
19793          POP     EBX\r
19794 end;\r
19795 {$ELSE ASM_VERSION} //Pascal\r
19796 function Parse( var S : String; const Separators : String ) : String;\r
19797 var Pos : Integer;\r
19798 begin\r
19799   Pos := IndexOfCharsMin( S, Separators );\r
19800   if Pos <= 0 then\r
19801      Pos := Length( S ) + 1;\r
19802   Result := S;\r
19803   S := Copy( Result, Pos + 1, MaxInt );\r
19804   Result := Copy( Result, 1, Pos - 1 );\r
19805 end;\r
19806 {$ENDIF ASM_VERSION}\r
19807 //[END Parse]\r
19809 {$IFNDEF _FPC}\r
19810 {$IFNDEF _D2}\r
19811 //[function WParse]\r
19812 function WParse( var S : WideString; const Separators : WideString ) : WideString;\r
19813 var Pos : Integer;\r
19814 begin\r
19815   Pos := IndexOfWideCharsMin( S, Separators );\r
19816   if Pos <= 0 then\r
19817      Pos := Length( S ) + 1;\r
19818   Result := S;\r
19819   S := Copy( Result, Pos + 1, MaxInt );\r
19820   Result := Copy( Result, 1, Pos - 1 );\r
19821 end;\r
19822 {$ENDIF _D2}\r
19823 {$ENDIF _FPC}\r
19825 //[function ParsePascalString]\r
19826 function ParsePascalString( var S : String; const Separators : String ) : String;\r
19827 var Pos, Idx : Integer;\r
19828     Hex, Spc : boolean;\r
19829     procedure SkipSpaces;\r
19830     begin\r
19831       if not Spc then\r
19832         while (Length( S ) >= Pos) and (S[ Pos ] = ' ') do\r
19833           Inc( Pos );\r
19834     end;\r
19835 var Buf : String;\r
19836     Ou, Val : Integer;\r
19837 begin\r
19838   Pos := 1;\r
19839   Spc := IndexOfChar( Separators, ' ' ) >= 0;\r
19840   SkipSpaces;\r
19841   if Length( S ) < Pos then\r
19842   begin\r
19843     Result := S;\r
19844     S := '';\r
19845     exit;\r
19846   end;\r
19847   Buf := PChar( S );\r
19848   Ou := 1;\r
19849   if S[ Pos ] in [ '''', '#' ] then\r
19850   begin\r
19851     // skip here string constant expression\r
19852     while Pos <= Length( S ) do\r
19853     begin\r
19854       if S[ Pos ] = '''' then\r
19855       begin\r
19856         Inc( Pos );\r
19857         while Pos <= Length( S ) do\r
19858         begin\r
19859           if S[ Pos ] = '''' then\r
19860             if (Pos = Length( S )) or (S[ Pos+1 ] <> '''') then\r
19861             begin\r
19862               Inc( Pos );\r
19863               break;\r
19864             end\r
19865             else Inc( Pos );\r
19866           Buf[ Ou ] := S[ Pos ];\r
19867           Inc( Ou );\r
19868           Inc( Pos );\r
19869         end;\r
19870         //if Pos < Length( S ) then Inc( Pos );\r
19871       end\r
19872          else\r
19873       if S[ Pos ] = '#' then\r
19874       begin\r
19875         Inc( Pos ); Hex := False; Val := 0;\r
19876         if (Pos < Length( S )) and (S[ Pos ] = '$') then\r
19877         begin\r
19878            Inc( Pos ); Hex := True;\r
19879         end;\r
19880         Dec( Pos );\r
19881         while Pos < Length( S ) do\r
19882         begin\r
19883           Inc( Pos );\r
19884           if (S[ Pos ] in [ '0'..'9' ]) or\r
19885              Hex and (S[ Pos ] in [ 'a'..'f', 'A'..'F' ]) then\r
19886           begin\r
19887             if Hex then\r
19888                Val := Val * 16\r
19889             else\r
19890                Val := Val * 10;\r
19891             if S[ Pos ] <= '9' then\r
19892                Val := Val + Integer( S[ Pos ] ) - Integer( '0' )\r
19893             else\r
19894             if S[ Pos ] <= 'F' then\r
19895                Val := Val + 10 + Integer( S[ Pos ] ) - Integer( 'A' )\r
19896             else\r
19897                Val := Val + 10 + Integer( S[ Pos ] ) - Integer( 'a' );\r
19898             continue;\r
19899           end;\r
19900           Inc( Pos ); break;\r
19901         end;\r
19902         Buf[ Ou ] := Char( Val );\r
19903         Inc( Ou );\r
19904       end\r
19905          else break;\r
19906       SkipSpaces;\r
19907       if S[ Pos ] <> '+' then break;\r
19908       SkipSpaces;\r
19909     end;\r
19910   end;\r
19911   Idx := IndexOfCharsMin( CopyEnd( S, Pos ), Separators );\r
19912   if Idx <= 0 then\r
19913   begin\r
19914     Result := Copy( Buf, 1, Ou - 1 ) + CopyEnd( S, Pos );\r
19915     S := '';\r
19916   end\r
19917      else\r
19918   begin\r
19919     Result := Copy( Buf, 1, Ou - 1 ) + Copy( S, Pos, Idx - 1 );\r
19920     S := CopyEnd( S, Pos + Idx );\r
19921   end;\r
19922 end;\r
19924 //[function String2PascalStrExpr]\r
19925 function String2PascalStrExpr( const S : String ) : String;\r
19926 var I, Strt : Integer;\r
19927   function String2DoubleQuotas( const S : String ) : String;\r
19928   var I, J : Integer;\r
19929   begin\r
19930     if IndexOfChar( S, '''' ) <= 0 then\r
19931        Result := S\r
19932     else\r
19933     begin\r
19934       J := 0;\r
19935       for I := 1 to Length( S ) do\r
19936         if S[ I ] = '''' then Inc( J );\r
19937       SetLength( Result, Length( S ) + J );\r
19938       J := 1;\r
19939       for I := 1 to Length( S ) do\r
19940       begin\r
19941         Result[ J ] := S[ I ];\r
19942         Inc( J );\r
19943         if S[ I ] = '''' then\r
19944         begin\r
19945           Result[ J ] := '''';\r
19946           Inc( J );\r
19947         end;\r
19948       end;\r
19949     end;\r
19950   end;\r
19951 begin\r
19952   Result := '';\r
19953   if S = '' then\r
19954   begin\r
19955     Result := '''''';\r
19956     exit;\r
19957   end;\r
19958   Strt := 1;\r
19959   for I := 1 to Length( S ) + 1 do\r
19960   begin\r
19961     if (I > Length( S )) or (S[ I ] < ' ') then\r
19962     begin\r
19963       if (I > Strt) and (I > 1) then\r
19964       begin\r
19965         if Result <> '' then\r
19966            Result := Result + '+';\r
19967         Result := Result + '''' + String2DoubleQuotas( Copy( S, Strt, I - Strt ) ) + '''';\r
19968       end;\r
19969       if I > Length( S ) then break;\r
19970       if Result <> '' then\r
19971          Result := Result + '+'\r
19972       else\r
19973          Result := Result + '''''+';\r
19974       Result := Result + '#' + Int2Str( Integer( S[ I ] ) );\r
19975       Strt := I + 1;\r
19976     end;\r
19977   end;\r
19978 end;\r
19980 //[function CompareMem]\r
19981 function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;\r
19982 asm\r
19983   {$IFDEF F_P}\r
19984         MOV     EAX, [P1]\r
19985         MOV     EDX, [P2]\r
19986         MOV     ECX, [Length]\r
19987   {$ENDIF}\r
19988         PUSH    ESI\r
19989         PUSH    EDI\r
19990         MOV     ESI,P1\r
19991         MOV     EDI,P2\r
19992         MOV     EDX,ECX\r
19993         XOR     EAX,EAX\r
19994         AND     EDX,3\r
19995         SHR     ECX,1\r
19996         SHR     ECX,1\r
19997         REPE    CMPSD\r
19998         JNE     @@2\r
19999         MOV     ECX,EDX\r
20000         REPE    CMPSB\r
20001         JNE     @@2\r
20002 @@1:    INC     EAX\r
20003 @@2:    POP     EDI\r
20004         POP     ESI\r
20005 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
20007 //[FUNCTION AllocMem]\r
20008 {$IFDEF ASM_VERSION}\r
20009 function AllocMem( Size : Integer ) : Pointer;\r
20010 asm     //cmd    //opd\r
20011         TEST     EAX, EAX\r
20012         JZ       @@exit\r
20013         PUSH     EAX\r
20014         CALL     System.@GetMem\r
20015         POP      EDX\r
20016         PUSH     EAX\r
20017         MOV      CL, 0\r
20018         CALL     System.@FillChar\r
20019         POP      EAX\r
20020 @@exit:\r
20021 end;\r
20022 {$ELSE ASM_VERSION} //Pascal\r
20023 function AllocMem( Size : Integer ) : Pointer;\r
20024 begin\r
20025    Result := nil;\r
20026    if Size > 0 then\r
20027    begin\r
20028      GetMem( Result, Size );\r
20029      FillChar( Result^, Size, 0 );\r
20030    end;\r
20031 end;\r
20032 {$ENDIF ASM_VERSION}\r
20033 //[END AllocMem]\r
20035 //[procedure DisposeMem]\r
20036 procedure DisposeMem( var Addr : Pointer );\r
20037 begin\r
20038    if Addr <> nil then\r
20039       FreeMem( Addr );\r
20040    Addr := nil;\r
20041 end;\r
20043 //[function AnsiUpperCase]\r
20044 function AnsiUpperCase(const S: string): string;\r
20045 var\r
20046   Len: Integer;\r
20047 begin\r
20048   Len := Length(S);\r
20049   SetString(Result, PChar(S), Len);\r
20050   if Len > 0 then CharUpperBuff(Pointer(Result), Len);\r
20051 end;\r
20053 //[function AnsiLowerCase]\r
20054 function AnsiLowerCase(const S: string): string;\r
20055 var\r
20056   Len: Integer;\r
20057 begin\r
20058   Len := Length(S);\r
20059   SetString(Result, PChar(S), Len);\r
20060   if Len > 0 then CharLowerBuff(Pointer(Result), Len);\r
20061 end;\r
20063 {$IFNDEF _D2}\r
20064 {$IFNDEF _FPC}\r
20065 //[function WAnsiUpperCase]\r
20066 function WAnsiUpperCase(const S: WideString): WideString;\r
20067 var Len: Integer;\r
20068 begin\r
20069   Len := Length(S);\r
20070   Result := S;\r
20071   if Len > 0 then CharUpperBuffW(Pointer(Result), Len);\r
20072 end;\r
20074 //[function WAnsiLowerCase]\r
20075 function WAnsiLowerCase(const S: WideString): WideString;\r
20076 var Len: Integer;\r
20077 begin\r
20078   Len := Length(S);\r
20079   Result := S;\r
20080   if Len > 0 then CharLowerBuffW(Pointer(Result), Len);\r
20081 end;\r
20082 {$ENDIF _FPC}\r
20083 {$ENDIF _D2}\r
20085 //[function AnsiCompareStr]\r
20086 function AnsiCompareStr(const S1, S2: string): Integer;\r
20087 begin\r
20088   Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), -1,\r
20089     PChar(S2), -1 ) - 2;\r
20090 end;\r
20092 //[function _AnsiCompareStr]\r
20093 function _AnsiCompareStr(S1, S2: PChar): Integer;\r
20094 begin\r
20095   Result := CompareString( LOCALE_USER_DEFAULT, 0, S1, -1,\r
20096                            S2, -1) - 2;\r
20097 end;\r
20099 //[function AnsiCompareStrNoCase]\r
20100 function AnsiCompareStrNoCase(const S1, S2: string): Integer;\r
20101 begin\r
20102   Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1), -1,\r
20103     PChar(S2), -1 ) - 2;\r
20104 end;\r
20106 //[function _AnsiCompareStrNoCase]\r
20107 function _AnsiCompareStrNoCase(S1, S2: PChar): Integer;\r
20108 begin\r
20109   Result := CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE, S1, -1,\r
20110                            S2, -1) - 2;\r
20111 end;\r
20113 //[function AnsiCompareText]\r
20114 function AnsiCompareText( const S1, S2: String ): Integer;\r
20115 begin\r
20116   Result := AnsiCompareStrNoCase( S1, S2 );\r
20117 end;\r
20119 //[function StrLCopy]\r
20120 function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar; assembler;\r
20121 asm\r
20122   {$IFDEF F_P}\r
20123         MOV     EAX, [Dest]\r
20124         MOV     EDX, [Source]\r
20125         MOV     ECX, [MaxLen]\r
20126   {$ENDIF F_P}\r
20127         PUSH    EDI\r
20128         PUSH    ESI\r
20129         PUSH    EBX\r
20130         MOV     ESI,EAX\r
20131         MOV     EDI,EDX\r
20132         MOV     EBX,ECX\r
20133         XOR     AL,AL\r
20134         TEST    ECX,ECX\r
20135         JZ      @@1\r
20136         REPNE   SCASB\r
20137         JNE     @@1\r
20138         INC     ECX\r
20139 @@1:    SUB     EBX,ECX\r
20140         MOV     EDI,ESI\r
20141         MOV     ESI,EDX\r
20142         MOV     EDX,EDI\r
20143         MOV     ECX,EBX\r
20144         SHR     ECX,2\r
20145         REP     MOVSD\r
20146         MOV     ECX,EBX\r
20147         AND     ECX,3\r
20148         REP     MOVSB\r
20149         STOSB\r
20150         MOV     EAX,EDX\r
20151         POP     EBX\r
20152         POP     ESI\r
20153         POP     EDI\r
20154 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
20156 //[FUNCTION StrPCopy]\r
20157 {$IFDEF ASM_VERSION}\r
20158 function StrPCopy(Dest: PChar; const Source: string): PChar;\r
20159 asm\r
20160         PUSH     EAX\r
20161         MOV      EAX, EDX\r
20162         CALL     System.@LStrLen\r
20163         MOV      ECX, EAX\r
20164         POP      EAX\r
20165         CALL     EDX2PChar\r
20166         CALL     StrLCopy\r
20167 end;\r
20168 {$ELSE ASM_VERSION} //Pascal\r
20169 function StrPCopy(Dest: PChar; const Source: string): PChar;\r
20170 begin\r
20171   Result := StrLCopy(Dest, PChar(Source), Length(Source));\r
20172 end;\r
20173 {$ENDIF ASM_VERSION}\r
20174 //[END StrPCopy]\r
20176 //[FUNCTION StrEq]\r
20177 {$IFDEF ASM_VERSION}\r
20178 function StrEq( const S1, S2 : String ) : Boolean;\r
20179 asm\r
20180         TEST     EDX, EDX\r
20181         JNZ      @@1\r
20182 @@0:    CMP      EAX, EDX\r
20183         JMP      @@exit\r
20184 @@1:    TEST     EAX, EAX\r
20185         JZ       @@0\r
20186         MOV      ECX, [EAX-4]\r
20187         CMP      ECX, [EDX-4]\r
20188         JNE      @@exit\r
20189         PUSH     EAX\r
20190         PUSH     EDX\r
20191         PUSH     0\r
20192         MOV      EDX, ESP\r
20193         CALL     LowerCase\r
20194         PUSH     0\r
20195         MOV      EAX, [ESP + 8]\r
20196         MOV      EDX, ESP\r
20197         CALL     LowerCase\r
20198         POP      EAX\r
20199         POP      EDX\r
20200         PUSH     EDX\r
20201         PUSH     EAX\r
20202         CALL     System.@LStrCmp\r
20203         MOV      EAX, ESP\r
20204         PUSHFD\r
20205         XOR      EDX, EDX\r
20206         MOV      DL, 2\r
20207         CALL     System.@LStrArrayClr\r
20208         POPFD\r
20209         POP      EDX\r
20210         POP      EDX\r
20211         POP      EDX\r
20212         POP      EDX\r
20213 @@exit:\r
20214         SETZ     AL\r
20215 end;\r
20216 {$ELSE ASM_VERSION} //Pascal\r
20217 function StrEq( const S1, S2 : String ) : Boolean;\r
20218 begin\r
20219   Result := (Length( S1 ) = Length( S2 )) and\r
20220             (LowerCase( S1 ) = LowerCase( S2 ));\r
20221 end;\r
20222 {$ENDIF ASM_VERSION}\r
20223 //[END StrEq]\r
20225 //[FUNCTION AnsiEq]\r
20226 {$IFDEF ASM_VERSION}\r
20227 function AnsiEq( const S1, S2 : String ) : Boolean;\r
20228 asm\r
20229         CALL     AnsiCompareStrNoCase\r
20230         TEST     EAX, EAX\r
20231         SETZ     AL\r
20232 end;\r
20233 {$ELSE ASM_VERSION} //Pascal\r
20234 function AnsiEq( const S1, S2 : String ) : Boolean;\r
20235 begin\r
20236   Result := AnsiCompareStrNoCase( S1, S2 ) = 0;\r
20237 end;\r
20238 {$ENDIF ASM_VERSION}\r
20239 //[END AnsiEq]\r
20241 {$IFNDEF _D2}\r
20242 {$IFNDEF _FPC}\r
20243 //[function WAnsiEq]\r
20244 function WAnsiEq( const S1, S2 : WideString ) : Boolean;\r
20245 begin\r
20246   Result := WAnsiLowerCase( S1 )=WAnsiLowerCase( S2 );\r
20247 end;\r
20248 {$ENDIF _FPC}\r
20249 {$ENDIF _D2}\r
20251 //[FUNCTION StrIn]\r
20252 {$IFDEF ASM_VERSION}\r
20253 function StrIn(const S: String; const A: array of String): Boolean;\r
20254 asm\r
20255 @@1:\r
20256         TEST     ECX, ECX\r
20257         JL       @@ret_0\r
20259         PUSH     EDX\r
20260         MOV      EDX, [EDX+ECX*4]\r
20261         DEC      ECX\r
20263         PUSH     ECX\r
20264         PUSH     EAX\r
20265         CALL     StrEq\r
20266         DEC      AL\r
20267         POP      EAX\r
20268         POP      ECX\r
20270         POP      EDX\r
20271         JNZ      @@1\r
20273         MOV      AL, 1\r
20274         RET\r
20276 @@ret_0:XOR      EAX, EAX\r
20277 end;\r
20278 {$ELSE ASM_VERSION} //Pascal\r
20279 function StrIn(const S: String; const A: array of String): Boolean;\r
20280 var I : Integer;\r
20281 begin\r
20282   for I := Low( A ) to High( A ) do\r
20283       if StrEq( S, A[ I ] ) then\r
20284       begin\r
20285         Result := True;\r
20286         Exit;\r
20287       end;\r
20288   Result := False;\r
20289 end;\r
20290 {$ENDIF ASM_VERSION}\r
20291 //[END StrIn]\r
20293 {$IFNDEF _D2}\r
20294 {$IFNDEF _FPC}\r
20295 //[function WStrIn]\r
20296 function WStrIn( const S : WideString; const A : array of WideString ) : Boolean;\r
20297 var I : Integer;\r
20298 begin\r
20299   for I := Low( A ) to High( A ) do\r
20300       if WAnsiEq( S, A[ I ] ) then\r
20301       begin\r
20302         Result := True;\r
20303         Exit;\r
20304       end;\r
20305   Result := False;\r
20306 end;\r
20307 {$ENDIF _FPC}\r
20308 {$ENDIF _D2}\r
20310 //[function StrIs]\r
20311 function StrIs( const S : String; const A : array of String; var Idx: Integer ) : Boolean;\r
20312 var I : Integer;\r
20313 begin\r
20314   Idx := -1;\r
20315   for I := Low( A ) to High( A ) do\r
20316       if StrEq( S, A[ I ] ) then\r
20317       begin\r
20318         Idx := I;\r
20319         Result := True;\r
20320         Exit;\r
20321       end;\r
20322   Result := False;\r
20323 end;\r
20325 //[function IntIn]\r
20326 function IntIn( Value: Integer; const List: array of Integer ): Boolean;\r
20327 var I: Integer;\r
20328 begin\r
20329   Result := FALSE;\r
20330   for I := 0 to High( List ) do\r
20331   begin\r
20332     if Value = List[ I ] then\r
20333     begin\r
20334       Result := TRUE;\r
20335       break;\r
20336     end;\r
20337   end;\r
20338 end;\r
20340 //[FUNCTION _StrSatisfy]\r
20341 {$IFDEF ASM_VERSION}\r
20342 function _StrSatisfy( S, Mask : PChar ) : Boolean;\r
20343 asm\r
20344     TEST EAX, EAX\r
20345     JZ   @@exit\r
20346         XCHG     ECX, EAX\r
20347         //       EDX <- Mask\r
20348         //       ECX <- S\r
20349         XOR      EAX, EAX\r
20350         MOV      AL, '*'\r
20351 @@rest_satisfy:\r
20352         PUSH     ECX\r
20353         PUSH     EDX\r
20355 @@nx_char:\r
20356         MOV      AH, [EDX]\r
20357         OR       AH, [ECX]\r
20358         JZ       @@fin //@@ret_true\r
20360         MOV      AH, 0\r
20362         CMP      word ptr [EDX], AX //'*'\r
20363         JE       @@fin //@@ret_true\r
20365         CMP      byte ptr [ECX], AH\r
20366         JNE      @@10\r
20368         DEC      EDX\r
20369 @@1:\r
20370         INC      EDX\r
20371         CMP      byte ptr [EDX], AL //'*'\r
20372         JE       @@1\r
20373         //CMP      byte ptr [EDX], '?'\r
20374         //JE       @@1\r
20376         CMP      byte ptr [EDX], AH\r
20377         SETZ     AL\r
20378         JMP      @@fin\r
20380 @@10:   CMP      byte ptr [EDX], AH\r
20381         JE       @@ret_false\r
20383         CMP      byte ptr [EDX], '?'\r
20384         JNE      @@11\r
20386 @@go_nx_char:\r
20387         INC      ECX\r
20388         INC      EDX\r
20389         JMP      @@nx_char\r
20391 @@11:\r
20392         CMP      byte ptr [EDX], AL //'*'\r
20393         JNE      @@20\r
20395         INC      EDX\r
20396 @@12:   CMP      byte ptr [ECX], AH\r
20397         JE       @@ret_false\r
20399         CALL     @@rest_satisfy\r
20400         TEST     AL, AL\r
20401         JNE      @@fin\r
20402         MOV      AL, '*'\r
20404         INC      ECX\r
20405         JMP      @@12\r
20407 @@20:   MOV      AH, [EDX]\r
20408         XOR      AH, [ECX]\r
20410         JE       @@go_nx_char\r
20411 @@ret_false:\r
20412         XOR      EAX, EAX\r
20414 @@fin:\r
20415         POP      EDX\r
20416         POP      ECX\r
20417 @@exit:\r
20418 end;\r
20419 {$ELSE ASM_VERSION} //Pascal\r
20420 function _StrSatisfy( S, Mask : PChar ) : Boolean;\r
20421 label next_char;\r
20422 begin\r
20423 next_char:\r
20424   Result := True;\r
20425   if (S^ = #0) and (Mask^ = #0) then exit;\r
20426   if (Mask^ = '*') and (Mask[1] = #0) then exit;\r
20427   if S^ = #0 then\r
20428   begin\r
20429     while Mask^ = '*' do\r
20430           Inc( Mask );\r
20431     Result := Mask^ = #0;\r
20432     exit;\r
20433   end;\r
20434   Result := False;\r
20435   if Mask^ = #0 then exit;\r
20436   if Mask^ = '?' then\r
20437   begin\r
20438     Inc( S ); Inc( Mask ); goto next_char;\r
20439   end;\r
20440   if Mask^ = '*' then\r
20441   begin\r
20442     Inc( Mask );\r
20443     while S^ <> #0 do\r
20444     begin\r
20445       Result := _StrSatisfy( S, Mask );\r
20446       if Result then exit;\r
20447       Inc( S );\r
20448     end;\r
20449     exit; // (Result = False)\r
20450   end;\r
20451   Result := S^ = Mask^;\r
20452   Inc( S ); Inc( Mask );\r
20453   if Result then goto next_char;\r
20454 end;\r
20455 {$ENDIF ASM_VERSION}\r
20456 //[END _StrSatisfy]\r
20458 //[FUNCTION StrSatisfy]\r
20459 {$IFDEF ASM_VERSION}\r
20460 function StrSatisfy( const S, Mask: String ): Boolean;\r
20461 asm\r
20462         PUSH     ESI\r
20463         XCHG     ESI, EAX\r
20464         PUSH     0\r
20465         XCHG     EAX, EDX\r
20466         CALL     EAX2PChar\r
20467         MOV      EDX, ESP\r
20469         CMP      byte ptr [EAX], 0\r
20470         JZ       @@0\r
20471         CALL     AnsiLowerCase\r
20472 @@0:\r
20473         XCHG     EAX, ESI\r
20474         PUSH     0\r
20475         CALL     EAX2PChar\r
20476         MOV      EDX, ESP\r
20478         CMP      byte ptr [EAX], 0\r
20479         JZ       @@1\r
20480         CALL     AnsiLowerCase\r
20481 @@1:\r
20482         POP      EAX\r
20483         POP      EDX\r
20484         PUSH     EDX\r
20485         PUSH     EAX\r
20486         CALL     _StrSatisfy\r
20488         XCHG     ESI, EAX\r
20490         CALL     RemoveStr\r
20491         CALL     RemoveStr\r
20492         XCHG     EAX, ESI\r
20494         POP      ESI\r
20495 end;\r
20496 {$ELSE ASM_VERSION} //Pascal\r
20497 function StrSatisfy( const S, Mask: String ): Boolean;\r
20498 begin\r
20499   Result := _StrSatisfy( PChar( AnsiLowerCase( S ) ),\r
20500                          PChar( AnsiLowerCase( Mask ) ) );\r
20501 end;\r
20502 {$ENDIF ASM_VERSION}\r
20503 //[END StrSatisfy]\r
20505 //[FUNCTION _2StrSatisfy]\r
20506 {$IFDEF ASM_VERSION}\r
20507 function _2StrSatisfy( S, Mask: PChar ): Boolean;\r
20508 asm     //     //\r
20509         PUSH   EBX\r
20510         XCHG   EBX, EAX\r
20511         PUSH   0\r
20512         MOV    EAX, ESP\r
20513         CALL   System.@LStrFromPChar\r
20514         PUSH   0\r
20515         MOV    EAX, ESP\r
20516         MOV    EDX, EBX\r
20517         CALL   System.@LStrFromPChar\r
20518         POP    EAX\r
20519         POP    EDX\r
20520         PUSH   EDX\r
20521         PUSH   EAX\r
20522         CALL   StrSatisfy\r
20523         XCHG   EBX, EAX\r
20524         CALL   RemoveStr\r
20525         CALL   RemoveStr\r
20526         XCHG   EAX, EBX\r
20527         POP    EBX\r
20528 end;\r
20529 {$ELSE ASM_VERSION} // Pascal\r
20530 function _2StrSatisfy( S, Mask: PChar ): Boolean;\r
20531 begin\r
20532   Result := StrSatisfy( S, Mask );\r
20533 end;\r
20534 {$ENDIF ASM_VERSION}\r
20535 //[END _2StrSatisfy]\r
20537 //[function StrReplace]\r
20538 function StrReplace( var S: String; const From, ReplTo: String ): Boolean;\r
20539 var I: Integer;\r
20540 begin\r
20541   I := pos( From, S );\r
20542   if I > 0 then\r
20543   begin\r
20544     S := Copy( S, 1, I - 1 ) + ReplTo + CopyEnd( S, I + Length( From ) );\r
20545     Result := TRUE;\r
20546   end\r
20547   else Result := FALSE;\r
20548 end;\r
20550 {-}\r
20551 {$IFDEF _FPC}\r
20552 //[procedure SetLengthW]\r
20553 procedure SetLengthW( var W: WideString; NewLength: Integer );\r
20554 begin\r
20555   while Length( W ) < NewLength do\r
20556     W := W + ' ' + W;\r
20557   if Length( W ) > NewLength then\r
20558     Delete( W, NewLength + 1, Length( W ) - NewLength );\r
20559 end;\r
20561 //[function CopyW]\r
20562 function CopyW( const W: WideString; From, Count: Integer ): WideString;\r
20563 begin\r
20564   Result := '';\r
20565   if Count <= 0 then Exit;\r
20566   SetLengthW( Result, Count );\r
20567   Move( W[ From ], Result[ 1 ], Count * Sizeof( WideChar ) );\r
20568 end;\r
20570 //[function posW]\r
20571 function posW( const S1, S2: String ): Integer;\r
20572 var I, L1: Integer;\r
20573 begin\r
20574   L1 := Length( S1 );\r
20575   for I := 1 to Length( S2 )-L1+1 do\r
20576   begin\r
20577     if Copy( S2, I, L1 ) = S1 then\r
20578     begin\r
20579       Result := I;\r
20580       Exit;\r
20581     end;\r
20582   end;\r
20583   Result := 0;\r
20584 end;\r
20585 {$ENDIF _FPC}\r
20587 {$IFNDEF _FPC}\r
20588 {$IFNDEF _D2}\r
20589 //[function WStrReplace]\r
20590 function WStrReplace( var S: WideString; const From, ReplTo: WideString ): Boolean;\r
20591 var I: Integer;\r
20592 begin\r
20593   I := pos( From, S );\r
20594   if I > 0 then\r
20595   begin\r
20596     S := Copy( S, 1, I - 1 ) + ReplTo + Copy( S, I + Length( From ), MaxInt );\r
20597     Result := TRUE;\r
20598   end\r
20599   else Result := FALSE;\r
20600 end;\r
20602 //[function WStrRepeat]\r
20603 function WStrRepeat( const S: WideString; Count: Integer ): WideString;\r
20604 var I, L: Integer;\r
20605 begin\r
20606   L := Length( S );\r
20607   SetLength( Result, L * Count );\r
20608   for I := 0 to Count-1 do\r
20609     Move( S[ 1 ], Result[ 1 + I * L ], L * Sizeof( WideChar ) );\r
20610 end;\r
20611 {$ENDIF _D2}\r
20612 {$ENDIF _FPC}\r
20614 {+}\r
20615 //[function StrRepeat]\r
20616 function StrRepeat( const S: String; Count: Integer ): String;\r
20617 var I, L: Integer;\r
20618 begin\r
20619   L := Length( S );\r
20620   SetLength( Result, L * Count );\r
20621   for I := 0 to Count-1 do\r
20622     Move( S[ 1 ], Result[ 1 + I * L ], L );\r
20623 end;\r
20626 //[PROCEDURE NormalizeUnixText]\r
20627 {$IFDEF ASM_VERSION}\r
20628 procedure NormalizeUnixText( var S: String );\r
20629 asm     //cmd    //opd\r
20630         CMP      dword ptr [EAX], 0\r
20631         JZ       @@exit\r
20632         PUSH     EBX\r
20633         PUSH     EDI\r
20634         MOV      EBX, EAX\r
20635         CALL     UniqueString\r
20636         MOV      EDI, [EBX]\r
20637 @@1:    MOV      EAX, EDI\r
20638         CALL     System.@LStrLen\r
20639         XCHG     ECX, EAX\r
20640         MOV      AX, $0D0A\r
20642         CMP      byte ptr [EDI], AL\r
20643         JNE      @@loo\r
20644         MOV      byte ptr [EDI], AH\r
20645 @@loo:\r
20646         TEST     ECX, ECX\r
20647         JZ       @@fin\r
20648 @@loo1:\r
20649         REPNZ SCASB\r
20650         JNZ      @@fin\r
20651         CMP      byte ptr [EDI-2], AH\r
20652         JE       @@loo\r
20653         MOV      byte ptr [EDI-1], AH\r
20654         JNE      @@loo1\r
20655 @@fin:  POP      EDI\r
20656         POP      EBX\r
20657 @@exit:\r
20658 end;\r
20659 {$ELSE ASM_VERSION} //Pascal\r
20660 procedure NormalizeUnixText( var S: String );\r
20661 var I: Integer;\r
20662 begin\r
20663   if S <> '' then\r
20664   begin\r
20665     if S[ 1 ] = #10 then\r
20666       S[ 1 ] := #13;\r
20667     for I := 2 to Length(S) do\r
20668       if (S[I]=#10) and (S[I-1]<>#13) then\r
20669         S[I] := #13;\r
20670   end;\r
20671 end;\r
20672 {$ENDIF ASM_VERSION}\r
20673 //[END NormalizeUnixText]\r
20675 //[function StrComp]\r
20676 function StrComp(const Str1, Str2: PChar): Integer; assembler;\r
20677 asm\r
20678   {$IFDEF F_P}\r
20679         MOV     EAX, [Str1]\r
20680         MOV     EDX, [Str2]\r
20681   {$ENDIF F_P}\r
20682         PUSH    EDI\r
20683         PUSH    ESI\r
20684         MOV     EDI,EDX\r
20685         XCHG    ESI,EAX\r
20686         OR      ECX, -1\r
20687         XOR     EAX,EAX\r
20688         REPNE   SCASB\r
20689         NOT     ECX\r
20690         MOV     EDI,EDX\r
20691         XOR     EDX,EDX\r
20692         REPE    CMPSB\r
20693         MOV     AL,[ESI-1]\r
20694         MOV     DL,[EDI-1]\r
20695         SUB     EAX,EDX\r
20696         POP     ESI\r
20697         POP     EDI\r
20698 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
20700 function StrComp_NoCase(const Str1, Str2: PChar): Integer;\r
20701 asm\r
20702   {$IFDEF F_P}\r
20703         MOV     EAX, [Str1]\r
20704         MOV     EDX, [Str2]\r
20705   {$ENDIF F_P}\r
20706         PUSH    EDI\r
20707         PUSH    ESI\r
20708         MOV     EDI,EDX\r
20709         XCHG    ESI,EAX\r
20710         OR      ECX, -1\r
20711         XOR     EAX,EAX\r
20712         REPNE   SCASB\r
20714         NOT     ECX\r
20715         MOV     EDI,EDX\r
20716   @@0:\r
20717         XOR     EDX,EDX\r
20718         REPE    CMPSB\r
20719         MOV     AL,[ESI-1]\r
20720         MOV     AH, AL\r
20721         SUB     AH, 'a'\r
20722         CMP     AH, 25\r
20723         JA      @@1\r
20724         SUB     AL, $20\r
20725   @@1:\r
20726         MOV     DL,[EDI-1]\r
20727         MOV     AH, DL\r
20728         SUB     AH, 'a'\r
20729         CMP     AH, 25\r
20730         JA      @@2\r
20731         SUB     DL, $20\r
20732   @@2:\r
20733         MOV     AH, 0\r
20734         SUB     EAX,EDX\r
20735         JNZ     @@exit\r
20736         CMP     DL, 0\r
20737         JNZ     @@0\r
20739   @@exit:\r
20740         POP     ESI\r
20741         POP     EDI\r
20742 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
20744 //[function StrLComp_NoCase]\r
20745 function StrLComp_NoCase(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;\r
20746 asm\r
20747   {$IFDEF F_P}\r
20748         MOV     EAX, [Str1]\r
20749         MOV     EDX, [Str2]\r
20750         MOV     ECX, [MaxLen]\r
20751   {$ENDIF F_P}\r
20752         PUSH    EDI\r
20753         PUSH    ESI\r
20754         PUSH    EBX\r
20755         MOV     EDI,EDX\r
20756         MOV     ESI,EAX\r
20757         MOV     EBX,ECX\r
20758         XOR     EAX,EAX\r
20759         OR      ECX,ECX\r
20760         JE      @@exit\r
20761         REPNE   SCASB\r
20762         SUB     EBX,ECX\r
20763         MOV     ECX,EBX\r
20764         MOV     EDI,EDX\r
20765   @@0:\r
20766         XOR     EDX,EDX\r
20767         REPE    CMPSB\r
20768         MOV     AL,[ESI-1]\r
20769         MOV     AH, AL\r
20770         SUB     AH, 'a'\r
20771         CMP     AH, 25\r
20772         JA      @@1\r
20773         SUB     AL, $20\r
20774   @@1:\r
20775         MOV     DL,[EDI-1]\r
20776         MOV     AH, DL\r
20777         SUB     AH, 'a'\r
20778         CMP     AH, 25\r
20779         JA      @@2\r
20780         SUB     DL, $20\r
20781   @@2:\r
20782         MOV     AH, 0\r
20783         SUB     EAX,EDX\r
20784         JECXZ   @@exit\r
20785         JZ      @@0\r
20787   @@exit:\r
20788         POP     EBX\r
20789         POP     ESI\r
20790         POP     EDI\r
20791 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
20793 //[function StrLComp]\r
20794 function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer; assembler;\r
20795 asm\r
20796   {$IFDEF F_P}\r
20797         MOV     EAX, [Str1]\r
20798         MOV     EDX, [Str2]\r
20799         MOV     ECX, [MaxLen]\r
20800   {$ENDIF F_P}\r
20801         PUSH    EDI\r
20802         PUSH    ESI\r
20803         PUSH    EBX\r
20804         MOV     EDI,EDX\r
20805         MOV     ESI,EAX\r
20806         MOV     EBX,ECX\r
20807         XOR     EAX,EAX\r
20808         OR      ECX,ECX\r
20809         JE      @@1\r
20810         REPNE   SCASB\r
20811         SUB     EBX,ECX\r
20812         MOV     ECX,EBX\r
20813         MOV     EDI,EDX\r
20814         XOR     EDX,EDX\r
20815         REPE    CMPSB\r
20816         MOV     AL,[ESI-1]\r
20817         MOV     DL,[EDI-1]\r
20818         SUB     EAX,EDX\r
20819 @@1:    POP     EBX\r
20820         POP     ESI\r
20821         POP     EDI\r
20822 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
20824 //[function StrLen]\r
20825 function StrLen(const Str: PChar): Cardinal; assembler;\r
20826 asm\r
20827   {$IFDEF F_P}\r
20828         MOV     EAX, [Str]\r
20829   {$ENDIF F_P}\r
20830         XCHG    EAX, EDI\r
20831         XCHG    EDX, EAX\r
20832         OR      ECX, -1\r
20833         XOR     EAX, EAX\r
20834         CMP     EAX, EDI\r
20835         JE      @@exit0\r
20836         REPNE   SCASB\r
20837         DEC     EAX\r
20838         DEC     EAX\r
20839         SUB     EAX,ECX\r
20840 @@exit0:\r
20841         MOV     EDI,EDX\r
20842 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
20844 //[FUNCTION __DelimiterLast]\r
20845 {$IFDEF ASM_VERSION}\r
20846 function __DelimiterLast( Str: PChar; Delimiters: PChar ): PChar;\r
20847 asm\r
20848         PUSH     ESI\r
20850         CALL     EAX2PChar\r
20852         MOV      ESI, EDX\r
20853         MOV      EDX, EAX\r
20855 @@tolast:\r
20856         CMP      byte ptr [EAX], 0\r
20857         JZ       @@next1\r
20858         INC      EAX\r
20859         JMP      @@tolast\r
20861 @@next1:\r
20862         PUSH     EAX\r
20864 @@next:\r
20865         LODSB\r
20866         TEST     AL, AL\r
20867         JZ       @@exit\r
20869         PUSH     EDX\r
20870         XCHG     EDX, EAX\r
20871         CALL     StrRScan\r
20872         POP      EDX\r
20874         TEST     EAX, EAX\r
20875         JZ       @@next\r
20877         POP      ECX\r
20878         CMP      byte ptr [ECX], 0\r
20879         JZ       @@next1\r
20881         CMP      EAX, ECX\r
20882         JG       @@next1\r
20884         PUSH     ECX\r
20885         JLE      @@next\r
20887 @@exit: POP      EAX\r
20888         POP      ESI\r
20889 end;\r
20890 {$ELSE ASM_VERSION} //Pascal\r
20891 function __DelimiterLast( Str: PChar; Delimiters: PChar ): PChar;\r
20892 var\r
20893     P, F : PChar;\r
20894 begin\r
20895   P := Str;\r
20896   Result := P + StrLen( Str );\r
20897   while Delimiters^ <> #0 do\r
20898   begin\r
20899     F := StrRScan( P, Delimiters^ );\r
20900     if F <> nil then\r
20901     if (Result^ = #0) or (Integer(F) > Integer(Result)) then\r
20902        Result := F;\r
20903     Inc( Delimiters );\r
20904   end;\r
20905 end;\r
20906 {$ENDIF ASM_VERSION}\r
20907 //[END __DelimiterLast]\r
20909 //[function SkipSpaces]\r
20910 function SkipSpaces( P: PChar ): PChar;\r
20911 begin\r
20912   while True do\r
20913   begin\r
20914     while (P[0] <> #0) and (P[0] <= ' ') do Inc(P);\r
20915     if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break;\r
20916   end;\r
20917   Result := P;\r
20918 end;\r
20920 //[function SkipParam]\r
20921 function SkipParam(P: PChar): PChar;\r
20922 begin\r
20923   P := SkipSpaces( P );\r
20924   while P[0] > ' ' do\r
20925     if P[0] = '"' then\r
20926     begin\r
20927       Inc(P);\r
20928       while (P[0] <> #0) and (P[0] <> '"') do\r
20929         Inc(P);\r
20930       if P[0] <> #0 then Inc(P);\r
20931     end\r
20932       else\r
20933       Inc(P);\r
20934   Result := P;\r
20935 end;\r
20937 //[FUNCTION ParamStr]\r
20938 function ParamStr( Idx: Integer ): String;\r
20939 var\r
20940   P, P1: PChar;\r
20941   Buffer: array[ 0..260 ] of Char;\r
20942 begin\r
20943   if Idx = 0 then\r
20944     SetString( Result, Buffer, GetModuleFileName( 0, Buffer, Sizeof( Buffer ) ) )\r
20945   else\r
20946   begin\r
20947     P := GetCommandLine;\r
20948     repeat\r
20949       P := SkipSpaces( P );\r
20950       P1 := P;\r
20951       P := SkipParam(P);\r
20952       if Idx = 0 then Break;\r
20953       Dec(Idx);\r
20954     until (Idx < 0) or (P = P1);\r
20955     Result := Copy( P1, 1, P - P1 );\r
20956     if Length( Result ) >= 2 then\r
20957     if (Result[ 1 ] = '"') and (Result[ Length( Result ) ] = '"') then\r
20958       Result := Copy( Result, 2, Length( Result ) - 2 );\r
20959   end;\r
20960 end;\r
20961 //[END ParamStr]\r
20963 //[FUNCTION ParamCount]\r
20964 function ParamCount: Integer;\r
20965 var\r
20966   S: string;\r
20967 begin\r
20968   Result := 0;\r
20969   while True do\r
20970   begin\r
20971     S := ParamStr(Result + 1);\r
20972     if S = '' then Break;\r
20973     Inc(Result);\r
20974   end;\r
20975 end;\r
20976 //[END ParamCount]\r
20978 //[FUNCTION DelimiterLast]\r
20979 {$IFDEF ASM_VERSION}\r
20980 function DelimiterLast( const Str, Delimiters: String ): Integer;\r
20981 asm\r
20982         CALL     EAX2PChar\r
20983         CALL     EDX2PChar\r
20984         PUSH     EAX\r
20985         CALL     __DelimiterLast\r
20986         POP      EDX\r
20987         SUB      EAX, EDX\r
20988         INC      EAX\r
20989 end;\r
20990 {$ELSE ASM_VERSION} //Pascal\r
20991 function DelimiterLast( const Str, Delimiters: String ): Integer;\r
20992 var PStr: PChar;\r
20993 begin\r
20994   PStr := PChar( Str );\r
20995   Result := Integer( __DelimiterLast( PStr, PChar( Delimiters ) ) )\r
20996           - Integer( PStr )\r
20997           + 1; // {Viman}\r
20998 end;\r
20999 {$ENDIF ASM_VERSION}\r
21000 //[END DelimiterLast]\r
21002 // Thanks to Marco Bobba - Marisa Bo for this code\r
21003 //[function StrIsStartingFrom]\r
21004 function StrIsStartingFrom( Str, Pattern: PChar ): Boolean;\r
21005 asm\r
21006   {$IFDEF F_P}\r
21007         MOV     EAX, [Str]\r
21008         MOV     EDX, [Pattern]\r
21009   {$ENDIF F_P}\r
21010         XOR     ECX, ECX\r
21011       @@1:\r
21012         MOV     CL, [EDX]   // pattern[ i ]\r
21013         INC     EDX\r
21014         MOV     CH, [EAX]   // str[ i ]\r
21015         INC     EAX\r
21016         JECXZ   @@2         // str = pattern; CL = #0, CH = #0\r
21017         CMP     CL, CH\r
21018         JE      @@1\r
21019       @@2:\r
21020         TEST    CL, CL\r
21021         SETZ    AL\r
21022 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
21024 function StrIsStartingFromNoCase( Str, Pattern: PChar ): Boolean;\r
21025 asm\r
21026   {$IFDEF F_P}\r
21027         MOV     EAX, [Str]\r
21028         MOV     EDX, [Pattern]\r
21029   {$ENDIF F_P}\r
21030         XOR     ECX, ECX\r
21031       @@1:\r
21032         MOV     CL, [EDX]   // pattern[ i ]\r
21033         INC     EDX\r
21034         MOV     CH, [EAX]   // str[ i ]\r
21035         INC     EAX\r
21036         JECXZ   @@2         // str = pattern; CL = #0, CH = #0\r
21037         CMP     CL, 'a'\r
21038         JB      @@cl_ok\r
21039         CMP     CL, 'z'\r
21040         JA      @@cl_ok\r
21041         SUB     CL, 32\r
21042       @@cl_ok:\r
21043         CMP     CH, 'a'\r
21044         JB      @@ch_ok\r
21045         CMP     CH, 'z'\r
21046         JA      @@ch_ok\r
21047         SUB     CH, 32\r
21048       @@ch_ok:\r
21049         CMP     CL, CH\r
21050         JE      @@1\r
21051       @@2:\r
21052         TEST    CL, CL\r
21053         SETZ    AL\r
21054 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
21056 {$IFNDEF _FPC}\r
21057 //[FUNCTION Format]\r
21058 {$IFDEF ASM_VERSION}\r
21059 function Format( const fmt: string; params: array of const ): String;\r
21060 asm\r
21061         PUSH    ESI\r
21062         PUSH    EDI\r
21063         PUSH    EBX\r
21064         MOV     EBX, ESP\r
21065         ADD     ESP, -2048\r
21066         MOV     ESI, ESP\r
21068         INC     ECX\r
21069         JZ      @@2\r
21070 @@1:\r
21071         MOV     EDI, [EDX + ECX*8 - 8]\r
21072         PUSH    EDI\r
21073         LOOP    @@1\r
21074 @@2:\r
21075         PUSH    ESP\r
21076         PUSH    EAX\r
21077         PUSH    ESI\r
21079         CALL    wvsprintf\r
21081         MOV     EDX, ESI\r
21082         MOV     EAX, @Result\r
21083         CALL    System.@LStrFromPChar\r
21085         MOV     ESP, EBX\r
21086         POP     EBX\r
21087         POP     EDI\r
21088         POP     ESI\r
21089 end;\r
21090 {$ELSE ASM_VERSION} //Pascal\r
21091 function Format( const fmt: string; params: array of const ): String;\r
21092 var Buffer: array[ 0..2047 ] of Char;\r
21093     ElsArray, El: PDWORD;\r
21094     I : Integer;\r
21095     P : PDWORD;\r
21096 begin\r
21097   ElsArray := nil;\r
21098   if High( params ) >= 0 then\r
21099     GetMem( ElsArray, (High( params ) + 1) * sizeof( Pointer ) );\r
21100   El := ElsArray;\r
21101   for I := 0 to High( params ) do\r
21102   begin\r
21103     P := @params[ I ];\r
21104     P := Pointer( P^ );\r
21105     El^ := DWORD( P );\r
21106     Inc( El );\r
21107   end;\r
21108   wvsprintf( @Buffer[0], PChar( fmt ), PChar( ElsArray ) );\r
21109   Result := Buffer;\r
21110   if ElsArray <> nil then\r
21111      FreeMem( ElsArray );\r
21112 end;\r
21113 {$ENDIF ASM_VERSION}\r
21114 //[END Format]\r
21116 //[function LStrFromPWCharLen]\r
21117 function LStrFromPWCharLen(Source: PWideChar; Length: Integer): String;\r
21118 var\r
21119   DestLen: Integer;\r
21120   Buffer: array[0..2047] of Char;\r
21121 begin\r
21122   if Length <= 0 then\r
21123   begin\r
21124     //_LStrClr(Result);\r
21125     Result := '';\r
21126     Exit;\r
21127   end;\r
21128   if Length < SizeOf(Buffer) div 2 then\r
21129   begin\r
21130     DestLen := WideCharToMultiByte(0, 0, Source, Length,\r
21131       Buffer, SizeOf(Buffer), nil, nil);\r
21132     if DestLen > 0 then\r
21133     begin\r
21134       Result := Buffer;\r
21135       //System.LStrFromPCharLen(Result, Buffer, DestLen);\r
21136       Exit;\r
21137     end;\r
21138   end;\r
21139   DestLen := WideCharToMultiByte(0, 0, Source, Length, nil, 0, nil, nil);\r
21140   // _LStrFromPCharLen(Dest, nil, DestLen);\r
21141   SetLength( Result, DestLen );\r
21142   WideCharToMultiByte(0, 0, Source, Length, Pointer(Result), DestLen, nil, nil);\r
21143 end;\r
21145 //[function LStrFromPWChar]\r
21146 function LStrFromPWChar(Source: PWideChar): String;\r
21147 {* from Delphi5 - because D2 does not contain it. }\r
21148 asm\r
21149         PUSH    EDX\r
21150         XOR     EDX,EDX\r
21151         TEST    EAX,EAX\r
21152         JE      @@5\r
21153         PUSH    EAX\r
21154 @@0:    CMP     DX,[EAX+0]\r
21155         JE      @@4\r
21156         CMP     DX,[EAX+2]\r
21157         JE      @@3\r
21158         CMP     DX,[EAX+4]\r
21159         JE      @@2\r
21160         CMP     DX,[EAX+6]\r
21161         JE      @@1\r
21162         ADD     EAX,8\r
21163         JMP     @@0\r
21164 @@1:    ADD     EAX,2\r
21165 @@2:    ADD     EAX,2\r
21166 @@3:    ADD     EAX,2\r
21167 @@4:    XCHG    EDX,EAX\r
21168         POP     EAX\r
21169         SUB     EDX,EAX\r
21170         SHR     EDX,1\r
21171 @@5:    POP     ECX\r
21172         JMP     LStrFromPWCharLen\r
21173 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
21174 {$ENDIF _FPC}\r
21177 /////////////////////////////////////////////////////////////////////////\r
21178 //\r
21179 //\r
21180 //                          F   I   L   E   S\r
21181 //\r
21182 //\r
21183 /////////////////////////////////////////////////////////////////////////\r
21184 //[FILES]\r
21186    This part of the unit modified by Tim Slusher and Vladimir Kladov.\r
21189 {* Set of utility methods to work with files\r
21190    and reqistry.\r
21191    When programming KOL, which is Windows API-oriented, You should\r
21192    avoid alien (for Windows) embedded Pascal files handling, and\r
21193    use API-calls which implemented very well. This set of functions\r
21194    is intended to make this easier.\r
21195    Also TDirList object implementation present here and some registry\r
21196    access functions, which allow to make code more elegant.\r
21199 {$UNDEF ASM_LOCAL}\r
21200 {$IFDEF ASM_VERSION}\r
21201   {$DEFINE ASM_LOCAL}\r
21202 {$ENDIF ASM_VERSION}\r
21204 //[FUNCTION FileCreate]\r
21205 {$IFDEF ASM_VERSION}\r
21206 function FileCreate( const FileName: string; OpenFlags: DWord): THandle;\r
21207 asm\r
21208         XOR      ECX, ECX\r
21209         PUSH     ECX\r
21210         MOV      ECX, EDX\r
21211         SHR      ECX, 16\r
21212         AND      CX, $1FFF\r
21213         JNZ      @@1\r
21214         MOV      CL, FILE_ATTRIBUTE_NORMAL\r
21215 @@1:    PUSH     ECX\r
21216         MOV      CL, DH\r
21217         PUSH     ECX                  // CreationMode\r
21218         PUSH     0\r
21219         MOV      CL, DL\r
21220         PUSH     ECX                  // ShareMode\r
21221         MOV      DX, 0\r
21222         PUSH     EDX                  // AccessMode\r
21223         //CALL     System.@LStrToPChar // FileName must not be ''\r
21224         PUSH     EAX\r
21225         CALL     CreateFile\r
21226 end;\r
21227 {$ELSE ASM_VERSION} //Pascal\r
21228 function FileCreate(const FileName: string; OpenFlags: DWord): THandle;\r
21229 var Attr: DWORD;\r
21230 begin\r
21231   Attr := (OpenFlags shr 16) and $1FFF;\r
21232   if Attr = 0 then Attr := FILE_ATTRIBUTE_NORMAL;\r
21233   Result := CreateFile( PChar(FileName), OpenFlags and $F0000000,\r
21234                         OpenFlags and $F, nil, (OpenFlags shr 8) and $F,\r
21235                         Attr, 0 );\r
21236 end;\r
21237 {$ENDIF ASM_VERSION}\r
21238 //[END FileCreate]\r
21240 //[FUNCTION FileClose]\r
21241 {$IFDEF ASM_VERSION}\r
21242 function FileClose( Handle: THandle): Boolean;\r
21243 asm\r
21244         PUSH     EAX\r
21245         CALL     CloseHandle\r
21246         TEST     EAX, EAX\r
21247         SETNZ    AL\r
21248 end;\r
21249 {$ELSE ASM_VERSION} //Pascal\r
21250 function FileClose(Handle: THandle): boolean;\r
21251 begin\r
21252      Result := CloseHandle(Handle);\r
21253 end;\r
21254 {$ENDIF ASM_VERSION}\r
21255 //[END FileClose]\r
21257 //[FUNCTION FileExists]\r
21258 {$IFDEF ASM_VERSION}\r
21259 function FileExists( const FileName : String ) : Boolean;\r
21260 const size_TWin32FindData = sizeof( TWin32FindData );\r
21261 asm\r
21262         CALL     EAX2PChar\r
21263         PUSH     EAX\r
21264         CALL     GetFileAttributes\r
21265         INC      EAX\r
21266         JZ       @@exit\r
21267         DEC      EAX\r
21268         {$IFDEF PARANOIA}\r
21269         DB $24, FILE_ATTRIBUTE_DIRECTORY\r
21270         {$ELSE}\r
21271         AND      AL, FILE_ATTRIBUTE_DIRECTORY\r
21272         {$ENDIF}\r
21273         SETZ     AL\r
21274 @@exit:\r
21275 end;\r
21276 {$ELSE ASM_VERSION} //Pascal\r
21277 function FileExists( const FileName : String ) : Boolean;\r
21278 var\r
21279   Code: Integer;\r
21280 begin\r
21281   Code := GetFileAttributes(PChar(FileName));\r
21282   Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code = 0);\r
21283 end;\r
21284 {$ENDIF ASM_VERSION}\r
21285 //[END FileExists]\r
21287 //[FUNCTION FileSeek]\r
21288 {$IFDEF ASM_VERSION}\r
21289 function FileSeek( Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;\r
21290 asm\r
21291         MOVZX    ECX, CL\r
21292         PUSH     ECX\r
21293         PUSH     0\r
21294         PUSH     EDX\r
21295         PUSH     EAX\r
21296         CALL     SetFilePointer\r
21297 end;\r
21298 {$ELSE ASM_VERSION} //Pascal\r
21299 function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;\r
21300 begin\r
21301   Result := SetFilePointer(Handle, MoveTo, nil, Ord( MoveMethod ) );\r
21302 end;\r
21303 {$ENDIF ASM_VERSION}\r
21304 //[END FileSeek]\r
21306 //[FUNCTION FileRead]\r
21307 {$IFDEF ASM_VERSION}\r
21308 function FileRead( Handle: THandle; var Buffer; Count: DWord): DWord;\r
21309 asm\r
21310         PUSH     EBP\r
21311         PUSH     0\r
21312         MOV      EBP, ESP\r
21313         PUSH     0\r
21314         PUSH     EBP\r
21315         PUSH     ECX\r
21316         PUSH     EDX\r
21317         PUSH     EAX\r
21318         CALL     ReadFile\r
21319         TEST     EAX, EAX\r
21320         POP      EAX\r
21321         JNZ      @@exit\r
21322         XOR      EAX, EAX\r
21323 @@exit:\r
21324         POP      EBP\r
21325 end;\r
21326 {$ELSE ASM_VERSION} //Pascal\r
21327 function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;\r
21328 begin\r
21329      if not ReadFile(Handle, Buffer, Count, Result, nil) then\r
21330        Result := 0;\r
21331 end;\r
21332 {$ENDIF ASM_VERSION}\r
21333 //[END FileRead]\r
21335 //[FUNCTION File2Str]\r
21336 {$IFDEF ASM_VERSION}\r
21337 function File2Str( Handle: THandle): String;\r
21338 asm\r
21339         PUSH     EDX\r
21340         TEST     EAX, EAX\r
21341         JZ       @@exit // return ''\r
21343         PUSH     EBX\r
21344         MOV      EBX, EAX // EBX = Handle\r
21345         XOR      EDX, EDX\r
21346         XOR      ECX, ECX\r
21347         INC      ECX\r
21348         CALL     FileSeek\r
21349         PUSH     EAX // Pos\r
21350         PUSH     0\r
21351         PUSH     EBX\r
21352         CALL     GetFileSize\r
21353         POP      EDX\r
21354         SUB      EAX, EDX // EAX = Size - Pos\r
21355         JZ       @@exitEBX\r
21357         PUSH     EAX\r
21358         CALL     System.@GetMem\r
21359         XCHG     EAX, EBX\r
21360         MOV      EDX, EBX\r
21361         POP      ECX\r
21362         PUSH     ECX\r
21363         CALL     FileRead\r
21364         POP      ECX\r
21365         MOV      EDX, EBX\r
21366         POP      EBX\r
21367         POP      EAX\r
21368         PUSH     EDX\r
21369         {$IFDEF _D2}\r
21370         CALL     _LStrFromPCharLen\r
21371         {$ELSE}\r
21372         CALL     System.@LStrFromPCharLen\r
21373         {$ENDIF}\r
21374         JMP      @@freebuf\r
21376 @@exitEBX:\r
21377         POP      EBX\r
21378 @@exit:\r
21379         XCHG     EDX, EAX\r
21380         POP      EAX // @Result\r
21381         PUSH     EDX\r
21382         CALL     System.@LStrFromPChar\r
21383 @@freebuf:\r
21384         POP      EAX\r
21385         TEST     EAX, EAX\r
21386         JZ       @@fin\r
21387         CALL     System.@FreeMem\r
21388 @@fin:\r
21389 end;\r
21390 {$ELSE ASM_VERSION} //Pascal\r
21391 function File2Str(Handle: THandle): String;\r
21392 var Pos, Size: DWORD;\r
21393 begin\r
21394   Result := '';\r
21395   if Handle = 0 then Exit;\r
21396   Pos := FileSeek( Handle, 0, spCurrent );\r
21397   Size := GetFileSize( Handle, nil );\r
21398   SetString( Result, nil, Size - Pos + 1 );\r
21399   FileRead( Handle, Result[ 1 ], Size - Pos );\r
21400   Result[ Size - Pos + 1 ] := #0;\r
21401 end;\r
21402 {$ENDIF ASM_VERSION}\r
21403 //[END File2Str]\r
21405 //[FUNCTION FileWrite]\r
21406 {$IFDEF ASM_VERSION}\r
21407 function FileWrite( Handle: THandle; const Buffer; Count: DWord): DWord;\r
21408 asm\r
21409         PUSH     EBP\r
21410         PUSH     EBP\r
21411         MOV      EBP, ESP\r
21412         PUSH     0\r
21413         PUSH     EBP\r
21414         PUSH     ECX\r
21415         PUSH     EDX\r
21416         PUSH     EAX\r
21417         CALL     WriteFile\r
21418         TEST     EAX, EAX\r
21419         POP      EAX\r
21420         JNZ      @@exit\r
21421         XOR      EAX, EAX\r
21422 @@exit:\r
21423         POP      EBP\r
21424 end;\r
21425 {$ELSE ASM_VERSION} //Pascal\r
21426 function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;\r
21427 begin\r
21428      if not WriteFile(Handle, Buffer, Count, Result, nil) then\r
21429        Result := 0;\r
21430 end;\r
21431 {$ENDIF ASM_VERSION}\r
21432 //[END FileWrite]\r
21434 //[FUNCTION FileEOF]\r
21435 {$IFDEF ASM_VERSION}\r
21436 function FileEOF( Handle: THandle ) : Boolean;\r
21437 asm\r
21438         PUSH     EAX\r
21440         PUSH     0\r
21441         PUSH     EAX\r
21442         CALL     GetFileSize\r
21444         XCHG     EAX, [ESP]\r
21446         MOV      CL, spCurrent\r
21447         XOR      EDX, EDX\r
21448         CALL     FileSeek\r
21450         POP      EDX\r
21451         CMP      EAX, EDX\r
21452         SETGE    AL\r
21453 end;\r
21454 {$ELSE ASM_VERSION} //Pascal\r
21455 function FileEOF( Handle: THandle ) : Boolean;\r
21456 var Siz, Pos : DWord;\r
21457 begin\r
21458   Siz := GetFileSize( Handle, nil );\r
21459   Pos := FileSeek( Handle, 0, spCurrent );\r
21460   Result := Pos >= Siz;\r
21461 end;\r
21462 {$ENDIF ASM_VERSION}\r
21463 //[END FileEOF]\r
21465 //[FUNCTION FileFullPath]\r
21466 {$IFDEF ASM_noVERSION}\r
21467 function FileFullPath( const FileName: String ) : String;\r
21468 const\r
21469   BkSlash: String = '\';\r
21470   szTShFileInfo = sizeof( TShFileInfo );\r
21471 asm\r
21472         PUSH     EBX\r
21473         PUSH     ESI\r
21474         MOV      EBX, EDX\r
21475         PUSH     EAX\r
21477         XCHG     EAX, EDX\r
21478         CALL     System.@LStrClr\r
21480         POP      EDX\r
21481         PUSH     0\r
21482         MOV      EAX, ESP\r
21483         CALL     System.@LStrAsg\r
21484         MOV      ESI, ESP\r
21486 @@loo:  CMP      dword ptr [ESI], 0\r
21487         JZ       @@fin\r
21489         MOV      EAX, ESI\r
21490         MOV      EDX, [BkSlash]\r
21491         PUSH     0\r
21492         MOV      ECX, ESP\r
21493         CALL     Parse\r
21495         CMP      dword ptr [EBX], 0\r
21496         JE       @@1\r
21497         MOV      EAX, EBX\r
21498         MOV      EDX, [BkSlash]\r
21499         CALL     System.@LStrCat\r
21500         JMP      @@2\r
21501 @@1:\r
21502         POP      EAX\r
21503         PUSH     EAX\r
21504         CALL     System.@LStrLen\r
21505         CMP      EAX, 2\r
21506         JNE      @@2\r
21507         POP      EAX\r
21508         PUSH     EAX\r
21509         CMP      byte ptr [EAX+1], ':'\r
21510         JNE      @@2\r
21512         MOV      EAX, EBX\r
21513         POP      EDX\r
21514         PUSH     EDX\r
21515         CALL     System.@LStrAsg\r
21516         JMP      @@3\r
21517 @@2:\r
21518         PUSH     0\r
21519         MOV      EAX, ESP\r
21520         MOV      EDX, [EBX]\r
21521         CALL     System.@LStrAsg\r
21522         MOV      EAX, ESP\r
21523         MOV      EDX, [ESP+4]\r
21524         CALL     System.@LStrCat\r
21525         POP      EAX\r
21526         PUSH     EAX\r
21527         SUB      ESP, szTShFileInfo\r
21528         MOV      EDX, ESP\r
21529         PUSH     SHGFI_DISPLAYNAME\r
21530         PUSH     szTShFileInfo\r
21531         PUSH     EDX\r
21532         PUSH     0\r
21533         PUSH     EAX\r
21534         CALL     ShGetFileInfo\r
21535         LEA      EDX, [ESP].TShFileInfo.szDisplayName\r
21536         CMP      byte ptr [EDX], 0\r
21537         JE       @@clr_stk\r
21538         LEA      EAX, [ESP+szTShFileInfo+4]\r
21539         CALL     System.@LStrFromPChar\r
21540 @@clr_stk:\r
21541         ADD      ESP, szTShFileInfo\r
21542         CALL     RemoveStr\r
21543         POP      EDX\r
21544         PUSH     EDX\r
21545         MOV      EAX, EBX\r
21546         CALL     System.@LStrCat\r
21548 @@3:    CALL     RemoveStr\r
21549         JMP      @@loo\r
21551 @@fin:  CALL     RemoveStr\r
21552         POP      ESI\r
21553         POP      EBX\r
21554 end;\r
21555 {$ELSE ASM_VERSION} //Pascal\r
21556 function FileFullPath( const FileName: String ) : String;\r
21557 var SFI: TShFileInfo;\r
21558     Src, S: String;\r
21559 begin\r
21560   Result := '';\r
21561   Src := FileName;\r
21562   while Src <> '' do\r
21563   begin\r
21564     S := Parse( Src, '\' );\r
21565     if Result <> '' then\r
21566       Result := Result + '\';\r
21567     if (Result = '') and (Length( S ) = 2) and (S[ 2 ] = ':') then\r
21568       Result := S\r
21569     else\r
21570     begin\r
21571       ShGetFileInfo( PChar( Result + S ), 0, SFI, Sizeof( SFI ),\r
21572                      SHGFI_DISPLAYNAME );\r
21573       if SFI.szDisplayName[ 0 ] <> #0 then\r
21574         S := SFI.szDisplayName;\r
21575       Result := Result + S;\r
21576     end;\r
21577   end;\r
21578   if ExtractFileExt( Result ) = '' then\r
21579   // case when flag 'Hide extensions for registered file types' is set on\r
21580   // in the Explorer:\r
21581     Result := Result + ExtractFileExt( FileName );\r
21582 end;\r
21583 {$ENDIF ASM_VERSION}\r
21584 //[END FileFullPath]\r
21586 //[function FileShortPath]\r
21587 function FileShortPath( const FileName: String ): String;\r
21588 var Buf: array[ 0..MAX_PATH ] of Char;\r
21589 begin\r
21590   GetShortPathName( PChar( FileName ), Buf, Sizeof( Buf ) );\r
21591   Result := Buf;\r
21592 end;\r
21594 //[function FileIconSystemIdx]\r
21595 function FileIconSystemIdx( const Path: String ): Integer;\r
21596 var SFI: TShFileInfo;\r
21597 begin\r
21598   SFI.iIcon := 0; // Bartov\r
21599   ShGetFileInfo( PChar( Path ), 0, SFI, sizeof( SFI ),\r
21600                  //-- Babenko Alexey: -----------------//\r
21601                  // SHGFI_ICON or                     //\r
21602                  //----------------------------------//\r
21603                  SHGFI_SMALLICON or SHGFI_SYSICONINDEX );\r
21604   Result := SFI.iIcon;\r
21605 end;\r
21607 //[function FileIconSysIdxOffline]\r
21608 function FileIconSysIdxOffline( const Path: String ): Integer;\r
21609 var SFI: TShFileInfo;\r
21610 begin\r
21611   SFI.iIcon := 0; // Bartov\r
21612   ShGetFileInfo( PChar( Path ), FILE_ATTRIBUTE_NORMAL, SFI, sizeof( SFI ),\r
21613                  //-- Babenko Alexey: -----------------//\r
21614                  //SHGFI_ATTRIBUTES or SHGFI_ICON or //\r
21615                  //----------------------------------//\r
21616                  SHGFI_SMALLICON or SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES );\r
21617   Result := SFI.iIcon;\r
21618 end;\r
21620 //[procedure LogFileOutput]\r
21621 procedure LogFileOutput( const filepath, str: String );\r
21622 var F: HFile;\r
21623 begin\r
21624   F := FileCreate( filepath, ofOpenWrite or ofOpenAlways );\r
21625   if F = INVALID_HANDLE_VALUE then Exit;\r
21626   FileSeek( F, 0, spEnd );\r
21627   FileWrite( F, {$IFNDEF _D2} String {$ENDIF}\r
21628              ( str + #13#10 )[ 1 ], Length( str ) + 2 );\r
21629   FileClose( F );\r
21630 end;\r
21632 //[function StrSaveToFile]\r
21633 function StrSaveToFile( const Filename, Str: String ): Boolean;\r
21634 begin\r
21635   Result := Mem2File( PChar( Filename ), PChar( Str ), Length( Str ) )\r
21636             = Length( Str );\r
21637 end;\r
21639 //[function StrLoadFromFile]\r
21640 function StrLoadFromFile( const Filename: String ): String;\r
21641 var F: HFile;\r
21642 begin\r
21643   Result := '';\r
21644   F := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyWrite );\r
21645   if F = INVALID_HANDLE_VALUE then Exit;\r
21646   Result := File2Str( F );\r
21647   FileClose( F ); {??ee(zhog); Dark Knight}\r
21648 end;\r
21650 //[function Mem2File]\r
21651 function Mem2File( Filename: PChar; Mem: Pointer; Len: Integer ): Integer;\r
21652 var F: HFile;\r
21653 begin\r
21654   Result := 0;\r
21655   F := FileCreate( Filename, ofOpenWrite or ofOpenAlways );\r
21656   if F = INVALID_HANDLE_VALUE then Exit;\r
21657   Result := FileWrite( F, Mem^, Len );\r
21658   FileClose( F );\r
21659 end;\r
21661 //[function File2Mem]\r
21662 function File2Mem( Filename: PChar; Mem: Pointer; MaxLen: Integer ): Integer;\r
21663 var F: HFile;\r
21664 begin\r
21665   Result := 0;\r
21666   F := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyWrite );\r
21667   if F = INVALID_HANDLE_VALUE then Exit;\r
21668   Result := FileRead( F, Mem^, MaxLen );\r
21669   FileClose( F );\r
21670 end;\r
21672 //[FUNCTION DirectoryExists]\r
21673 {$IFDEF ASM_VERSION}\r
21674 function DirectoryExists( const Name: string): Boolean;\r
21675 asm\r
21676         //CALL     System.@LStrToPChar // Name must not be ''\r
21677         PUSH     EAX\r
21678         CALL     GetFileAttributes\r
21679         INC      EAX\r
21680         JZ       @@exit\r
21681         DEC      EAX\r
21682         {$IFDEF PARANOIA}\r
21683         DB $24, FILE_ATTRIBUTE_DIRECTORY\r
21684         {$ELSE}\r
21685         AND      AL, FILE_ATTRIBUTE_DIRECTORY\r
21686         {$ENDIF}\r
21687         SETNZ    AL\r
21688 @@exit:\r
21689 end;\r
21690 {$ELSE ASM_VERSION} //Pascal\r
21691 function DirectoryExists(const Name: string): Boolean;\r
21692 var\r
21693   Code: Integer;\r
21694 begin\r
21695   Code := GetFileAttributes(PChar(Name));\r
21696   Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);\r
21697 end;\r
21698 {$ENDIF ASM_VERSION}\r
21699 //[END DirectoryExists]\r
21701 //[function CheckDirectoryContent]\r
21702 function CheckDirectoryContent( const Name: String; SubDirsOnly: Boolean; const Mask: String ): Boolean;\r
21703 var FD: TWin32FindData;\r
21704     FH: THandle;\r
21705 begin\r
21706   if not DirectoryExists( Name ) then\r
21707     Result := TRUE\r
21708   else\r
21709   begin\r
21710     FH := Windows.FindFirstFile( PChar( IncludeTrailingPathDelimiter( Name )\r
21711        + Mask ), FD );\r
21712     if FH = INVALID_HANDLE_VALUE then\r
21713       Result := TRUE\r
21714     else\r
21715     begin\r
21716       Result := TRUE;\r
21717       repeat\r
21718         if not StrIn( FD.cFileName, ['.','..'] ) then\r
21719         begin\r
21720           if SubDirsOnly and LongBool(FD.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)\r
21721              or not SubDirsOnly then\r
21722           begin\r
21723             Result := FALSE;\r
21724             break;\r
21725           end;\r
21726         end;\r
21727       until not Windows.FindNextFile( FH, FD );\r
21728       Windows.FindClose( FH );\r
21729     end;\r
21730   end;\r
21731 end;\r
21733 //[function DirectoryEmpty]\r
21734 function DirectoryEmpty(const Name: String): Boolean;\r
21735 begin\r
21736   Result := CheckDirectoryContent( Name, FALSE, '*.*' );\r
21737 end;\r
21739 {-}\r
21740 //[function DirectorySize]\r
21741 function DirectorySize( const Path: String ): I64;\r
21742 var DirList: PDirList;\r
21743     I: Integer;\r
21744 begin\r
21745   Result := MakeInt64( 0, 0 );\r
21746   DirList := NewDirList( Path, '*.*', 0 );\r
21747   for I := 0 to DirList.Count-1 do\r
21748   begin\r
21749     if LongBool( DirList.Items[ I ].dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY ) then\r
21750       Result := Add64( Result, DirectorySize( DirList.Path + DirList.Names[ I ] ) )\r
21751     else\r
21752       Result := Add64( Result, MakeInt64( DirList.Items[ I ].nFileSizeLow,\r
21753              DirList.Items[ I ].nFileSizeHigh ) );\r
21754   end;\r
21755   DirList.Free;\r
21756 end;\r
21757 {+}\r
21759 //[function DirectoryHasSubdirs]\r
21760 function DirectoryHasSubdirs( const Path: String ): Boolean;\r
21761 begin\r
21762   Result := not CheckDirectoryContent( Path, TRUE, '*.*' );\r
21763 end;\r
21765 //[function GetFileList]\r
21766 function GetFileList(const dir: string): PStrList;\r
21767 var\r
21768    Srch: TWin32FindData;\r
21769    flag: Integer;\r
21770    succ: boolean;\r
21771 begin\r
21772    result := nil;\r
21773    flag := FindFirstFile(PChar(dir), Srch);\r
21774    //succ := flag <> 0; //---------------------------------------\r
21775    succ := flag <> Integer(INVALID_HANDLE_VALUE); // M.V.Chirikov\r
21776    while succ do begin\r
21777       if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin\r
21778          if Result = nil then begin\r
21779             Result := NewStrList;\r
21780          end;\r
21781          Result.Add(Srch.cFileName);\r
21782       end;\r
21783       succ := FindNextFile(Flag, Srch);\r
21784    end;\r
21785    FindClose(Flag);\r
21786 end;\r
21788 //[function ExcludeTrailingChar]\r
21789 function ExcludeTrailingChar( const S: String; C: Char ): String;\r
21790 begin\r
21791   Result := S;\r
21792   if Result <> '' then\r
21793   if Result[ Length( Result ) ] = C then\r
21794     Delete( Result, Length( Result ), 1 );\r
21795 end;\r
21797 //[function IncludeTrailingChar]\r
21798 function IncludeTrailingChar( const S: String; C: Char ): String;\r
21799 begin\r
21800   Result := S;\r
21801   if (Result = '') or (Result[ Length( Result ) ] <> C) then\r
21802     Result := Result + C;\r
21803 end;\r
21805 //---------------------------------------------------------\r
21806 // Following functions/procedures are created by Edward Aretino:\r
21807 // IncludeTrailingPathDelimiter, ExcludeTrailingPathDelimiter,\r
21808 // ForceDirectories, CreateDir, ChangeFileExt\r
21809 //---------------------------------------------------------\r
21810 //[function IncludeTrailingPathDelimiter]\r
21811 function IncludeTrailingPathDelimiter(const S: string): string;\r
21812 begin\r
21813    {if CopyTail(S, 1) <> '\' then\r
21814      Result := S + '\'\r
21815    else\r
21816      Result := S;}\r
21817    Result := IncludeTrailingChar( S, '\' );\r
21818 end;\r
21820 //[function ExcludeTrailingPathDelimiter]\r
21821 function ExcludeTrailingPathDelimiter(const S: string): string;\r
21822 begin\r
21823    {Result := S;\r
21824    if Length(Result) = 0 then Exit;\r
21826    if (CopyTail(Result, 1) = '\') then\r
21827      DeleteTail(Result, 1);}\r
21828    Result := ExcludeTrailingChar( S, '\' );\r
21829 end;\r
21831 //[function ForceDirectories]\r
21832 function ForceDirectories(Dir: string): Boolean;\r
21833 begin\r
21834  Result := Length(Dir) > 0; {Centronix}\r
21835  If not Result then Exit;\r
21836  Dir := ExcludeTrailingPathDelimiter(Dir);\r
21837  If (Length(Dir) < 3) or DirectoryExists(Dir) or\r
21838    (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.\r
21839  Result := ForceDirectories(ExtractFilePath(Dir)) and CreateDir(Dir);\r
21840 end;\r
21842 //[function CreateDir]\r
21843 function CreateDir(const Dir: string): Boolean;\r
21844 begin\r
21845    Result := Windows.CreateDirectory(PChar(Dir), nil);\r
21846 end;\r
21848 //[function ChangeFileExt]\r
21849 function ChangeFileExt(FileName: String; const Extension: string): string;\r
21850 var\r
21851    FileExt: String;\r
21852 begin\r
21853    FileExt := ExtractFileExt(FileName);\r
21854    DeleteTail(FileName, Length(FileExt));\r
21855    Result := FileName+ Extension;\r
21856 end;\r
21858 {$IFDEF ASM_VERSION}\r
21859 {$IFNDEF _D2}\r
21860 {$DEFINE ASM_LStrFromPCharLen}\r
21861 {$ENDIF}\r
21862 {$ENDIF ASM_VERSION}\r
21864 {$IFDEF ASM_LStrFromPCharLen}\r
21865   {$DEFINE ASM_DIRDelimiters}\r
21866 {$ENDIF}\r
21868 {$IFDEF ASM_VERSION}\r
21869   {$DEFINE ASM_DIRDelimiters}\r
21870 {$ENDIF ASM_VERSION}\r
21872 {$IFDEF ASM_DIRDelimiters}\r
21873 const\r
21874   DirDelimiters: PChar = ':\';\r
21875 {$ENDIF}\r
21877 //[FUNCTION ExtractFileName]\r
21878 {$IFDEF ASM_VERSION}\r
21879 function ExtractFileName( const Path : String ) : String;\r
21880 asm\r
21881         PUSH     EDX\r
21882         PUSH     EAX\r
21883         MOV      EDX, [DirDelimiters]\r
21884         CALL     __DelimiterLast\r
21885         POP      EDX\r
21886         CMP      byte ptr [EAX], 0\r
21887         JZ       @@1\r
21888         XCHG     EDX, EAX\r
21889         INC      EDX\r
21890 @@1:    POP      EAX\r
21891         CALL     System.@LStrFromPChar\r
21892 end;\r
21893 {$ELSE ASM_VERSION} //Pascal\r
21894 function ExtractFileName( const Path : String ) : String;\r
21895 var P: PChar;\r
21896 begin\r
21897   P := __DelimiterLast( PChar( Path ), ':\' );\r
21898   if P^ = #0 then\r
21899     Result := Path\r
21900   else\r
21901     Result := P + 1;\r
21902 end;\r
21903 {$ENDIF ASM_VERSION}\r
21904 //[END ExtractFileName]\r
21906 //[FUNCTION ExtractFilePath]\r
21907 {$IFDEF ASM_LStrFromPCharLen} // LStrFromPCharLen - there are no in D2\r
21908 function ExtractFilePath( const Path : String ) : String;\r
21909 asm\r
21910         PUSH     EDX\r
21911         MOV      EDX, [DirDelimiters]\r
21912         CALL     EAX2PChar\r
21913         PUSH     EAX\r
21914         CALL     __DelimiterLast\r
21915         XCHG     EDX, EAX\r
21916         XOR      ECX, ECX\r
21917         POP      EAX\r
21918         CMP      byte ptr [EDX], CL\r
21919         JZ       @@ret_0\r
21920         SUB      EDX, EAX\r
21921         INC      EDX\r
21922         XCHG     EDX, EAX\r
21923         XCHG     ECX, EAX\r
21924 @@ret_0:\r
21925         POP      EAX\r
21926         CALL     System.@LStrFromPCharLen\r
21927 end;\r
21928 {$ELSE} //Pascal\r
21929 function ExtractFilePath( const Path : String ) : String;\r
21930 //var I : Integer;\r
21931 var P, P0: PChar;\r
21932 begin\r
21933   P0 := PChar( Path );\r
21934   P := __DelimiterLast( P0, ':\' );\r
21935   if P^ = #0 then\r
21936     Result := ''\r
21937   else\r
21938     Result := Copy( Path, 1, P - P0 + 1 );\r
21939 end;\r
21940 {$ENDIF}\r
21942 //[function ExtractFileNameWOext]\r
21943 function ExtractFileNameWOext( const Path : String ) : String;\r
21944 begin\r
21945   Result := ExtractFileName( Path );\r
21946   Result := Copy( Result, 1, Length( Result ) - Length( ExtractFileExt( Result ) ) );\r
21947 end;\r
21949 {$IFDEF ASM_VERSION}\r
21950 const\r
21951   ExtDelimeters: PChar = '.';\r
21953 //[function ExtractFileExt]\r
21954 function ExtractFileExt( const Path : String ) : String;\r
21955 asm\r
21956         PUSH     EDX\r
21957         MOV      EDX, [ExtDelimeters]\r
21958         CALL     EAX2PChar\r
21959         CALL     __DelimiterLast\r
21960 @@1:    XCHG     EDX, EAX\r
21961         POP      EAX\r
21962         CALL     System.@LStrFromPChar\r
21963 end;\r
21964 {$ELSE ASM_VERSION} //Pascal\r
21965 function ExtractFileExt( const Path : String ) : String;\r
21966 var P: PChar;\r
21967 begin\r
21968   P := __DelimiterLast( PChar( Path ), '.' );\r
21969   Result := P;\r
21970 end;\r
21971 {$ENDIF ASM_VERSION}\r
21972 //[END ExtractFilePath]\r
21974 //[function ReplaceFileExt]\r
21975 function ReplaceFileExt( const Path, NewExt: String ): String;\r
21976 begin\r
21977   Result := ExtractFilePath( Path ) +\r
21978             ExtractFileNameWOext( ExtractFileName( Path ) ) +\r
21979             NewExt;\r
21980 end;\r
21982 //[function ExtractShortPathName]\r
21983 function ExtractShortPathName( const Path: String ): String;\r
21984 var\r
21985   Buffer: array[0..MAX_PATH - 1] of Char;\r
21986 begin\r
21987   SetString(Result, Buffer,\r
21988     GetShortPathName(PChar(Path), Buffer, SizeOf(Buffer)));\r
21989 end;\r
21991 //[function FilePathShortened]\r
21992 function FilePathShortened( const Path: String; MaxLen: Integer ): String;\r
21993 begin\r
21994   Result := FilePathShortenPixels( Path, 0, MaxLen );\r
21995 end;\r
21997 //[function PixelsLength]\r
21998 function PixelsLength( DC: HDC; const Text: String ): Integer;\r
21999 var Sz: TSize;\r
22000 begin\r
22001   if DC = 0 then\r
22002     Result := Length( Text )\r
22003   else\r
22004   begin\r
22005     Windows.GetTextExtentPoint32( DC, PChar( Text ), Length( Text ), Sz );\r
22006     Result := Sz.cx;\r
22007   end;\r
22008 end;\r
22010 //[function FilePathShortenPixels]\r
22011 function FilePathShortenPixels( const Path: String; DC: HDC; MaxPixels: Integer ): String;\r
22012 var L0, L1: Integer;\r
22013     Prev: String;\r
22014 begin\r
22015  Result := Path;\r
22016  L0 := PixelsLength( DC, Result );\r
22017  while L0 > MaxPixels do\r
22018  begin\r
22019    Prev := Result;\r
22020    L1 := pos( '\...\', Result );\r
22021    if L1 <= 0 then\r
22022      Result := ExcludeTrailingPathDelimiter( ExtractFilePath( Result ) )\r
22023    else\r
22024      Result := Copy( Result, 1, L1 - 1 );\r
22025    if Result <> '' then\r
22026      Result := IncludeTrailingPathDelimiter( ExtractFilePath( Result ) ) + '...\' + ExtractFileName( Path );\r
22027    if (Result = '') or (Result = Prev) then\r
22028    begin\r
22029      L1 := Length( ExtractFilePath( Result ) );\r
22030      while (PixelsLength( DC, Result ) > MaxPixels) and (L1 > 1) do\r
22031      begin\r
22032        Dec( L1 );\r
22033        Result := Copy( Result, 1, L1 ) + '...\' + ExtractFileName( Result );\r
22034      end;\r
22035      if PixelsLength( DC, Result ) > MaxPixels then\r
22036      begin\r
22037        L1 := MaxPixels + 1;\r
22038        while ((MaxPixels > 0) and (L1 > 1) or (MaxPixels = 0) and (L1 > 0)) and\r
22039              (PixelsLength( DC, Result ) > MaxPixels) do\r
22040        begin\r
22041          Dec( L1 );\r
22042          Result := Copy( ExtractFileName( Path ), 1, L1 ) + '...';\r
22043        end;\r
22044      end;\r
22045      break;\r
22046    end;\r
22047    L0 := PixelsLength( DC, Result );\r
22048  end;\r
22049 end;\r
22051 //[procedure CutFirstDirectory]\r
22052 procedure CutFirstDirectory(var S: String);\r
22053 var\r
22054   Root: Boolean;\r
22055   P: Integer;\r
22056 begin\r
22057   if S = '\' then\r
22058     S := ''\r
22059   else\r
22060   begin\r
22061     if S[1] = '\' then\r
22062     begin\r
22063       Root := True;\r
22064       Delete(S, 1, 1);\r
22065     end\r
22066     else\r
22067       Root := False;\r
22068     if S[1] = '.' then\r
22069       Delete(S, 1, 4);\r
22070     P := pos('\',S);\r
22071     if P <> 0 then\r
22072     begin\r
22073       Delete(S, 1, P);\r
22074       S := '...\' + S;\r
22075     end\r
22076     else\r
22077       S := '';\r
22078     if Root then\r
22079       S := '\' + S;\r
22080   end;\r
22081 end;\r
22083 //[function MinimizeName]\r
22084 function MinimizeName( const Path: String; DC: HDC; MaxPixels: Integer ): String;\r
22085 var\r
22086   Drive, Dir, Name: String;\r
22087 begin\r
22088   Result := Path;\r
22089   Dir := ExtractFilePath(Result);\r
22090   Name := ExtractFileName(Result);\r
22092   if (Length(Dir) >= 2) and (Dir[2] = ':') then\r
22093   begin\r
22094     Drive := Copy(Dir, 1, 2);\r
22095     Delete(Dir, 1, 2);\r
22096   end\r
22097   else\r
22098     Drive := '';\r
22099   while ((Dir <> '') or (Drive <> '')) and (PixelsLength(DC, Result) > MaxPixels) do\r
22100   begin\r
22101     if Dir = '\...\' then\r
22102     begin\r
22103       Drive := '';\r
22104       Dir := '...\';\r
22105     end\r
22106     else if Dir = '' then\r
22107       Drive := ''\r
22108     else\r
22109       CutFirstDirectory(Dir);\r
22110     Result := Drive + Dir + Name;\r
22111   end;\r
22112 end;\r
22114 //[FUNCTION FileSize]\r
22115 {$IFDEF ASM_VERSION}\r
22116 function FileSize( const Path : String ) : Integer;\r
22117 const size_TWin32FindData = sizeof( TWin32FindData );\r
22118 asm\r
22119         ADD      ESP, - size_TWin32FindData\r
22120         PUSH     ESP\r
22121         //CALL     System.@LStrToPChar // Path must not be ''\r
22122         PUSH     EAX\r
22123         CALL     FindFirstFile\r
22124         INC      EAX\r
22125         JZ       @@exit\r
22126         DEC      EAX\r
22127         PUSH     EAX\r
22128         CALL     FindClose\r
22130         MOV      EAX, [ESP].TWin32FindData.nFileSizeLow\r
22131 @@exit:\r
22132         ADD      ESP, size_TWin32FindData\r
22133 end;\r
22134 {$ELSE ASM_VERSION} //Pascal\r
22135 function FileSize( const Path : String ) : Integer;\r
22136 var FD : TWin32FindData;\r
22137     FH : THandle;\r
22138 begin\r
22139   FH := FindFirstFile( PChar( Path ), FD );\r
22140   Result := 0;\r
22141   if FH = INVALID_HANDLE_VALUE then exit;\r
22142   Result := FD.nFileSizeLow;\r
22143   if ((FD.nFileSizeLow and $80000000) <> 0) or\r
22144      (FD.nFileSizeHigh <> 0) then Result := -1;\r
22145   FindClose( FH );\r
22146 end;\r
22147 {$ENDIF ASM_VERSION}\r
22148 //[END FileSize]\r
22150 //*\r
22151 //[function FileTimeCompare]\r
22152 function FileTimeCompare( const FT1, FT2 : TFileTime ) : Integer;\r
22153 var ST1, ST2 : TSystemTime;\r
22154 begin\r
22155   FileTimeToSystemTime( FT1, ST1 );\r
22156   FileTimeToSystemTime( FT2, ST2 );\r
22157   Result := CompareSystemTime( ST1, ST2 );\r
22158 end;\r
22160 //[function GetSystemDir]\r
22161 function GetSystemDir: String;\r
22162 var Buf: array[ 0..MAX_PATH ] of Char;\r
22163 begin\r
22164   GetSystemDirectory( @ Buf[ 0 ], MAX_PATH + 1 );\r
22165   Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );\r
22166 end;\r
22168 //*\r
22169 //[function GetWindowsDir]\r
22170 function GetWindowsDir : string;\r
22171 var Buf : array[ 0..MAX_PATH ] of Char;\r
22172 begin\r
22173   GetWindowsDirectory( @Buf[ 0 ], MAX_PATH + 1 );\r
22174   Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );\r
22175 end;\r
22177 //[function GetWorkDir]\r
22178 function GetWorkDir : string;\r
22179 var Buf: array[ 0..MAX_PATH ] of Char;\r
22180 begin\r
22181   GetCurrentDirectory( MAX_PATH + 1, @ Buf[ 0 ] );\r
22182   Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );\r
22183 end;\r
22185 //*\r
22186 //[function GetTempDir]\r
22187 function GetTempDir : string;\r
22188 var Buf : array[ 0..MAX_PATH ] of Char;\r
22189 begin\r
22190   Windows.GetTempPath( MAX_PATH + 1, @Buf[ 0 ] );\r
22191   Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );\r
22192 end;\r
22194 //[function CreateTempFile]\r
22195 function CreateTempFile( const DirPath, Prefix: String ): String;\r
22196 var Buf: array[ 0..MAX_PATH ] of Char;\r
22197 begin\r
22198   GetTempFileName( PChar( DirPath ), PChar( Prefix ), 0, Buf );\r
22199   Result := Buf;\r
22200 end;\r
22202 //[function GetFileListStr]\r
22203 function GetFileListStr(FPath{e.g.'c:\tmp\'}, FMask{e.g.'*.*'}: string): string;\r
22204 {* List of files in string, separating each path from others with semicolon (';').\r
22205    E.g.: 'c:\tmp\unit1.dcu;c:\tmp\unit1.~pa' (for use with DeleteFile2Recycle())}\r
22206 var\r
22207    Srch: TWin32FindData;\r
22208    flag: Integer;\r
22209    succ: boolean;\r
22210    dir:string;\r
22211 begin\r
22212    result := '';\r
22213    if (FPath<>'') and (FPath[length(FPath)]<>'\') then FPath:=FPath+'\';\r
22214    if (FMask<>'') and (FMask[1]='\') then FMask:=CopyEnd(FMask,2);\r
22215    dir:=FPath+FMask;\r
22216    flag := FindFirstFile(PChar(dir), Srch);\r
22217    succ := flag <> 0;\r
22218    while succ do begin\r
22219       if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin\r
22220          if Result<>''then Result:=Result+';';\r
22221          Result:=Result+FPath+Srch.cFileName;\r
22222       end;\r
22223       succ := FindNextFile(Flag, Srch);\r
22224    end;\r
22225    FindClose(Flag);\r
22226 end;\r
22228 //[function DeleteFiles]\r
22229 function DeleteFiles( const DirPath: String ): Boolean;\r
22230 var Files, Name: String;\r
22231 begin\r
22232   Files := GetFileListStr( ExtractFilePath( DirPath ), ExtractFileName( DirPath ) );\r
22233   Result := TRUE;\r
22234   while Files <> '' do\r
22235   begin\r
22236     Name := Parse( Files, ';' );\r
22237     Result := Result and DeleteFile( PChar( Name ) );\r
22238   end;\r
22239 end;\r
22241 //*\r
22242 //[function DeleteFile2Recycle]\r
22243 function DeleteFile2Recycle( const Filename : String ) : Boolean;\r
22244 var FOS : TSHFileOpStruct;\r
22245     Buf : PChar;\r
22246     L : Integer;\r
22247 begin\r
22248   L := Length( Filename );\r
22249   GetMem( Buf, L + 2 );\r
22250   StrCopy( Buf, PChar( Filename ) );\r
22251   Buf[ L + 1 ] := #0;\r
22252   for L := L downto 0 do\r
22253     if Buf[ L ] = ';' then Buf[ L ] := #0;\r
22254   FillChar( FOS, Sizeof( FOS ), 0 );\r
22255   if Applet <> nil then\r
22256     FOS.Wnd := Applet.Handle;\r
22257   FOS.wFunc := FO_DELETE;\r
22258   FOS.pFrom := Buf;\r
22259   FOS.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;\r
22260   FOS.fAnyOperationsAborted := True;\r
22261   FOS.lpszProgressTitle := PChar( 'Delete ' + Filename + ' to Recycle bin' );\r
22262   Result := SHFileOperation( FOS ) = 0;\r
22263   if Result then\r
22264     Result := not FOS.fAnyOperationsAborted;\r
22265   FreeMem( Buf );\r
22266 end;\r
22268 //[function CopyMoveFiles]\r
22269 function CopyMoveFiles( const FromList, ToList: String; Move: Boolean ): Boolean;\r
22270 var FOS : TSHFileOpStruct;\r
22271     Buf : PChar;\r
22272     L : Integer;\r
22273 begin\r
22274   L := Length( FromList );\r
22275   GetMem( Buf, L + 2 );\r
22276   StrCopy( Buf, PChar( FromList ) );\r
22277   Buf[ L + 1 ] := #0;\r
22278   for L := L downto 0 do\r
22279     if Buf[ L ] = ';' then Buf[ L ] := #0;\r
22280   FillChar( FOS, Sizeof( FOS ), 0 );\r
22281   if Applet <> nil then\r
22282     FOS.Wnd := Applet.Handle;\r
22283   if Move then\r
22284   begin\r
22285     FOS.wFunc := FO_MOVE;\r
22286     FOS.lpszProgressTitle := PChar( 'Move files' );\r
22287   end\r
22288     else\r
22289   begin\r
22290     FOS.wFunc := FO_COPY;\r
22291     FOS.lpszProgressTitle := PChar( 'Copy files' );\r
22292   end;\r
22293   FOS.pFrom := Buf;\r
22294   FOS.pTo := PChar( ToList + #0 );\r
22295   FOS.fFlags := FOF_ALLOWUNDO;\r
22296   FOS.fAnyOperationsAborted := True;\r
22297   Result := SHFileOperation( FOS ) = 0;\r
22298   if Result then\r
22299     Result := not FOS.fAnyOperationsAborted;\r
22300   FreeMem( Buf );\r
22301 end;\r
22303 {-}\r
22304 //[function DiskFreeSpace]\r
22305 function DiskFreeSpace( const Path: String ): I64;\r
22306 type TGetDFSEx = function( Path: PChar; CallerFreeBytes, TotalBytes, FreeBytes: Pointer )\r
22307                  : Bool; stdcall;\r
22308 var GetDFSEx: TGetDFSEx;\r
22309     Kern32: THandle;\r
22310     V: TOSVersionInfo;\r
22311     Ex: Boolean;\r
22312     SpC, BpS, NFC, TNC: DWORD;\r
22313     FBA, TNB: I64;\r
22314 begin\r
22315   GetDFSEx := nil;\r
22316   V.dwOSVersionInfoSize := Sizeof( V );\r
22317   GetVersionEx( V );\r
22318   Ex := FALSE;\r
22319   if V.dwPlatformId = VER_PLATFORM_WIN32_NT then\r
22320   begin\r
22321     Ex := V.dwMajorVersion >= 4;\r
22322   end\r
22323     else\r
22324   if V.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then\r
22325   begin\r
22326     Ex := V.dwMajorVersion > 4;\r
22327     if not Ex then\r
22328     if V.dwMajorVersion = 4 then\r
22329     begin\r
22330       Ex := V.dwMinorVersion > 0;\r
22331       if not Ex then\r
22332         Ex := LoWord( V.dwBuildNumber ) >= $1111;\r
22333     end;\r
22334   end;\r
22335   if Ex then\r
22336   begin\r
22337     Kern32 := GetModuleHandle( 'kernel32.dll' );\r
22338     GetDFSEx := GetProcAddress( Kern32, 'GetDiskFreeSpaceExA' );\r
22339   end;\r
22340   if Assigned( GetDFSEx ) then\r
22341     GetDFSEx( PChar( Path ), @ FBA, @ TNB, @Result )\r
22342   else\r
22343   begin\r
22344     GetDiskFreeSpace( PChar( Path ), SpC, BpS, NFC, TNC );\r
22345     Result := Mul64i( MakeInt64( SpC * BpS, 0 ), NFC );\r
22346   end;\r
22347 end;\r
22348 {+}\r
22350 //*\r
22351 //[function GetUniqueFilename]\r
22352 function GetUniqueFilename( PathName: string ) : String;\r
22353 var Path, Nam, Ext : String;\r
22354     I, J, K : Integer;\r
22355 begin\r
22356   Result := PathName;\r
22357   Path := ExtractFilePath( PathName );\r
22358   if not DirectoryExists( Path ) then Exit;\r
22359   Nam := ExtractFileNameWOext( PathName );\r
22360   if Nam = '' then\r
22361   begin\r
22362     if Path[ Length( Path ) ] = '\' then\r
22363        Path := Copy( Path, 1, Length( Path ) - 1 );\r
22364     PathName := Path;\r
22365     Result := Path;\r
22366   end;\r
22367   Nam := ExtractFileNameWOext( PathName );\r
22368   Ext := ExtractFileExt( PathName );\r
22369   I := Length( Nam );\r
22370   for J := I downto 1 do\r
22371   if not (Nam[ J ] in [ '0'..'9' ]) then\r
22372   begin\r
22373     I := J;\r
22374     break;\r
22375   end;\r
22376   K := Str2Int( CopyEnd( Nam, I + 1 ) );\r
22377   while FileExists( Result ) do\r
22378   begin\r
22379     Inc( K );\r
22380     Result := Path + Copy( Nam, 1, I ) + Int2Str( K ) + Ext;\r
22381   end;\r
22382 end;\r
22384 //[FUNCTION GetStartDir]\r
22385 {$IFDEF ASM_VERSION}\r
22386 function GetStartDir : String;\r
22387 asm\r
22388         PUSH     EBX\r
22389         MOV      EBX, EAX\r
22391         XOR      EAX, EAX\r
22392         MOV      AH, 2\r
22393         SUB      ESP, EAX\r
22394         MOV      EDX, ESP\r
22395         PUSH     EAX\r
22396         PUSH     EDX\r
22397         PUSH     0\r
22398         CALL     GetModuleFileName\r
22400         LEA      EDX, [ESP + EAX]\r
22401 @@1:    DEC      EDX\r
22402         CMP      byte ptr [EDX], '\'\r
22403         JNZ      @@1\r
22405         INC      EDX\r
22406         MOV      byte ptr [EDX], 0\r
22408         MOV      EAX, EBX\r
22409         MOV      EDX, ESP\r
22410         CALL     System.@LStrFromPChar\r
22412         ADD      ESP, 200h\r
22413         POP      EBX\r
22414 end;\r
22415 {$ELSE ASM_VERSION} //Pascal\r
22416 function GetStartDir : String;\r
22417 var Buffer:array[0..260] of Char;\r
22418     I : Integer;\r
22419 begin\r
22420   I := GetModuleFileName( 0, Buffer, Sizeof( Buffer ) );\r
22421   for I := I downto 0 do\r
22422     if Buffer[ I ] = '\' then\r
22423     begin\r
22424       Buffer[ I + 1 ] := #0;\r
22425       break;\r
22426     end;\r
22427   Result := Buffer;\r
22428 end;\r
22429 {$ENDIF ASM_VERSION}\r
22430 //[END GetStartDir]\r
22432 //[END FILES]\r
22436 { TDirList }\r
22438 //[function NewDirList]\r
22439 function NewDirList( const DirPath, Filter: String; Attr: DWORD ): PDirList;\r
22440 begin\r
22441   {-}\r
22442   New( Result, Create );\r
22443   {+}{++}(*Result := PDirList.Create;*){--}\r
22444   Result.ScanDirectory( DirPath, Filter, Attr );\r
22445 end;\r
22446 //[END NewDirList]\r
22448 //[function NewDirListEx]\r
22449 function NewDirListEx( const DirPath, Filters: String; Attr: DWORD ): PDirList;\r
22450 begin\r
22451   {-}\r
22452   New( Result, Create );\r
22453   {+}{++}(*Result := PDirList.Create;*){--}\r
22454   Result.ScanDirectoryEx( DirPath, Filters, Attr );\r
22455 end;\r
22456 //[END NewDirListEx]\r
22458 {$IFDEF ASM_VERSION}\r
22459 //[procedure TDirList.Clear]\r
22460 procedure TDirList.Clear;\r
22461 asm\r
22462         XOR      ECX, ECX\r
22463         XCHG     ECX, [EAX].fList\r
22464         JECXZ    @@exit\r
22465         XCHG     EAX, ECX\r
22466         CALL     TList.Release\r
22467 @@exit:\r
22468 end;\r
22469 {$ELSE ASM_VERSION} //Pascal\r
22470 procedure TDirList.Clear;\r
22471 begin\r
22472   if FList <> nil then\r
22473     FList.Release;\r
22474   FList := nil;\r
22475 end;\r
22476 {$ENDIF ASM_VERSION}\r
22478 {$IFDEF ASM_VERSION}\r
22479 //[destructor TDirList.Destroy]\r
22480 destructor TDirList.Destroy;\r
22481 asm\r
22482         PUSH     EBX\r
22483         MOV      EBX, EAX\r
22484         CALL     Clear\r
22485         LEA      EAX, [EBX].FPath\r
22486         CALL     System.@LStrClr\r
22487         XCHG     EAX, EBX\r
22488         CALL     TObj.Destroy\r
22489         POP      EBX\r
22490 end;\r
22491 {$ELSE ASM_VERSION} //Pascal\r
22492 destructor TDirList.Destroy;\r
22493 begin\r
22494   Clear;\r
22495   FPath := '';\r
22496   inherited;\r
22497 end;\r
22498 {$ENDIF ASM_VERSION}\r
22500 //[FUNCTION FindFilter]\r
22501 {$IFDEF ASM_VERSION}\r
22502 function FindFilter( const Filter: String): String;\r
22503 asm\r
22504         XCHG     EAX, EDX\r
22505         PUSH     EAX\r
22506         CALL     System.@LStrAsg\r
22507         POP      EAX\r
22508         CMP      dword ptr [EAX], 0\r
22509         JNE      @@exit\r
22510         LEA      EDX, @@mask_all\r
22511         JE       System.@LStrFromPChar\r
22512 @@mask_all:  DB  '*.*',0\r
22513 @@exit:\r
22514 end;\r
22515 {$ELSE ASM_VERSION} //Pascal\r
22516 function FindFilter(const Filter: String): String;\r
22517 begin\r
22518   Result := Filter;\r
22519   if Result = '' then Result := '*.*';\r
22520 end;\r
22521 {$ENDIF ASM_VERSION}\r
22522 //[END FindFilter]\r
22524 //+\r
22525 //[function TDirList.Get]\r
22526 function TDirList.Get(Idx: Integer): PWin32FindData;\r
22527 begin\r
22528   Result := FList.fItems[ Idx ];\r
22529 end;\r
22531 {$IFDEF ASM_VERSION}\r
22532 //[function TDirList.GetCount]\r
22533 function TDirList.GetCount: Integer;\r
22534 asm\r
22535         MOV      EAX, [EAX].fList\r
22536         TEST     EAX, EAX\r
22537         {$IFDEF USE_CMOV}\r
22538         CMOVNZ   EAX, [EAX].TList.fCount\r
22539         {$ELSE}\r
22540         JZ       @@exit\r
22541         MOV      EAX, [EAX].TList.fCount\r
22542 @@exit: {$ENDIF}\r
22543 end;\r
22544 {$ELSE ASM_VERSION} //Pascal\r
22545 function TDirList.GetCount: Integer;\r
22546 begin\r
22547   Result := 0;\r
22548   if FList = nil then Exit;\r
22549   Result := FList.Count;\r
22550 end;\r
22551 {$ENDIF ASM_VERSION}\r
22553 {$IFDEF ASM_VERSION}\r
22554 //[function TDirList.GetNames]\r
22555 function TDirList.GetNames(Idx: Integer): string;\r
22556 asm\r
22557         MOV      EAX, [EAX].fList\r
22558         MOV      EAX, [EAX].TList.fItems\r
22559         MOV      EDX, [EAX + EDX*4]\r
22560 //*/////////////////////////////////////////////////////\r
22561 //      ADD      EDX, TWin32FindData.cFileName\r
22562 //*/////////////////////////////////////////////////////\r
22563         ADD      EDX, offset TWin32FindData.cFileName //\r
22564 //*/////////////////////////////////////////////////////\r
22565         MOV      EAX, ECX\r
22566         CALL     System.@LStrFromPChar\r
22567 end;\r
22568 {$ELSE ASM_VERSION} //Pascal\r
22569 function TDirList.GetNames(Idx: Integer): string;\r
22570 begin\r
22571   Result := PChar(@PWin32FindData(fList.fItems[ Idx ]).cFileName[0]);\r
22572   //Result := PChar(@Items[Idx].cFileName[0]);\r
22573 end;\r
22574 {$ENDIF ASM_VERSION}\r
22576 //[function TDirList.GetIsDirectory]\r
22577 function TDirList.GetIsDirectory(Idx: Integer): Boolean;\r
22578 begin\r
22579   Result := LongBool( Items[ Idx ].dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY );\r
22580 end;\r
22582 {$IFDEF ASM_noVERSION}\r
22583 //[function TDirList.SatisfyFilter]\r
22584 function TDirList.SatisfyFilter(FileName: PChar; FileAttr,\r
22585   FindAttr: DWord): Boolean;\r
22586 asm\r
22587         PUSH     EBX\r
22588         PUSH     ESI\r
22589         PUSH     EDI\r
22590         XCHG     EBX, EAX // EBX = @ Self\r
22591         MOV      EAX, [FindAttr]\r
22592         MOV      EDI, EDX // EDI = FileName\r
22593         MOV      EDX, EAX\r
22594         AND      EDX, ECX\r
22595         CMP      EDX, EAX\r
22596         JE       @@1\r
22598         TEST AL, FILE_ATTRIBUTE_NORMAL\r
22599         JZ      @@ret_false\r
22600 @@1:\r
22601         CMP      word ptr [EDI], '.'\r
22602         JE       @@1_1\r
22603         CMP      word ptr [EDI], '..'\r
22604         JNE      @@1_1\r
22605         CMP      byte ptr [EDI+2], 0\r
22606         JNE      @@1_1\r
22607 @@1_0:\r
22608         MOV      ECX, [FindAttr]\r
22609         TEST     CL, FILE_ATTRIBUTE_NORMAL\r
22610         JZ       @@1_1\r
22611         CMP      ECX, FILE_ATTRIBUTE_NORMAL\r
22612         JE       @@1_1\r
22613         TEST     AL, FILE_ATTRIBUTE_DIRECTORY\r
22614         JZ       @@1_1\r
22615         TEST     CL, FILE_ATTRIBUTE_DIRECTORY\r
22616         JNZ      @@ret_true\r
22618 @@1_1:\r
22619         MOV      ECX, [EBX].fFilters\r
22620         JECXZ    @@ret_false //?\r
22622         MOV      ESI, [ECX].TStrList.fList\r
22623         MOV      ESI, [ESI].TList.fItems\r
22624         MOV      ECX, [ECX].TStrList.fCount\r
22625         JECXZ    @@ret_false\r
22627 @@2:\r
22628         LODSD\r
22629         TEST     EAX, EAX\r
22630         JZ       @@nx_filter\r
22632         PUSHAD\r
22634         MOV      EDX, [EAX]\r
22635         CMP      DX, $002E\r
22636         JE       @@F_d_dd\r
22637         AND      EDX, $FFFFFF\r
22638         CMP      EDX, $002E2E\r
22639         JE       @@F_d_dd\r
22641         MOV      EDX, [EDI]\r
22642         CMP      DX, $002E\r
22643         JE       @@4\r
22644         AND      EDX, $FFFFFF\r
22645         CMP      EDX, $002E2E\r
22646         JE       @@4\r
22647         JMP      @@chk_anti\r
22649 @@F_d_dd:\r
22650         MOV      EDX, EDI\r
22651         PUSH     EAX\r
22652         CALL     StrComp\r
22653         TEST     EAX, EAX\r
22654         POP      EAX\r
22655         JZ       @@popad_ret_true\r
22657 @@chk_anti:\r
22658         XCHG     EDX, EAX // EDX = filter[ i ]\r
22659         MOV      EAX, EDI // EAX = FileName\r
22660         CMP      byte ptr [EDX], '^'\r
22661         JNE      @@3\r
22663         INC      EDX\r
22664         CALL     _2StrSatisfy\r
22665         TEST     AL, AL\r
22666         JZ       @@4\r
22667         POPAD\r
22668         JMP      @@ret_false\r
22670 @@3:    CALL     _2StrSatisfy\r
22671         TEST     AL, AL\r
22672         JZ       @@4\r
22673 @@popad_ret_true:\r
22674         POPAD\r
22675 @@ret_true:\r
22676         MOV      AL, 1\r
22677         JMP      @@exit\r
22679 @@4:    POPAD\r
22680 @@nx_filter:\r
22681         LOOP     @@2\r
22683 @@ret_false:\r
22684         XOR      EAX, EAX\r
22685 @@exit:\r
22686         POP      EDI\r
22687         POP      ESI\r
22688         POP      EBX\r
22689 end;\r
22690 {$ELSE ASM_VERSION} //Pascal\r
22691 function TDirList.SatisfyFilter(FileName: PChar; FileAttr,\r
22692   FindAttr: DWord): Boolean;\r
22693 {$IFDEF F_P}\r
22694 const Dot: String = '.';\r
22695 {$ENDIF F_P}\r
22696 var I: Integer;\r
22697     F: PChar;\r
22698     HasOnlyNegFilters: Boolean;\r
22699 begin\r
22700   Result := (((FileAttr and FindAttr) = FindAttr) or\r
22701             LongBool(FindAttr and FILE_ATTRIBUTE_NORMAL));\r
22702   if not Result then Exit;\r
22704   if (FileName <> {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) and\r
22705      (FileName <> '..') then\r
22706   if LongBool( FindAttr and FILE_ATTRIBUTE_NORMAL ) and\r
22707      (FindAttr <> FILE_ATTRIBUTE_NORMAL) then\r
22708      if LongBool( FindAttr and FILE_ATTRIBUTE_DIRECTORY ) and\r
22709         LongBool( FileAttr and FILE_ATTRIBUTE_DIRECTORY ) then Exit;\r
22711   HasOnlyNegFilters := TRUE;\r
22712   for I := 0 to fFilters.fCount - 1 do\r
22713   begin\r
22714     F := PChar(fFilters.fList.fItems[ I ]);\r
22715     if F = '' then continue;\r
22717     if (F = {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) or (F = '..') then\r
22718     begin\r
22719       if FileName = F then\r
22720         Exit;\r
22721     end\r
22722       else\r
22723     if (Filename = {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) or (FileName = '..') then\r
22724     begin\r
22725       //Result := FALSE;\r
22726       continue;\r
22727     end;\r
22729     if F[ 0 ] = '^' then\r
22730     begin\r
22731       if StrSatisfy( FileName, PChar(@F[ 1 ]) ) then\r
22732       begin\r
22733          Result := False;\r
22734          Exit;\r
22735       end;\r
22736     end\r
22737       else\r
22738     begin\r
22739       HasOnlyNegFilters := FALSE;\r
22740       if StrSatisfy( FileName, F ) then\r
22741       begin\r
22742         Result := True;\r
22743         Exit;\r
22744       end;\r
22745     end;\r
22746   end;\r
22748   Result := HasOnlyNegFilters and\r
22749             (FileName <> {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) and\r
22750             (FileName <> '..');\r
22752 end;\r
22753 {$ENDIF ASM_VERSION}\r
22755 {$IFDEF ASM_VERSION}\r
22756 //[procedure TDirList.ScanDirectory]\r
22757 procedure TDirList.ScanDirectory(const DirPath, Filter: String;\r
22758   Attr: DWord);\r
22759 const   sz_win32finddata = sizeof(TWin32FindData);\r
22760 asm\r
22761         PUSH     EBX\r
22762         PUSH     EDI\r
22763         MOV      EBX, EAX\r
22765         PUSHAD\r
22766         CALL     Clear\r
22767         CALL     NewList\r
22768         MOV      [EBX].fList, EAX\r
22769         POPAD\r
22771         PUSHAD\r
22772         LEA      EAX, [EBX].fPath\r
22773         CALL     System.@LStrAsg\r
22774         POPAD\r
22776         MOV      EAX, [EBX].fPath\r
22777         TEST     EAX, EAX\r
22778         JE       @@exit\r
22780         PUSHAD\r
22781         LEA      EDX, [EBX].fPath\r
22782         MOV      EAX, [EDX]\r
22783         CALL     IncludeTrailingPathDelimiter\r
22785         MOV      EAX, [EBX].fFilters\r
22786         TEST     EAX, EAX\r
22787         JNZ      @@1\r
22788         CALL     NewStrList\r
22789         MOV      [EBX].fFilters, EAX\r
22790         POPAD\r
22792         PUSHAD\r
22793         PUSH     ECX\r
22794         XCHG     EAX, ECX\r
22795         MOV      EDX, offset[@@star_d_star]\r
22796         CALL     StrComp\r
22797         TEST     AL, AL\r
22798         POP      EDX\r
22799         JNZ      @@asg_Filter\r
22800         MOV      EDX, offset[@@star]\r
22801 @@asg_Filter:\r
22802         MOV      EAX, [EBX].fFilters\r
22803         CALL     TStrList.Add\r
22804         JMP      @@1\r
22806 @@star_d_star:\r
22807         DB       '*.*', 0\r
22808         DD       -1, 1\r
22809 @@star: DB       '*', 0\r
22811 @@1:\r
22812         POPAD\r
22814         ADD      ESP, -sz_win32finddata\r
22815         XOR      EDX, EDX\r
22816         PUSH     EDX\r
22817         PUSH     EDX\r
22818         XCHG     EAX, ECX\r
22819         MOV      EDX, ESP\r
22820         CALL     FindFilter\r
22822         LEA      EAX, [ESP+4]\r
22823         MOV      EDX, [EBX].fPath\r
22824         POP      ECX\r
22825         PUSH     ECX\r
22826         CALL     System.@LStrCat3\r
22827         CALL     RemoveStr\r
22829         POP      EAX\r
22830         MOV      EDX, ESP\r
22831         PUSH     EAX\r
22832         PUSH     EDX\r
22833         PUSH     EAX\r
22834         CALL     FindFirstFile\r
22835         MOV      EDI, EAX\r
22836         INC      EAX\r
22837         MOV      EAX, ESP\r
22839         PUSHFD\r
22840         CALL     System.@LStrClr\r
22841         POPFD\r
22842         POP      ECX\r
22844         JZ       @@fin\r
22846 @@loop:\r
22847         MOV      ECX, [ESP].TWin32FindData.dwFileAttributes\r
22848         PUSH     [Attr]\r
22849         LEA      EDX, [ESP+4].TWin32FindData.cFileName\r
22850         MOV      EAX, EBX\r
22851         CALL     SatisfyFilter\r
22853         TEST     AL, AL\r
22854         JZ       @@next\r
22856         MOV      ECX, [EBX].fOnItem.TMethod.Code\r
22857         JECXZ    @@accept\r
22858         MOV      EAX, [EBX].fOnItem.TMethod.Data\r
22859         MOV      ECX, ESP\r
22860         PUSH     1\r
22861         MOV      EDX, ESP\r
22862         PUSH     EDX\r
22863         MOV      EDX, EBX\r
22864         CALL     dword ptr [EBX].fOnItem.TMethod.Code\r
22865         POP      ECX\r
22866         JECXZ    @@next\r
22867         LOOP     @@fin\r
22869 @@accept:\r
22870         MOV      EAX, sz_win32finddata\r
22871         PUSH     EAX\r
22872           CALL     System.@GetMem\r
22873           PUSH     EAX\r
22874             XCHG     EDX, EAX\r
22875             MOV      EAX, [EBX].fList\r
22876             CALL     TList.Add\r
22877           POP      EDX\r
22878         POP      ECX\r
22879         MOV      EAX, ESP\r
22880         CALL     System.Move\r
22882 @@next:\r
22883         PUSH     ESP\r
22884         PUSH     EDI\r
22885         CALL     FindNextFile\r
22886         TEST     EAX, EAX\r
22887         JNZ      @@loop\r
22889         PUSH     EDI\r
22890         CALL     FindClose\r
22892 @@fin:\r
22893         ADD      ESP, sz_win32finddata\r
22894 @@exit:\r
22895         XOR      EAX, EAX\r
22896         XCHG     EAX, [EBX].fFilters\r
22897         CALL     TObj.Free\r
22898         POP      EDI\r
22899         POP      EBX\r
22900 end;\r
22901 {$ELSE ASM_VERSION} //Pascal\r
22902 procedure TDirList.ScanDirectory(const DirPath, Filter: String;\r
22903   Attr: DWord);\r
22904 var FindData : TWin32FindData;\r
22905     E : PWin32FindData;\r
22906     FindHandle : THandle;\r
22907     Action: TDirItemAction;\r
22908 begin\r
22909   Clear;\r
22910   FList := NewList;\r
22911   FPath := DirPath;\r
22912   if FPath = '' then Exit;\r
22913   FPath := IncludeTrailingPathDelimiter( FPath );\r
22914   if fFilters = nil then\r
22915   begin\r
22916     fFilters := NewStrList;\r
22917     if Filter = '*.*' then\r
22918       fFilters.Add( '*' )\r
22919     else\r
22920       fFilters.Add( Filter );\r
22921   end;\r
22922   FindHandle := FindFirstFile( PChar( FPath + FindFilter( Filter ) ),\r
22923                                FindData );\r
22924   if FindHandle = INVALID_HANDLE_VALUE then Exit;\r
22925   while True do\r
22926   begin\r
22927     if SatisfyFilter( PChar(@FindData.cFileName[0]),\r
22928                       FindData.dwFileAttributes, Attr ) then\r
22929     begin\r
22930       Action := diAccept;\r
22931       if Assigned( OnItem ) then\r
22932         OnItem( @Self, FindData, Action );\r
22933       CASE Action OF\r
22934       diSkip: ;\r
22935       diAccept:\r
22936         begin\r
22937           GetMem( E, Sizeof( FindData ) );\r
22938           E^ := FindData;\r
22939           FList.Add( E );\r
22940         end;\r
22941       diCancel: break;\r
22942       END;\r
22943     end;\r
22944     if not FindNextFile( FindHandle, FindData ) then break;\r
22945   end;\r
22946   FindClose( FindHandle );\r
22947   fFilters.Free;\r
22948   fFilters := nil;\r
22949 end;\r
22950 {$ENDIF ASM_VERSION}\r
22952 {$IFDEF ASM_VERSION}\r
22953 //[procedure TDirList.ScanDirectoryEx]\r
22954 procedure TDirList.ScanDirectoryEx(const DirPath, Filters: String;\r
22955   Attr: DWord);\r
22956 asm\r
22957         PUSH     EBX\r
22958         MOV      EBX, EAX\r
22960         PUSHAD\r
22961         CALL     NewStrList\r
22962         MOV      [EBX].fFilters, EAX\r
22963         POPAD\r
22965         PUSHAD\r
22966         PUSH     0\r
22967         MOV      EAX, ESP\r
22968         MOV      EDX, ECX\r
22969         CALL     System.@LStrLAsg\r
22970 @@1:    MOV      ECX, [ESP]\r
22971         JECXZ    @@2\r
22972         MOV      EAX, ESP\r
22973         MOV      EDX, offset[@@semicolon]\r
22974         PUSH     0\r
22975         MOV      ECX, ESP\r
22976         CALL     Parse\r
22977         MOV      EAX, [ESP]\r
22978         MOV      EDX, ESP\r
22979         CALL     Trim\r
22980         POP      EDX\r
22981         PUSH     EDX\r
22982         TEST     EDX, EDX\r
22983         JZ       @@filt_added\r
22984         MOV      EAX, [EBX].fFilters\r
22985         CALL     TStrList.Add\r
22986 @@filt_added:\r
22987         CALL     RemoveStr\r
22988         JMP      @@1\r
22990         //       ';' string literal\r
22991         DD       -1, 1\r
22992 @@semicolon:\r
22993         DB       ';',0\r
22995 @@2:    POP      ECX\r
22996         POPAD\r
22997         XOR      ECX, ECX\r
22998         PUSH     [Attr]\r
22999         CALL     ScanDirectory\r
23000         {XOR      EAX, EAX\r
23001         XCHG     EAX, [EBX].fFilters\r
23002         CALL     TObj.Free}\r
23003         POP      EBX\r
23004 @@exit:\r
23005 end;\r
23006 {$ELSE ASM_VERSION} //Pascal\r
23007 procedure TDirList.ScanDirectoryEx(const DirPath, Filters: String;\r
23008   Attr: DWord);\r
23009 var F, FF: String;\r
23010 begin\r
23011   FF := Filters;\r
23012   fFilters := NewStrList;\r
23013   while FF <> '' do\r
23014   begin\r
23015     F := Trim( Parse( FF, ';' ) );\r
23016     if F <> '' then\r
23017       fFilters.Add( F );\r
23018   end;\r
23019   ScanDirectory( DirPath, '', Attr );\r
23020 end;\r
23021 {$ENDIF ASM_VERSION}\r
23023 type\r
23024   PSortDirData = ^TSortDirData;\r
23025   TSortDirData = packed Record\r
23026     FoldersFirst, CaseSensitive : Boolean;\r
23027     Rules : array[ 0..11 ] of TSortDirRules;\r
23028     Dir : PDirList;\r
23029   end;\r
23031 //[FUNCTION CompareDirItems]\r
23032 {$IFDEF ASM_noVERSION}\r
23033 function CompareDirItems( const Data : PSortDirData; const e1, e2 : DWORD ) : Integer;\r
23034 asm\r
23035         PUSH     EBX\r
23036         PUSH     ESI\r
23037         PUSH     EDI\r
23038         XCHG     EBX, EAX\r
23039         MOV      EAX, [EBX].TSortDirData.Dir\r
23040         MOV      EAX, [EAX].TDirList.fList\r
23041         MOV      EAX, [EAX].TList.fItems\r
23042         MOV      ESI, [EAX+EDX*4]\r
23043         MOV      EDI, [EAX+ECX*4]\r
23044         MOV      DL, byte ptr[ESI].TWin32FindData.dwFileAttributes\r
23045         MOV      DH, byte ptr[EDI].TWin32FindData.dwFileAttributes\r
23046         AND      DX, 2020h\r
23047         XOR      EAX, EAX\r
23048         CMP      DL, DH\r
23049         JE       @@1\r
23050         CMP      [EBX].TSortDirData.FoldersFirst, AL\r
23051         JE       @@1\r
23052         OR       AL, DL\r
23053         JNE      @@exit_near\r
23054         DEC      EAX\r
23055         //JMP      @@exit\r
23056 @@exit_near:\r
23057         POP      EDI\r
23058         POP      ESI\r
23059         POP      EBX\r
23060         RET\r
23062 @@sdrByDateChanged:\r
23063         LEA      EAX, [ESI].TWin32FindData.ftLastWriteTime\r
23064         LEA      EDX, [EDI].TWin32FindData.ftLastWriteTime\r
23065         JMP      @@sdrByDate1\r
23067 @@sdrByDateAccessed:\r
23068         LEA      EAX, [ESI].TWin32FindData.ftLastAccessTime\r
23069         LEA      EDX, [EDI].TWin32FindData.ftLastAccessTime\r
23070         JMP      @@sdrByDate1\r
23072 @@jmp_table:\r
23073         DD       offset[@@exit1], offset[@@2], offset[@@2]\r
23074         DD       offset[@@sdrByName], offset[@@sdrByExt]\r
23075         DD       offset[@@sdrBySize], offset[@@sdrBySize]\r
23076         DD       offset[@@sdrByDateCreate], offset[@@sdrByDateChanged]\r
23077         DD       offset[@@sdrByDateAccessed]\r
23079 @@1:\r
23080         LEA      EDX, [EBX].TSortDirData.Rules\r
23081         PUSH     EDX\r
23082 @@2:\r
23083         POP      EDX\r
23084         XOR      EAX, EAX\r
23085         MOV      AL, [EDX]\r
23086         INC      EDX\r
23087         PUSH     EDX\r
23089         JMP      dword ptr [@@jmp_table+EAX*4]\r
23090         //////// ///////////////////\r
23092 @@sdrByDateCreate:\r
23093         LEA      EAX, [ESI].TWin32FindData.ftCreationTime\r
23094         LEA      EDX, [EDI].TWin32FindData.ftCreationTime\r
23095 @@sdrByDate1:\r
23096         PUSH     EDX\r
23097         PUSH     EAX     \r
23098         CALL     CompareFileTime\r
23099         TEST     EAX, EAX\r
23100         JE       @@2\r
23101         JMP      @@exit1\r
23103 @@sdrBySize:\r
23104         MOV      EAX, [ESI].TWin32FindData.nFileSizeHigh\r
23105         SUB      EAX, [EDI].TWin32FindData.nFileSizeHigh\r
23106         JNE      @@sdrBySize1\r
23107         MOV      EAX, [ESI].TWin32FindData.nFileSizeLow\r
23108         SUB      EAX, [EDI].TWin32FindData.nFileSizeLow\r
23109 @@to_2:\r
23110         JE       @@2\r
23111 @@sdrBySize1:\r
23112         POP      EDX\r
23113         DEC      EDX\r
23114         CMP      byte ptr[EDX], sdrBySizeDescending\r
23115         JNE      @@sdrBySize2\r
23116         NEG      EAX\r
23117 @@sdrBySize2:\r
23118         JNE      @@exit\r
23119         //////// ///////////////////\r
23121         DD       -1, 1\r
23122 @@point:DB       '.',0\r
23124 @@sdrByExt:\r
23125         LEA      EAX, [EDI].TWin32FindData.cFileName\r
23126         MOV      EDX, offset[@@point]\r
23127         PUSH     EDX\r
23128         CALL     __DelimiterLast\r
23129         POP      EDX\r
23130         PUSH     EAX\r
23131         LEA      EAX, [ESI].TWin32FindData.cFileName\r
23132         CALL     __DelimiterLast\r
23133         POP      EDX\r
23134         JMP      @@sdrByName0\r
23136 @@sdrByName:\r
23137         LEA      EAX, [ESI].TWin32FindData.cFileName\r
23138         LEA      EDX, [EDI].TWin32FindData.cFileName\r
23139 @@sdrByName0:\r
23140         CMP      [EBX].TSortDirData.CaseSensitive, 0\r
23141         JNE      @@sdrByName1\r
23142         CALL     _AnsiCompareStrNoCase\r
23143         JMP      @@sdrByName2\r
23144 @@sdrByName1:\r
23145         CALL     _AnsiCompareStr\r
23146 @@sdrByName2:\r
23147         TEST     EAX, EAX\r
23148         JE       @@to_2\r
23149         //JMP    @@exit1\r
23151 @@exit1:\r
23152         POP      EDX\r
23153 @@exit:\r
23154         POP      EDI\r
23155         POP      ESI\r
23156         POP      EBX\r
23157 end;\r
23158 {$ELSE ASM_VERSION} //Pascal\r
23159 function CompareDirItems( const Data : PSortDirData; const e1, e2 : DWORD ) : Integer;\r
23160 var I : Integer;\r
23161     Item1, Item2 : PWin32FindData;\r
23162     S1, S2 : PChar;\r
23163     IsDir1, IsDir2 : Boolean;\r
23164     Date1, Date2 : PFileTime;\r
23165 begin\r
23166   Item1 := Data.Dir.fList.fItems[ e1 ];\r
23167   Item2 := Data.Dir.fList.fItems[ e2 ];\r
23168   Result := 0;\r
23169   IsDir1 := (Item1.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0;\r
23170   IsDir2 := (Item2.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0;\r
23171   if (IsDir1 <> IsDir2) and Data.FoldersFirst then\r
23172   begin\r
23173     if IsDir1 then Result := -1 else Result := 1;\r
23174     exit;\r
23175   end;\r
23176   for I := 0 to High(Data.Rules) do\r
23177   begin\r
23178     case Data.Rules[ I ] of\r
23179     sdrByName:\r
23180       begin\r
23181         S1 := Item1.cFileName;\r
23182         S2 := Item2.cFileName;\r
23183         if not Data.CaseSensitive then\r
23184           Result := _AnsiCompareStrNoCase( S1, S2 )\r
23185         else\r
23186           Result := _AnsiCompareStr( S1, S2 );\r
23187       end;\r
23188     sdrByExt:\r
23189       begin\r
23190         S1 := Item1.cFileName;\r
23191         S2 := Item2.cFileName;\r
23192         S1 := __DelimiterLast( S1, '.' );\r
23193         S2 := __DelimiterLast( S2, '.' );\r
23194         if not Data.CaseSensitive then\r
23195            Result := _AnsiCompareStrNoCase( S1, S2 )\r
23196         else\r
23197            Result := _AnsiCompareStr( S1, S2 );\r
23198       end;\r
23199     sdrBySize, sdrBySizeDescending:\r
23200       begin\r
23201         if Item1.nFileSizeHigh < Item2.nFileSizeHigh then\r
23202            Result := -1\r
23203         else\r
23204         if Item1.nFileSizeHigh > Item2.nFileSizeHigh then\r
23205            Result := 1\r
23206         else\r
23207         if Item1.nFileSizeLow < Item2.nFileSizeLow then\r
23208            Result := -1\r
23209         else\r
23210         if Item1.nFileSizeLow > Item2.nFileSizeLow then\r
23211            Result := 1;\r
23212         if Data.Rules[ I ] = sdrBySizeDescending then\r
23213            Result := -Result;\r
23214       end;\r
23215     sdrByDateCreate:\r
23216       begin\r
23217         Date1 := @Item1.ftCreationTime;\r
23218         Date2 := @Item2.ftCreationTime;\r
23219         Result := CompareFileTime( Date1^, Date2^ );\r
23220       end;\r
23221     sdrByDateChanged:\r
23222       begin\r
23223         Date1 := @Item1.ftLastWriteTime;\r
23224         Date2 := @Item2.ftLastWriteTime;\r
23225         Result := CompareFileTime( Date1^, Date2^ );\r
23226       end;\r
23227     sdrByDateAccessed:\r
23228       begin\r
23229         Date1 := @Item1.ftLastAccessTime;\r
23230         Date2 := @Item2.ftLastAccessTime;\r
23231         Result := CompareFileTime( Date1^, Date2^ );\r
23232       end;\r
23233     end; {case}\r
23234     if Result <> 0 then break;\r
23235   end;\r
23236 end;\r
23237 {$ENDIF ASM_VERSION}\r
23238 //[END CompareDirItems]\r
23240 //[PROCEDURE SwapDirItems]\r
23241 {$IFDEF ASM_VERSION}\r
23242 procedure SwapDirItems( const Data : PSortDirData; const e1, e2 : DWORD );\r
23243 asm\r
23244         MOV      EAX, [EAX].TSortDirData.Dir\r
23245         MOV      EAX, [EAX].TDirList.fList\r
23246         MOV      EAX, [EAX].TList.fItems\r
23247         LEA      EDX, [EAX+EDX*4]\r
23248         LEA      ECX, [EAX+ECX*4]\r
23249         MOV      EAX, [EDX]\r
23250         XCHG     EAX, [ECX]\r
23251         MOV      [EDX], EAX\r
23252 end;\r
23253 {$ELSE ASM_VERSION} //Pascal\r
23254 procedure SwapDirItems( const Data : PSortDirData; const e1, e2 : DWORD );\r
23255 var Tmp : Pointer;\r
23256 begin\r
23257   Tmp := Data.Dir.FList.fItems[ e1 ];\r
23258   Data.Dir.FList.fItems[ e1 ] := Data.Dir.FList.fItems[ e2 ];\r
23259   Data.Dir.FList.fItems[ e2 ] := Tmp;\r
23260 end;\r
23261 {$ENDIF ASM_VERSION}\r
23262 //[END SwapDirItems]\r
23265   TSortDirData = packed Record\r
23266     FoldersFirst, CaseSensitive : Boolean;\r
23267     Rules : array[ 0..11 ] of TSortDirRules;\r
23268     Dir : PDirList;\r
23269   end;\r
23271 {$IFDEF ASM_VERSION}\r
23272 procedure TDirList.Sort(Rules: array of TSortDirRules);\r
23273 const   high_DefSortDirRules = High( DefSortDirRules );\r
23274 asm\r
23275         PUSH     EBX\r
23276         PUSH     ESI\r
23277         XOR      EBX,EBX\r
23278         CMP      [EAX].fList, EBX\r
23279         JE       @@exit\r
23281         PUSH     EAX           // prepare Dir = @Self\r
23282         XOR      EAX, EAX\r
23283         PUSH     EAX\r
23284         PUSH     EAX\r
23285         PUSH     EAX\r
23286         MOV      ESI, ESP\r
23287         INC      ECX           // ECX = High(Rules)\r
23288         JZ       @@2\r
23289 @@1:    MOV      AH, [EDX]     // AH = Rules[ I ]\r
23290         INC      EDX\r
23291         CALL     @@add_rule\r
23292         LOOP     @@1\r
23293 @@2:    LEA      EDX, [DefSortDirRules]\r
23294         MOV      CL, high_DefSortDirRules + 1\r
23295 @@21:   MOV      AH, [EDX]\r
23296         INC      EDX\r
23297         CALL     @@add_rule\r
23298         LOOP     @@21\r
23300         PUSH     BX           // prepare FoldersFirst(BL), CaseSensitive(BH)\r
23301         MOV      EBX, [ESP].TSortDirData.Dir\r
23302         MOV      EAX, ESP\r
23303         PUSH     offset[SwapDirItems]\r
23304         MOV      ECX, offset[CompareDirItems]\r
23305         MOV      EDX, [EBX].fList\r
23306         MOV      EDX, [EDX].TList.fCount\r
23307         CALL     SortData\r
23309         ADD      ESP, 18\r
23310         JMP      @@exit\r
23312 @@add_rule:\r
23313         PUSH     ESI\r
23314         PUSH     ECX\r
23315         MOV      CL, 11\r
23316 @@a1:   LODSB\r
23317         TEST     AL, AL\r
23318         JZ       @@a2\r
23319         CMP      AL, AH\r
23320         JE       @@a3\r
23321         LOOP     @@a1\r
23322 @@a2:   DEC      ESI\r
23323         MOV      [ESI], AH\r
23324         CMP      AH, sdrFoldersFirst\r
23325         JNE      @@a4\r
23326         INC      BL\r
23327 @@a4:   CMP      AH, sdrCaseSensitive\r
23328         JNE      @@a3\r
23329         INC      BH\r
23330 @@a3:   POP      ECX\r
23331         POP      ESI\r
23332         RET\r
23334 @@exit:\r
23335         POP      ESI\r
23336         POP      EBX\r
23337 end;\r
23338 {$ELSE ASM_VERSION} //Pascal\r
23339 procedure TDirList.Sort(Rules: array of TSortDirRules);\r
23340 var SortDirData : TSortDirData;\r
23341     I, J : Integer;\r
23343     function RulePresent( Rule : TSortDirRules ) : Boolean;\r
23344     var K : Integer;\r
23345     begin\r
23346       Result := True;\r
23347       for K := J - 1 downto 0 do\r
23348         if Rule = SortDirData.Rules[ K ] then exit;\r
23349       Result := False;\r
23350     end;\r
23352     procedure AddRule( Rule : TSortDirRules );\r
23353     begin\r
23354       if J > High( SortDirData.Rules ) then exit;\r
23355       if RulePresent( Rule ) then exit;\r
23356       SortDirData.Rules[ J ] := Rule;\r
23357       Inc( J );\r
23358     end;\r
23359 begin\r
23360   if fList = nil then Exit;\r
23361   J := 0;\r
23362   for I := 0 to High(Rules) do\r
23363     AddRule( Rules[ I ] );\r
23364   for I := 0 to High(DefSortDirRules) do\r
23365     AddRule( DefSortDirRules[ I ] );\r
23366   while J < High( SortDirData.Rules ) do\r
23367   begin\r
23368     SortDirData.Rules[ J ] := sdrNone;\r
23369     Inc( J );\r
23370   end;\r
23372   SortDirData.Dir := @Self;\r
23373   SortDirData.FoldersFirst := RulePresent( sdrFoldersFirst );\r
23374   SortDirData.CaseSensitive := RulePresent( sdrCaseSensitive );\r
23375   SortData( Pointer( @SortDirData ), fList.fCount, @CompareDirItems, @SwapDirItems );\r
23376 end;\r
23377 {$ENDIF ASM_VERSION}\r
23380 //[function TDirList.FileList]\r
23381 function TDirList.FileList(const Separator: String; Dirs,\r
23382   FullPaths: Boolean): String;\r
23383 var I: Integer;\r
23384 begin\r
23385   Result := '';\r
23386   for I := 0 to Count-1 do\r
23387   begin\r
23388     if not Dirs and IsDirectory[ I ] then Continue;\r
23389     if FullPaths then\r
23390       Result := Result + Path;\r
23391     Result := Result + Names[ I ] + Separator;\r
23392   end;\r
23393 end;\r
23399 ////////////////////////////////////////////////////////////////////////\r
23400 //\r
23401 //\r
23402 //                        R  E  G  I  S  T  R  Y\r
23403 //\r
23404 //\r
23405 ////////////////////////////////////////////////////////////////////////\r
23409 {++}(*\r
23410 function RegSetValueEx; external advapi32 name 'RegSetValueExA';\r
23411 *){--}\r
23414 { -- registry -- }\r
23416 //[function RegKeyOpenRead]\r
23417 function RegKeyOpenRead( Key: HKey; const SubKey: String ): HKey;\r
23418 begin\r
23419   if RegOpenKeyEx( Key, PChar( SubKey ), 0, KEY_READ, Result ) <> ERROR_SUCCESS then\r
23420      Result := 0;\r
23421 end;\r
23423 //[function RegKeyOpenWrite]\r
23424 function RegKeyOpenWrite( Key: HKey; const SubKey: String ): HKey;\r
23425 begin\r
23426   if RegOpenKeyEx( Key, PChar( SubKey ), 0, KEY_READ or KEY_WRITE, Result ) <> ERROR_SUCCESS then\r
23427      Result := 0;\r
23428 end;\r
23430 //[function RegKeyOpenCreate]\r
23431 function RegKeyOpenCreate( Key: HKey; const SubKey: String ): HKey;\r
23432 var dwDisp: DWORD;\r
23433 begin\r
23434   if RegCreateKeyEx( Key, PChar( SubKey ), 0, nil, 0, KEY_ALL_ACCESS, nil, Result,\r
23435                      @dwDisp ) <> ERROR_SUCCESS then\r
23436     Result := 0;\r
23437 end;\r
23439 //[function RegKeyGetDw]\r
23440 function RegKeyGetDw( Key: HKey; const ValueName: String ): DWORD;\r
23441 var dwType, dwSize: DWORD;\r
23442 begin\r
23443   dwSize := sizeof( DWORD );\r
23444   Result := 0;\r
23445   if (Key = 0) or\r
23446      (RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType, PByte( @Result ), @dwSize ) <> ERROR_SUCCESS)\r
23447      or (dwType <> REG_DWORD) then Result := 0;\r
23448 end;\r
23450 //[function RegKeyGetStr]\r
23451 function RegKeyGetStr( Key: HKey; const ValueName: String ): String;\r
23452 var dwType, dwSize: DWORD;\r
23453     Buffer: PChar;\r
23455     function Query: Boolean;\r
23456     begin\r
23457       Result := RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType,\r
23458                 Pointer( Buffer ), @dwSize ) = ERROR_SUCCESS;\r
23459     end;\r
23460 begin\r
23461   Result := '';\r
23462   if Key = 0 then Exit;\r
23463   dwSize := 0;\r
23464   Buffer := nil;\r
23465   if not Query or (dwType <> REG_SZ) then Exit;\r
23466   GetMem( Buffer, dwSize );\r
23467   if Query then\r
23468     Result := Buffer;\r
23469   FreeMem( Buffer );\r
23470 end;\r
23472 //[function RegKeyGetStrEx]\r
23473 function RegKeyGetStrEx( Key: HKey; const ValueName: String ): String;\r
23474 var dwType, dwSize: DWORD;\r
23475     Buffer, Buffer2: PChar;\r
23476     Sz: Integer;\r
23477     function Query: Boolean;\r
23478     begin\r
23479       Result := RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType,\r
23480                 Pointer( Buffer ), @dwSize ) = ERROR_SUCCESS;\r
23481     end;\r
23482 begin\r
23483   Result := '';\r
23484   if Key = 0 then Exit;\r
23485   dwSize := 0;\r
23486   Buffer := nil;\r
23487   if not Query or ((dwType <> REG_SZ) and (dwtype <> REG_EXPAND_SZ)) then Exit;\r
23488   GetMem( Buffer, dwSize );\r
23489   if Query then\r
23490   begin\r
23491     if dwtype = REG_EXPAND_SZ then\r
23492     begin\r
23493       //------------------------------------------------------ by Dmitry Zharov\r
23494       // Sz := ExpandEnvironmentStrings(Buffer,nil,0);         18-Aug-2004\r
23495       // SetLength( Result, Sz );\r
23496       // ExpandEnvironmentStrings(Buffer, PChar(Result), Sz);\r
23497       //---------------------------------------------//\r
23498       Sz := ExpandEnvironmentStrings(Buffer,nil,0);  // bug in size detection! sometimes we get an additional 2 bytes at the end...\r
23499       GetMem(Buffer2,Sz);                            //\r
23500       ExpandEnvironmentStrings(Buffer, Buffer2, Sz); //\r
23501       Result:=Buffer2;                               //\r
23502       FreeMem(Buffer2);                              //\r
23503       //---------------------------------------------//\r
23504     end\r
23505       else\r
23506     Result := Buffer;\r
23507   end;\r
23508   FreeMem( Buffer );\r
23509 end;\r
23511 //[function RegKeySetDw]\r
23512 function RegKeySetDw( Key: HKey; const ValueName: String; Value: DWORD ): Boolean;\r
23513 begin\r
23514   Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0, REG_DWORD, @Value, sizeof( DWORD ) )\r
23515             = ERROR_SUCCESS);\r
23516 end;\r
23518 //[function RegKeySetStr]\r
23519 function RegKeySetStr( Key: HKey; const ValueName: String; const Value: String ): Boolean;\r
23520 begin\r
23521   Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0,\r
23522             REG_SZ, PChar(Value),\r
23523              Length( Value ) + 1 ) = ERROR_SUCCESS);\r
23524 end;\r
23526 //[function RegKeySetStrEx]\r
23527 function RegKeySetStrEx( Key: HKey; const ValueName: string; const Value: string;\r
23528                          expand: boolean): Boolean;\r
23529 var dwType: DWORD;\r
23530 begin\r
23531   dwType := REG_SZ;\r
23532   if expand then\r
23533     dwType := REG_EXPAND_SZ;\r
23534   Result := (Key <> 0) and (RegSetValueEx(Key, PChar(ValueName), 0, dwType,\r
23535             PChar(Value), Length(Value) + 1) = ERROR_SUCCESS);\r
23536 end;\r
23538 //[procedure RegKeyClose]\r
23539 procedure RegKeyClose( Key: HKey );\r
23540 begin\r
23541   if Key <> 0 then\r
23542     RegCloseKey( Key );\r
23543 end;\r
23545 //[function RegKeyDelete]\r
23546 function RegKeyDelete( Key: HKey; const SubKey: String ): Boolean;\r
23547 begin\r
23548   Result := FALSE;\r
23549   if Key <> 0 then\r
23550     Result := RegDeleteKey( Key, PChar( SubKey ) ) = ERROR_SUCCESS;\r
23551 end;\r
23553 //[function RegKeyDeleteValue]\r
23554 function RegKeyDeleteValue( Key: HKey; const SubKey: String ): Boolean;\r
23555 begin\r
23556   Result := FALSE;\r
23557   if Key <> 0 then\r
23558     Result := RegDeleteValue( Key, PChar( SubKey ) ) = ERROR_SUCCESS;\r
23559 end;\r
23561 //[function RegKeyExists]\r
23562 function RegKeyExists( Key: HKey; const SubKey: String ): Boolean;\r
23563 var K: Integer;\r
23564 begin\r
23565   if Key = 0 then\r
23566   begin\r
23567     Result := FALSE;\r
23568     Exit;\r
23569   end;\r
23570   K := RegKeyOpenRead( Key, SubKey );\r
23571   Result := K <> 0;\r
23572   if K <> 0 then\r
23573     RegKeyClose( K );\r
23574 end;\r
23576 //[function RegKeyValExists]\r
23577 function RegKeyValExists( Key: HKey; const ValueName: String ): Boolean;\r
23578 var dwType, dwSize: DWORD;\r
23579 begin\r
23580   Result := (Key <> 0) and\r
23581             (RegQueryValueEx( Key, PChar( ValueName ), nil,\r
23582             @dwType, nil, @dwSize ) = ERROR_SUCCESS);\r
23583 end;\r
23585 //[function RegKeyValueSize]\r
23586 function RegKeyValueSize( Key: HKey; const ValueName: String ): Integer;\r
23587 begin\r
23588   Result := 0;\r
23589   if Key = 0 then Exit;\r
23590   RegQueryValueEx( Key, PChar( ValueName ), nil, nil, nil, @ DWORD( Result ) );\r
23591 end;\r
23593 //[function RegKeyGetBinary]\r
23594 function RegKeyGetBinary( Key: HKey; const ValueName: String; var Buffer; Count: Integer ): Integer;\r
23595 begin\r
23596   Result := 0;\r
23597   if Key = 0 then Exit;\r
23598   Result := Count;\r
23599   RegQueryValueEx( Key, PChar( ValueName ), nil, nil, @ Buffer, @ Result );\r
23600 end;\r
23602 //[function RegKeySetBinary]\r
23603 function RegKeySetBinary( Key: HKey; const ValueName: String; const Buffer; Count: Integer ): Boolean;\r
23604 begin\r
23605   Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0,\r
23606                     REG_BINARY, @ Buffer, Count ) = ERROR_SUCCESS);\r
23607 end;\r
23609 //[function RegKeyGetDateTime]\r
23610 function RegKeyGetDateTime(Key: HKey; const ValueName: String): TDateTime;\r
23611 begin\r
23612   RegKeyGetBinary( Key, ValueName, Result, Sizeof( Result ) );\r
23613 end;\r
23615 //[function RegKeySetDateTime]\r
23616 function RegKeySetDateTime(Key: HKey; const ValueName: String; DateTime: TDateTime): Boolean;\r
23617 begin\r
23618   Result := RegKeySetBinary( Key, ValueName, DateTime, Sizeof( DateTime ) );\r
23619 end;\r
23621 //-----------------------------------------------\r
23622 // functions by Valerian Luft <luft@valerian.de>\r
23623 //-----------------------------------------------\r
23624 //[function RegKeyGetSubKeys]\r
23625 function RegKeyGetSubKeys( const Key: HKEY; List: PStrList) : Boolean;\r
23626 var\r
23627   I, Size, NumSubKeys, MaxSubKeyLen : DWORD;\r
23628   KeyName: String;\r
23629 begin\r
23630   Result := False;\r
23631   List.Clear ;\r
23632   if RegQueryInfoKey(Key, nil, nil, nil, @NumSubKeys, @MaxSubKeyLen, nil, nil, nil, nil,\r
23633 nil, nil) = ERROR_SUCCESS then\r
23634     begin\r
23635       if NumSubKeys > 0 then begin\r
23636         for I := 0 to NumSubKeys-1 do\r
23637         begin\r
23638           Size := MaxSubKeyLen+1;\r
23639           SetLength(KeyName, Size);\r
23640           //FillChar(KeyName[1],Size,#0);\r
23641           RegEnumKeyEx(Key, I, @KeyName[1], Size, nil, nil, nil, nil);\r
23642           SetLength(KeyName, lstrlen(@KeyName[1]));\r
23643           List.Add(KeyName);\r
23644         end;\r
23645       end;\r
23646       Result:= True;\r
23647   end;\r
23648 end;\r
23651 //[function RegKeyGetValueNames]\r
23652 function RegKeyGetValueNames(const Key: HKEY; List: PStrList): Boolean;\r
23653 var\r
23654   I, Size, NumSubKeys, NumValueNames, MaxValueNameLen: DWORD;\r
23655   ValueName: String;\r
23656 begin\r
23657   List.Clear ;\r
23658   Result:=False;\r
23659   if RegQueryInfoKey(Key, nil, nil, nil, @NumSubKeys, nil, nil, @NumValueNames,\r
23660 @MaxValueNameLen, nil, nil, nil) = ERROR_SUCCESS then\r
23661   begin\r
23662      if NumValueNames > 0 then\r
23663         for I := 0 to NumValueNames - 1 do begin\r
23664           Size := MaxValueNameLen + 1;\r
23665           SetLength(ValueName, Size);\r
23666           //FillChar(ValueName[1],Size,#0);\r
23667           RegEnumValue(Key, I, @ValueName[1], Size, nil, nil, nil, nil);\r
23668           SetLength(ValueName, lstrlen(@ValueName[1]));\r
23669           List.Add(ValueName);\r
23670         end;\r
23671      Result := True;\r
23672   end ;\r
23673 end;\r
23676 //[function RegKeyGetValueTyp]\r
23677 function RegKeyGetValueTyp (const Key:HKEY; const ValueName: String) : DWORD;\r
23678 begin\r
23679 Result:= Key ;\r
23680 if Key <> 0 then\r
23681    RegQueryValueEx (Key,@ValueName[1],NIL,@Result,NIL,NIL)\r
23682 end;\r
23696 { -- TDirChange -- }\r
23698 const FilterFlags: array[ TFileChangeFilters ] of Integer = (\r
23699       FILE_NOTIFY_CHANGE_FILE_NAME, FILE_NOTIFY_CHANGE_DIR_NAME,\r
23700       FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_NOTIFY_CHANGE_SIZE,\r
23701       FILE_NOTIFY_CHANGE_LAST_WRITE, $20 {FILE_NOTIFY_CHANGE_LAST_ACCESS},\r
23702       $40 {FILE_NOTIFY_CHANGE_CREATION}, FILE_NOTIFY_CHANGE_SECURITY );\r
23704 //[FUNCTION _NewDirChgNotifier]\r
23705 {$IFDEF ASM_VERSION}\r
23706 function _NewDirChgNotifier: PDirChange;\r
23707 begin\r
23708   New( Result, Create );\r
23709 end;\r
23710 //[function NewDirChangeNotifier]\r
23711 function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;\r
23712                                WatchSubtree: Boolean; ChangeProc: TOnDirChange )\r
23713                                : PDirChange;\r
23714 const Dflt_Flags = FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or\r
23715       FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or\r
23716       FILE_NOTIFY_CHANGE_LAST_WRITE;\r
23717 asm\r
23718         PUSH     EBX\r
23719         PUSH     ECX // [EBP-8] = WatchSubtree\r
23720         PUSH     EDX // [EBP-12] = Filter\r
23721         PUSH     EAX // [EBP-16] = Path\r
23722         CALL     _NewDirChgNotifier\r
23723         XCHG     EBX, EAX\r
23724         LEA      EAX, [EBX].TDirChange.FPath\r
23725         POP      EDX\r
23726         CALL     System.@LStrAsg\r
23727         MOV      EAX, [ChangeProc].TMethod.Code\r
23728         MOV      [EBX].TDirChange.FOnChange.TMethod.Code, EAX\r
23729         MOV      EAX, [ChangeProc].TMethod.Data\r
23730         MOV      [EBX].TDirChange.FOnChange.TMethod.Data, EAX\r
23731         POP      ECX\r
23732         MOV      EAX, Dflt_Flags\r
23733         MOVZX    ECX, CL\r
23734         JECXZ    @@flags_ready\r
23735         PUSH     ECX\r
23736         MOV      EAX, ESP\r
23737         MOV      EDX, offset[FilterFlags]\r
23738         XOR      ECX, ECX\r
23739         MOV      CL, 7\r
23740         CALL     MakeFlags\r
23741         POP      ECX\r
23742 @@flags_ready:           // EAX = Flags\r
23743         POP      EDX\r
23744         MOVZX    EDX, DL // EDX = WatchSubtree\r
23745         PUSH     EAX\r
23746         PUSH     EDX\r
23747         PUSH     [EBX].TDirChange.FPath\r
23748         CALL     FindFirstChangeNotification\r
23749         MOV      [EBX].TDirChange.FHandle, EAX\r
23750         INC      EAX\r
23751         JZ       @@fault\r
23752         PUSH     EBX\r
23753         PUSH     offset[TDirChange.Execute]\r
23754         CALL     NewThreadEx\r
23755         MOV      [EBX].TDirChange.FMonitor, EAX\r
23756         JMP      @@exit\r
23757 @@fault:\r
23758         XCHG     EAX, EBX\r
23759         CALL     TObj.Free\r
23760 @@exit:\r
23761         XCHG     EAX, EBX\r
23762         POP      EBX\r
23763 end;\r
23764 {$ELSE ASM_VERSION} //Pascal\r
23765 function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;\r
23766                                WatchSubtree: Boolean; ChangeProc: TOnDirChange )\r
23767                                : PDirChange;\r
23768 var Flags: DWORD;\r
23769 begin\r
23770   {-}\r
23771   New( Result, Create );\r
23772   {+}{++}(*Result := PDirChange.Create;*){--}\r
23774   Result.FPath := Path;\r
23775   Result.FOnChange := ChangeProc;\r
23776   if Filter = [ ] then\r
23777     Flags := FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or\r
23778       FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or\r
23779       FILE_NOTIFY_CHANGE_LAST_WRITE\r
23780   else\r
23781     Flags := MakeFlags( @Filter, FilterFlags );\r
23782   Result.FHandle := FindFirstChangeNotification(PChar(Result.FPath),\r
23783                     Bool( Integer( WatchSubtree ) ), Flags);\r
23784   if Result.FHandle <> INVALID_HANDLE_VALUE then\r
23785     Result.FMonitor := NewThreadEx( Result.Execute )\r
23786   else //MsgOK( 'Can not monitor ' + Result.FPath + #13'Error ' + Int2Str( GetLastError ) );\r
23787   begin\r
23788     Result.Free;\r
23789     Result := nil;\r
23790   end;\r
23791 end;\r
23792 {$ENDIF ASM_VERSION}\r
23793 //[END _NewDirChgNotifier]\r
23795 { TDirChange }\r
23797 {$IFDEF ASM_VERSION}\r
23798 //[procedure TDirChange.Changed]\r
23799 procedure TDirChange.Changed;\r
23800 asm\r
23801         MOV      ECX, [EAX].FPath\r
23802         XCHG     EDX, EAX\r
23803         MOV      EAX, [EDX].FOnChange.TMethod.Data\r
23804         CALL     [EDX].FOnChange.TMethod.Code\r
23805 end;\r
23806 {$ELSE ASM_VERSION} //Pascal\r
23807 procedure TDirChange.Changed;\r
23808 begin\r
23809   FOnChange(@Self, FPath); // must be assigned always!!!\r
23810 end;\r
23811 {$ENDIF ASM_VERSION}\r
23813 {$IFDEF ASM_VERSION}\r
23814 //[destructor TDirChange.Destroy]\r
23815 destructor TDirChange.Destroy;\r
23816 asm\r
23817         PUSH     EBX\r
23818         XCHG     EBX, EAX\r
23819         MOV      ECX, [EBX].FMonitor\r
23820         JECXZ    @@no_monitor\r
23821         XCHG     EAX, ECX\r
23822         CALL     TObj.Free\r
23823 @@no_monitor:\r
23824         MOV      ECX, [EBX].FHandle\r
23825         JECXZ    @@exit\r
23826         PUSH     ECX\r
23827         CALL     FindCloseChangeNotification\r
23828 @@exit:\r
23829         LEA      EAX, [EBX].FPath\r
23830         CALL     System.@LStrClr\r
23831         XCHG     EAX, EBX\r
23832         CALL     TObj.Destroy\r
23833         POP      EBX\r
23834 end;\r
23835 {$ELSE ASM_VERSION} //Pascal\r
23836 destructor TDirChange.Destroy;\r
23837 begin\r
23838   if FMonitor <> nil then\r
23839      FMonitor.Free;\r
23840   if FHandle > 0 then // FHandle <> INVALID_HANDLE_VALUE AND FHandle <> 0\r
23841      FindCloseChangeNotification(FHandle);\r
23842   FPath := '';\r
23843   inherited;\r
23844 end;\r
23845 {$ENDIF ASM_VERSION}\r
23847 {$IFDEF ASM_noVERSION}\r
23848 //[function TDirChange.Execute]\r
23849 function TDirChange.Execute(Sender: PThread): Integer;\r
23850 asm\r
23851         PUSH     EBX\r
23852         PUSH     ESI\r
23853         XCHG     EBX, EAX\r
23854         MOV      ESI, EDX\r
23855 @@loo:\r
23856         MOVZX    ECX, [ESI].TThread.FTerminated\r
23857         INC      ECX\r
23858         LOOP     @@e_loop\r
23860         MOV      ECX, [EBX].FHandle\r
23861         INC      ECX\r
23862         JZ       @@e_loop\r
23864         PUSH     INFINITE\r
23865         PUSH     ECX\r
23866         CALL     WaitForSingleObject\r
23867         OR       EAX, EAX\r
23868         JNZ      @@loo\r
23870         PUSH     [EBX].FHandle\r
23871         MOV      EAX, [EBX].FMonitor\r
23872         PUSH     EBX\r
23873         PUSH     offset[TDirChange.Changed]\r
23874         CALL     TThread.Synchronize\r
23875         CALL     FindNextChangeNotification\r
23876         JMP      @@loo\r
23877 @@e_loop:\r
23879         POP      ESI\r
23880         POP      EBX\r
23881         XOR      EAX, EAX\r
23882 end;\r
23883 {$ELSE ASM_VERSION} //Pascal\r
23884 function TDirChange.Execute(Sender: PThread): Integer;\r
23885 begin\r
23886   while (not Sender.Terminated and (FHandle <> INVALID_HANDLE_VALUE)) do\r
23887     if (WaitForSingleObject(FHandle, INFINITE) = WAIT_OBJECT_0) then\r
23888     begin\r
23889       if AppletTerminated then break;\r
23890       Applet.GetWindowHandle;\r
23891       FMonitor.Synchronize( Changed );\r
23892       FindNextChangeNotification(FHandle);\r
23893     end;\r
23894   Result := 0;\r
23895 end;\r
23896 {$ENDIF ASM_VERSION}\r
23910 //////////////////////////////////////////////////////////////////////\r
23911 //\r
23912 //\r
23913 //                D  A  T  E     A  N  D     T  I  M  E\r
23914 //\r
23915 //\r
23916 //////////////////////////////////////////////////////////////////////\r
23928 { -- date and time utilities -- }\r
23930 {* This part of the unit contains date-time routines. It is not a simple compilation\r
23931    of Delphi VCL date-time. E.g., TDateTime type is not based on 31-Dec-1899,\r
23932    but it is based on 31-Dec-0000 instead, allowing easy manipulating of dates\r
23933    at all Christian era, and all other historical era too. }\r
23935 //[procedure DivMod]\r
23936 procedure DivMod(Dividend: Integer; Divisor: Word;\r
23937   var Result, Remainder: Word);\r
23938 {$IFDEF F_P}\r
23939 begin\r
23940         Result    := Dividend div Divisor;\r
23941         Remainder := Dividend mod Divisor;\r
23942 end;\r
23943 {$ELSE DELPHI}\r
23944 asm\r
23945         PUSH    EBX\r
23946         MOV     EBX,EDX\r
23947         MOV     EDX,EAX\r
23948         SHR     EDX,16\r
23949         DIV     BX\r
23950         MOV     EBX,Remainder\r
23951         MOV     [ECX],AX\r
23952         MOV     [EBX],DX\r
23953         POP     EBX\r
23954 end;\r
23955 {$ENDIF}\r
23957 {++}(*\r
23958 //[API GetLocalTime, GetSystemTime]\r
23959 procedure GetLocalTime; external kernel32 name 'GetLocalTime';\r
23960 procedure GetSystemTime; external kernel32 name 'GetSystemTime';\r
23961 *){--}\r
23963 //*\r
23964 //[function Now]\r
23965 function Now : TDateTime;\r
23966 var SystemTime : TSystemTime;\r
23967 begin\r
23968    GetLocalTime( SystemTime );\r
23969    SystemTime2DateTime( SystemTime, Result );\r
23970 end;\r
23972 //[function Date]\r
23973 function Date: TDateTime;\r
23974 begin\r
23975   Result := Trunc( Now );\r
23976 end;\r
23978 //[procedure DecodeDateFully]\r
23979 procedure DecodeDateFully( DateTime: TDateTime; var Year, Month, Day, DayOfWeek: WORD );\r
23980 var ST: TSystemTime;\r
23981 begin\r
23982   DateTime2SystemTime( DateTime, ST );\r
23983   Year := ST.wYear;\r
23984   Month := ST.wMonth;\r
23985   Day := ST.wDay;\r
23986   DayOfWeek := ST.wDayOfWeek;\r
23987 end;\r
23989 //[procedure DecodeDate]\r
23990 procedure DecodeDate( DateTime: TDateTime; var Year, Month, Day: WORD );\r
23991 var Dummy: Word;\r
23992 begin\r
23993   DecodeDateFully( DateTime, Year, Month, Day, Dummy );\r
23994 end;\r
23996 //[function EncodeDate]\r
23997 function EncodeDate( Year, Month, Day: WORD; var DateTime: TDateTime ): Boolean;\r
23998 var ST: TSystemTime;\r
23999 begin\r
24000   FillChar( ST, Sizeof( ST ), 0 );\r
24001   ST.wYear := Year;\r
24002   ST.wMonth := Month;\r
24003   ST.wDay := Day;\r
24004   Result := SystemTime2DateTime( ST, DateTime );\r
24005 end;\r
24007 //[FUNCTION CompareSystemTime]\r
24008 {$IFDEF ASM_VERSION}\r
24009 function CompareSystemTime( const D1, D2 : TSystemTime) : Integer; assembler;\r
24010 asm\r
24011         PUSH     ESI\r
24012         PUSH     EBX\r
24013         MOV      ESI, EAX\r
24014         XOR      EAX, EAX\r
24015         XOR      ECX, ECX\r
24016         MOV      CL, 8  // 8 words: wYear, wMonth,..., wMilliseconds\r
24017 @@loo:\r
24018         LODSW\r
24019         MOV      BX, [EDX]\r
24020         INC      EDX\r
24021         INC      EDX\r
24023         CMP      CL, 6\r
24024         JE       @@cont  // skip compare DayOfWeek\r
24026         SUB      AX, BX\r
24027         JNE      @@calc\r
24029 @@cont:\r
24030         LOOP     @@loo\r
24031         JMP      @@exit\r
24033 @@calc:\r
24034         SBB      EAX, EAX\r
24035         {$IFDEF PARANOIA}\r
24036         DB $0C, 1\r
24037         {$ELSE}\r
24038         OR       AL, 1\r
24039         {$ENDIF}\r
24041 @@exit:\r
24042         POP      EBX\r
24043         POP      ESI\r
24044 end;\r
24045 {$ELSE ASM_VERSION} //Pascal\r
24046 function CompareSystemTime(const D1, D2 : TSystemTime) : Integer;\r
24047 var R: Integer;\r
24048    procedure CompareFields(const F1, F2 : Integer);\r
24049    begin\r
24050       if R <> 0 then Exit;\r
24051       if F1 = F2 then Exit;\r
24052       if F1 < F2 then\r
24053          R := -1\r
24054       else\r
24055          R := 1;\r
24056    end;\r
24057 begin\r
24058    R := 0;\r
24059    CompareFields( D1.wYear, D2.wYear );\r
24060    CompareFields( D1.wMonth, D2.wMonth );\r
24061    CompareFields( D1.wDay, D2.wDay );\r
24062    CompareFields( D1.wHour, D2.wHour );\r
24063    CompareFields( D1.wMinute, D2.wMinute );\r
24064    CompareFields( D1.wSecond, D2.wSecond );\r
24065    CompareFields( D1.wMilliseconds, D2.wMilliseconds );\r
24066    Result := R;\r
24067 end;\r
24068 {$ENDIF ASM_VERSION}\r
24069 //[END CompareSystemTime]\r
24071 //*\r
24072 //[procedure IncDays]\r
24073 procedure IncDays( var SystemTime : TSystemTime; DaysNum : Integer );\r
24074 var DateTime : TDateTime;\r
24075 begin\r
24076    SystemTime2DateTime( SystemTime, DateTime );\r
24077    DateTime := DateTime + DaysNum;\r
24078    DateTime2SystemTime( DateTime, SystemTime );\r
24079 end;\r
24081 //*\r
24082 //[procedure IncMonths]\r
24083 procedure IncMonths( var SystemTime : TSystemTime; MonthsNum : Integer );\r
24084 var M : Integer;\r
24085     DateTime : TDateTime;\r
24086 begin\r
24087    M := SystemTime.wMonth + MonthsNum - 1;\r
24088    Inc( SystemTime.wYear, M div 12 );\r
24089    SystemTime.wMonth := M mod 12 + 1;\r
24091    // Normalize wDayOfWeek field:\r
24092    SystemTime2DateTime( SystemTime, DateTime );\r
24093    DateTime2SystemTime( DateTime, SystemTime );\r
24094 end;\r
24096 //*\r
24097 //[function IsLeapYear]\r
24098 function IsLeapYear(Year: Word): Boolean;\r
24099 begin\r
24100   Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));\r
24101 end;\r
24103 //*\r
24104 //[function SystemTime2DateTime]\r
24105 function SystemTime2DateTime(const SystemTime : TSystemTime; var DateTime : TDateTime ) : Boolean;\r
24106 var I : Integer;\r
24107     Day : Integer;\r
24108     DayTable: PDayTable;\r
24109 begin\r
24110   Result := False;\r
24111   DateTime := 0.0;\r
24112   DayTable := @MonthDays[IsLeapYear(SystemTime.wYear)];\r
24113   with SystemTime do\r
24114 //-------- by Vadim Petrov ----------------------------------------------------------------\r
24115 //if (wYear >= 1) and (wYear <= 9999) and (wMonth >= 1) and (wMonth <= 12) and\r
24116 //  (wDay >= 1) and (wDay <= DayTable^[wMonth]) and\r
24117 //  (wHour < 24) and (wMinute < 60) and (wSecond < 60) and (wMilliSeconds < 1000) then\r
24118 //---------------------------------------------------------------------------------------//\r
24119   if {(wYear >= 0) !always true! and} (wYear <= 9999) and\r
24120     {(wMonth >= 0) !always true! and} (wMonth <= 12) and\r
24121     {(wDay >= 0) !always true! and} (wDay <= DayTable^[wMonth]) and                                      //\r
24122     (wHour < 24) and (wMinute < 60) and (wSecond < 60) and (wMilliSeconds < 1000) then   //\r
24123 //---------------------------------------------------------------------------------------//\r
24124   begin\r
24125     Day := wDay;\r
24126     for I := 1 to wMonth - 1 do\r
24127         Inc(Day, DayTable^[I]);\r
24128     I := wYear - 1;\r
24129     //--------------- by Vadim Petrov ------++\r
24130     if I<0 then i := 0;                     //\r
24131     //--------------------------------------++\r
24132     DateTime := I * 365 + I div 4 - I div 100 + I div 400 + Day\r
24133              + (wHour * 3600000 + wMinute * 60000 + wSecond * 1000 + wMilliSeconds) / MSecsPerDay;\r
24134     Result := True;\r
24135   end;\r
24136 end;\r
24138 //*\r
24139 //[function DayOfWeek]\r
24140 function DayOfWeek(Date: TDateTime): Integer;\r
24141 begin\r
24142   Result := (Trunc( Date ) + 6) mod 7 + 1;\r
24143 end;\r
24145 //*\r
24146 //[function DateTime2SystemTime]\r
24147 function DateTime2SystemTime(const DateTime : TDateTime; var SystemTime : TSystemTime ) : Boolean;\r
24148 const\r
24149   D1 = 365;\r
24150   D4 = D1 * 4 + 1;\r
24151   D100 = D4 * 25 - 1;\r
24152   D400 = D100 * 4 + 1;\r
24153 var Days : Integer;\r
24154     Y, M, D, I: Word;\r
24155     MSec : Integer;\r
24156     DayTable: PDayTable;\r
24157     MinCount, MSecCount: Word;\r
24158 begin\r
24159   Days := Trunc( DateTime );\r
24160   MSec := Round((DateTime - Days) * MSecsPerDay);\r
24161   Result := False;\r
24162   with SystemTime do\r
24163   if Days > 0 then\r
24164   begin\r
24165     Dec(Days);\r
24166     Y := 1;\r
24167     while Days >= D400 do\r
24168     begin\r
24169       Dec(Days, D400);\r
24170       Inc(Y, 400);\r
24171     end;\r
24172     DivMod(Days, D100, I, D);\r
24173     if I = 4 then\r
24174     begin\r
24175       Dec(I);\r
24176       Inc(D, D100);\r
24177     end;\r
24178     Inc(Y, I * 100);\r
24179     DivMod(D, D4, I, D);\r
24180     Inc(Y, I * 4);\r
24181     DivMod(D, D1, I, D);\r
24182     if I = 4 then\r
24183     begin\r
24184       Dec(I);\r
24185       Inc(D, D1);\r
24186     end;\r
24187     Inc(Y, I);\r
24188     DayTable := @MonthDays[IsLeapYear(Y)];\r
24189     M := 1;\r
24190     while True do\r
24191     begin\r
24192       I := DayTable^[M];\r
24193       if D < I then Break;\r
24194       Dec(D, I);\r
24195       Inc(M);\r
24196     end;\r
24197     wYear := Y;\r
24198     wMonth := M;\r
24199     wDay := D + 1;\r
24200     wDayOfWeek := DayOfWeek( DateTime );\r
24201     DivMod(MSec, 60000, MinCount, MSecCount);\r
24202     DivMod(MinCount, 60, wHour, wMinute);\r
24203     DivMod(MSecCount, 1000, wSecond, wMilliSeconds);\r
24204     Result := True;\r
24205   end;\r
24206 end;\r
24208 function DateTime_DiffSysLoc: TDateTime;\r
24209 var ST, LT: TSystemTime;\r
24210     FT, FT1: TFileTime;\r
24211     D1, D2: TDateTime;\r
24212 begin\r
24213   GetSystemTime( ST );\r
24214   SystemTimeToFileTime( ST, FT );\r
24215   FileTimeToLocalFileTime( FT, FT1 );\r
24216   FileTimeToSystemTime( FT1, LT );\r
24217   SystemTime2DateTime( ST, D1 );\r
24218   SystemTime2DateTime( LT, D2 );\r
24219   Result := D2 - D1;\r
24220 end;\r
24222 //[function DateTime_System2Local]\r
24223 function DateTime_System2Local( DTSys: TDateTime ): TDateTime;\r
24224 begin\r
24225   Result := DTSys + DateTime_DiffSysLoc;\r
24226 end;\r
24228 //[function DateTime_Local2System]\r
24229 function DateTime_Local2System( DTLoc: TDateTime ): TDateTime;\r
24230 begin\r
24231   Result := DTLoc - DateTime_DiffSysLoc;\r
24232 end;\r
24234 //*\r
24235 //[function CatholicEaster]\r
24236 function CatholicEaster( nYear: Integer ): TDateTime;\r
24237 var\r
24238    nMoon, nEpact, nSunday, nGold, nCent, nCorx, nCorz: Integer;\r
24239    SystemTime : TSystemTime;\r
24240 begin\r
24241    FillChar( SystemTime, Sizeof( SystemTime ), 0 );\r
24242    with SystemTime do\r
24243    begin\r
24245     wYear := nYear;\r
24247     { The Golden Number of the year in the 19 year Metonic Cycle }\r
24248     nGold := ( ( wYear mod 19 ) + 1  );\r
24250     { Calculate the Century }\r
24251     nCent := ( ( wYear div 100 ) + 1 );\r
24253     { No. of Years in which leap year was dropped in order to keep in step\r
24254       with the sun }\r
24255     nCorx := ( ( 3 * nCent ) div 4 - 12 );\r
24257     { Special Correction to Syncronize Easter with the moon's orbit }\r
24258     nCorz := ( ( 8 * nCent + 5 ) div 25 - 5 );\r
24260     { Find Sunday }\r
24261     nSunday := ( ( 5 * wYear ) div 4 - nCorx - 10 );\r
24263     { Set Epact (specifies occurance of full moon }\r
24264     nEpact := ( ( 11 * nGold + 20 + nCorz - nCorx ) mod 30 );\r
24266     if ( nEpact < 0 ) then\r
24267        nEpact := nEpact + 30;\r
24269     if ( ( nEpact = 25 ) and ( nGold > 11 ) ) or ( nEpact = 24 ) then\r
24270        nEpact := nEpact + 1;\r
24272     { Find Full Moon }\r
24273     nMoon := 44 - nEpact;\r
24275     if ( nMoon < 21 ) then\r
24276        nMoon := nMoon + 30;\r
24278     { Advance to Sunday }\r
24279     nMoon := ( nMoon + 7 - ( ( nSunday + nMoon ) mod 7 ) );\r
24281     if ( nMoon > 31 ) then\r
24282        begin\r
24283          wMonth := 4;\r
24284          wDay   := ( nMoon - 31 );\r
24285        end\r
24286     else\r
24287        begin\r
24288          wMonth := 3;\r
24289          wDay   := nMoon;\r
24290        end;\r
24291    end;\r
24292    SystemTime2DateTime( SystemTime, Result );\r
24293 end;\r
24295 //*\r
24296 //[function SystemDate2Str]\r
24297 function SystemDate2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;\r
24298                          const DfltDateFormat : TDateFormat; const DateFormat : PChar ) : String;\r
24299 var Buf : PChar;\r
24300     Sz : Integer;\r
24301     Flags : DWORD;\r
24302 begin\r
24303    Sz := 100;\r
24304    Buf := nil;\r
24305    Result := '';\r
24306    Flags := 0;\r
24307    if DateFormat = nil then\r
24308    if DfltDateFormat = dfShortDate then\r
24309       Flags := DATE_SHORTDATE\r
24310    else\r
24311       Flags := DATE_LONGDATE;\r
24312    while True do\r
24313    begin\r
24314       if Buf <> nil then\r
24315          FreeMem( Buf );\r
24316       GetMem( Buf, Sz );\r
24317       if Buf = nil then Exit;\r
24318       if GetDateFormat( LocaleID, Flags, @SystemTime, DateFormat, Buf, Sz )\r
24319          = 0 then\r
24320       begin\r
24321          if GetLastError = ERROR_INSUFFICIENT_BUFFER then\r
24322             Sz := Sz * 2\r
24323          else\r
24324             break;\r
24325       end\r
24326          else\r
24327       begin\r
24328          Result := Buf;\r
24329          break;\r
24330       end;\r
24331    end;\r
24332    if Buf <> nil then\r
24333       FreeMem( Buf );\r
24334 end;\r
24336 //*\r
24337 //[function SystemTime2Str]\r
24338 function SystemTime2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;\r
24339                          const Flags : TTimeFormatFlags; const TimeFormat : PChar ) : String;\r
24340 var Buf : PChar;\r
24341     Sz : Integer;\r
24342     Flg : DWORD;\r
24343 begin\r
24344    Sz := 100;\r
24345    Buf := nil;\r
24346    Result := '';\r
24347    Flg := 0;\r
24348    if tffNoMinutes in Flags then\r
24349       Flg := TIME_NOMINUTESORSECONDS\r
24350    else\r
24351    if tffNoSeconds in Flags then\r
24352       Flg := TIME_NOSECONDS;\r
24353    if tffNoMarker in Flags then\r
24354       Flg := Flg or TIME_NOTIMEMARKER;\r
24355    if tffForce24 in Flags then\r
24356       Flg := Flg or TIME_FORCE24HOURFORMAT;\r
24357    while True do\r
24358    begin\r
24359       if Buf <> nil then\r
24360          FreeMem( Buf );\r
24361       GetMem( Buf, Sz );\r
24362       if Buf = nil then Exit;\r
24363       if GetTimeFormat( LocaleID, Flg, @SystemTime, TimeFormat, Buf, Sz )\r
24364          = 0 then\r
24365       begin\r
24366          if GetLastError = ERROR_INSUFFICIENT_BUFFER then\r
24367             Sz := Sz * 2\r
24368          else\r
24369             break;\r
24370       end\r
24371          else\r
24372       begin\r
24373          Result := Buf;\r
24374          break;\r
24375       end;\r
24376    end;\r
24377    if Buf <> nil then\r
24378       FreeMem( Buf );\r
24379 end;\r
24381 //[function Date2StrFmt]\r
24382 function Date2StrFmt( const Fmt: String; D: TDateTime ): String;\r
24383 var ST: TSystemTime;\r
24384     lpFmt: PChar;\r
24385 begin\r
24386   DateTime2SystemTime( D, ST );\r
24387   lpFmt := nil;\r
24388   if Fmt <> '' then lpFmt := PChar( Fmt );\r
24389   Result := SystemDate2Str( ST, LOCALE_USER_DEFAULT, dfShortDate, lpFmt );\r
24390 end;\r
24392 //[function Time2StrFmt]\r
24393 function Time2StrFmt( const Fmt: String; D: TDateTime ): String;\r
24394 var ST: TSystemTime;\r
24395     lpFmt: PChar;\r
24396 begin\r
24397   if D < 1 then D := D + 1;\r
24398   DateTime2SystemTime( D, ST );\r
24399   lpFmt := nil;\r
24400   if Fmt <> '' then lpFmt := PChar( Fmt );\r
24401   Result := SystemTime2Str( ST, LOCALE_USER_DEFAULT, [], lpFmt );\r
24402 end;\r
24404 //[function DateTime2StrShort]\r
24405 function DateTime2StrShort( D: TDateTime ): String;\r
24406 var ST: TSystemTime;\r
24407 begin\r
24408   //--------- by Vadim Petrov --------++\r
24409   if D < 1 then D := D + 1;           //\r
24410   //----------------------------------++\r
24411   DateTime2SystemTime( D, ST );\r
24412   Result := SystemDate2Str( ST, LOCALE_USER_DEFAULT {GetUserDefaultLCID}, dfShortDate, nil ) + ' ' +\r
24413             SystemTime2Str( ST, LOCALE_USER_DEFAULT {GetUserDefaultLCID}, [], nil );\r
24414 end;\r
24416 //[function Str2DateTimeFmt]\r
24417 function Str2DateTimeFmt( const sFmtStr, sS: String ): TDateTime;\r
24418 var h12, hAM: Boolean;\r
24419     FmtStr, S: PChar;\r
24421   function GetNum( var S: PChar; NChars: Integer ): Integer;\r
24422   begin\r
24423     Result := 0;\r
24424     while (S^ <> #0) and (NChars <> 0) do\r
24425     begin\r
24426       Dec( NChars );\r
24427       if S^ in ['0'..'9'] then\r
24428       begin\r
24429         Result := Result * 10 + Ord(S^) - Ord('0');\r
24430         Inc( S );\r
24431       end\r
24432       else\r
24433         break;\r
24434     end;\r
24435   end;\r
24437   function GetYear( var S: PChar; NChars: Integer ): Integer;\r
24438   var STNow: TSystemTime;\r
24439       OldDate: Boolean;\r
24440   begin\r
24441     Result := GetNum( S, NChars );\r
24442     GetSystemTime( STNow );\r
24443     OldDate := Result < 50;\r
24444     Result := Result + STNow.wYear - STNow.wYear mod 100;\r
24445     if OldDate then Dec( Result, 100 );\r
24446   end;\r
24448   function GetMonth( const fmt: String; var S: PChar ): Integer;\r
24449   var SD: TSystemTime;\r
24450       M: Integer;\r
24451       C, MonthStr: String;\r
24452   begin\r
24453     GetSystemTime( SD );\r
24454     for M := 1 to 12 do\r
24455     begin\r
24456       SD.wMonth := M;\r
24457       C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/dd/yyyy/' ) );\r
24458       MonthStr := Parse( C, '/' );\r
24459       if AnsiCompareStrNoCase( MonthStr, Copy( S, 1, Length( MonthStr ) ) ) = 0 then\r
24460       begin\r
24461         Result := M;\r
24462         Inc( S, Length( MonthStr ) );\r
24463         Exit;\r
24464       end;\r
24465     end;\r
24466     Result := 1;\r
24467   end;\r
24469   procedure SkipDayOfWeek( const fmt: String; var S: PChar );\r
24470   var SD: TSystemTime;\r
24471       Dt: TDateTime;\r
24472       D: Integer;\r
24473       C, DayWeekStr: String;\r
24474   begin\r
24475     GetSystemTime( SD );\r
24476     SystemTime2DateTime( SD, Dt );\r
24477     Dt := Dt - SD.wDayOfWeek;\r
24478     for D := 0 to 6 do\r
24479     begin\r
24480       DateTime2SystemTime( Dt, SD );\r
24481       C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/MM/yyyy/' ) );\r
24482       DayWeekStr := Parse( C, '/' );\r
24483       if AnsiCompareStrNoCase( DayWeekStr, Copy( S, 1, Length( DayWeekStr ) ) ) = 0 then\r
24484       begin\r
24485         Inc( S, Length( DayWeekStr ) );\r
24486         Exit;\r
24487       end;\r
24488       Dt := Dt + 1.0;\r
24489     end;\r
24490   end;\r
24492   procedure GetTimeMark( const fmt: String; var S: PChar );\r
24493   var SD: TSystemTime;\r
24494       AM: Boolean;\r
24495       C, TimeMarkStr: String;\r
24496   begin\r
24497     GetSystemTime( SD );\r
24498     SD.wHour := 0;\r
24499     for AM := FALSE to TRUE do\r
24500     begin\r
24501       C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/HH/mm' ) );\r
24502       TimeMarkStr := Parse( C, '/' );\r
24503       if AnsiCompareStrNoCase( TimeMarkStr, Copy( S, 1, Length( TimeMarkStr ) ) ) = 0 then\r
24504       begin\r
24505         Inc( S, Length( TimeMarkStr ) );\r
24506         hAM := AM;\r
24507         Exit;\r
24508       end;\r
24509       SD.wHour := 13;\r
24510     end;\r
24511     Result := 1;\r
24512   end;\r
24514   function FmtIs1( S: PChar ): Boolean;\r
24515   begin\r
24516     if StrIsStartingFrom( FmtStr, S ) then\r
24517     begin\r
24518       Inc( FmtStr, StrLen( S ) );\r
24519       Result := TRUE;\r
24520     end\r
24521       else\r
24522       Result := FALSE;\r
24523   end;\r
24525   function FmtIs( S1, S2: PChar ): Boolean;\r
24526   begin\r
24527     Result := FmtIs1( S1 ) or FmtIs1( S2 );\r
24528   end;\r
24530 var ST: TSystemTime;\r
24531 begin\r
24532   FmtStr := PChar( sFmtStr);\r
24533   S := PChar( sS );\r
24534   FillChar( ST, Sizeof( ST ), 0 );\r
24535   h12 := FALSE;\r
24536   hAM := FALSE;\r
24537   while (FmtStr^ <> #0) and (S^ <> #0) do\r
24538   begin\r
24539     if (FmtStr^ in ['a'..'z','A'..'Z']) and (S^ in ['0'..'9']) then\r
24540     begin\r
24541       if      FmtIs1( 'yyyy'   ) then ST.wYear := GetNum( S, 4 )\r
24542       else if FmtIs1( 'yy' )     then ST.wYear := GetYear( S, 2 )\r
24543       else if FmtIs1( 'y' )      then ST.wYear := GetYear( S, -1 )\r
24544       else if FmtIs( 'dd', 'd' ) then ST.wDay := GetNum( S, 2 )\r
24545       else if FmtIs( 'MM', 'M' ) then ST.wMonth := GetNum( S, 2 )\r
24546       else if FmtIs( 'HH', 'H' ) then ST.wHour := GetNum( S, 2 )\r
24547       else if FmtIs( 'hh', 'h' ) then begin ST.wHour := GetNum( S, 2 ); h12 := TRUE end\r
24548       else if FmtIs( 'mm', 'm' ) then ST.wMinute := GetNum( S, 2 )\r
24549       else if FmtIs( 'ss', 's' ) then ST.wSecond := GetNum( S, 2 )\r
24550       else break; // + ECM\r
24551     end\r
24552       else\r
24553     if (FmtStr^ in [ 'M', 'd', 'g' ]) then\r
24554     begin\r
24555       if      FmtIs1( 'MMMM' ) then ST.wMonth := GetMonth( 'MMMM', S )\r
24556       else if FmtIs1( 'MMM'  ) then ST.wMonth := GetMonth( 'MMM', S )\r
24557       else if FmtIs1( 'dddd' ) then SkipDayOfWeek( 'dddd', S )\r
24558       else if FmtIs1( 'ddd'  ) then SkipDayOfWeek( 'ddd', S )\r
24559       else if FmtIs1( 'tt'   ) then GetTimeMark( 'tt', S )\r
24560       else if FmtIs1( 't'    ) then GetTimeMark( 't', S )\r
24561       else break; // + ECM\r
24562     end\r
24563       else\r
24564     begin\r
24565       if FmtStr^ = S^ then\r
24566         Inc( FmtStr );\r
24567       Inc( S );\r
24568     end;\r
24569   end;\r
24571   if h12 then\r
24572   if hAM then\r
24573     Inc( ST.wHour, 12 );\r
24575   SystemTime2DateTime( ST, Result );\r
24576 end;\r
24578 var FmtBuf: PChar;\r
24579     DateSeparator : Char = #0; // + ECM\r
24581 //[function Str2DateTimeShort]\r
24582 function Str2DateTimeShort( const S: String ): TDateTime;\r
24583 var FmtStr, FmtStr2: String;\r
24585   function EnumDateFmt( lpstrFmt: PChar ): Boolean; stdcall;\r
24586   begin\r
24587     GetMem( FmtBuf, StrLen( lpstrFmt ) + 1 );\r
24588     StrCopy( FmtBuf, lpstrFmt );\r
24589     Result := FALSE;\r
24590   end;\r
24592 begin\r
24593   FmtStr := 'dd.MM.yyyy';\r
24594   FmtBuf := nil;\r
24595   EnumDateFormats( @ EnumDateFmt, LOCALE_USER_DEFAULT, DATE_SHORTDATE );\r
24596   if FmtBuf <> nil then\r
24597   begin\r
24598     FmtStr := FmtBuf;\r
24599     FreeMem( FmtBuf );\r
24600   end;\r
24602   FmtStr2 := 'H:mm:ss';\r
24603   FmtBuf := nil;\r
24604   EnumTimeFormats( @ EnumDateFmt, LOCALE_USER_DEFAULT, 0 );\r
24605   if FmtBuf <> nil then\r
24606   begin\r
24607     FmtStr2 := FmtBuf;\r
24608     FreeMem( FmtBuf );\r
24609   end;\r
24611   Result := Str2DateTimeFmt( FmtStr + ' ' + FmtStr2, S );\r
24612 end;\r
24614 // + ECM\r
24615 //[function Str2DateTimeShortEx]\r
24616 function Str2DateTimeShortEx( const S: String ): TDateTime;\r
24617 var St: String;\r
24618   Buff: Array[0..1] of Char;\r
24619 begin\r
24620   if DateSeparator = #0 then\r
24621   begin\r
24622     if GetLocaleInfo(GetThreadLocale,LOCALE_SDATE,Buff,2) > 0 then\r
24623       DateSeparator := Buff[0];\r
24624   end;\r
24625   St := S;\r
24626   if Pos(DateSeparator,S) = 0 then\r
24627     St := '0.0.0 '+S;\r
24628   Result := Str2DateTimeShort(St);\r
24629 end;\r
24648 ///////////////////////////////////////////////////////////////////////\r
24649 //\r
24650 //\r
24651 //                          T  H  R  E  A  D  S\r
24652 //\r
24653 //\r
24654 ///////////////////////////////////////////////////////////////////////\r
24663 { -- Thread -- }\r
24665 //[function ThreadFunc]\r
24666 function ThreadFunc(Thread: PThread): integer; stdcall;\r
24667 begin\r
24668   Result := Thread.Execute;\r
24669 end;\r
24671 {$IFDEF USE_CONSTRUCTORS}\r
24672 //[function NewThread]\r
24673 function NewThread: PThread;\r
24674 begin\r
24675   new( Result, ThreadCreate );\r
24676 end;\r
24677 //[END NewThread]\r
24678 {$ELSE not_USE_CONSTRUCTORS}\r
24679 //*\r
24680 //[function NewThread]\r
24681 function NewThread: PThread;\r
24682 begin\r
24683   {$IFNDEF FPC105ORBELOW}\r
24684   IsMultiThread := True;\r
24685   {$ENDIF}\r
24686   {-}\r
24687   New( Result, Create );\r
24688   {+}\r
24689   {++}(*Result := PThread.Create;*){--}\r
24690   Result.FSuspended := True;\r
24691   Result.FHandle := CreateThread( nil, // no security\r
24692                                   0,   // the same stack size\r
24693                                   @ThreadFunc, // thread entry point\r
24694                                   Result,      // parameter to pass to ThreadFunc\r
24695                                   CREATE_SUSPENDED,   // always SUSPENDED\r
24696                                   Result.FThreadID ); // receive thread ID\r
24697 end;\r
24698 //[END NewThread]\r
24699 {$ENDIF USE_CONSTRUCTORS}\r
24701 {$IFDEF USE_CONSTRUCTORS}\r
24702 //[function NewThreadEx]\r
24703 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;\r
24704 begin\r
24705   new( Result, ThreadCreateEx( Proc ) );\r
24706 end;\r
24707 {$ELSE not_USE_CONSTRUCTORS}\r
24709 //[FUNCTION NewThreadEx]\r
24710 {$IFDEF ASM_VERSION}\r
24711 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;\r
24712 asm\r
24713         CALL     NewThread\r
24714         POP      EBP\r
24715         POP      ECX\r
24716         POP      EDX\r
24717         MOV      [EAX].TThread.fOnExecute.TMethod.Code, EDX\r
24718         POP      EDX\r
24719         MOV      [EAX].TThread.fOnExecute.TMethod.Data, EDX\r
24720         PUSH     ECX\r
24721         PUSH     EAX\r
24722         CALL     TThread.Resume\r
24723         POP      EAX\r
24724         RET\r
24725 end;\r
24726 {$ELSE ASM_VERSION} //Pascal\r
24727 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;\r
24728 begin\r
24729   Result := NewThread;\r
24730   Result.OnExecute := {++}(*{$IFDEF F_P} @ {$ENDIF}*){--}Proc;\r
24731   Result.Resume;\r
24732 end;\r
24733 {$ENDIF ASM_VERSION}\r
24734 //[END NewThreadEx]\r
24736 {$ENDIF USE_CONSTRUCTORS}\r
24738 //[function NewThreadAutoFree]\r
24739 function NewThreadAutoFree( const Proc: TOnThreadExecute ): PThread;\r
24740 begin\r
24741   Result := NewThread;\r
24742   Result.OnExecute := {++}(*{$IFDEF F_P} @ {$ENDIF}*){--}Proc;\r
24743   Result.F_AutoFree := TRUE;\r
24744   if Assigned( Proc ) then\r
24745     Result.Resume;\r
24746 end;\r
24748 { TThread }\r
24750 {$IFDEF ASM_VERSION}\r
24751 //[destructor TThread.Destroy]\r
24752 destructor TThread.Destroy;\r
24753 asm\r
24754         PUSH     EBX\r
24755         MOV      EBX, EAX\r
24756         CMP      [EAX].FTerminated, 0\r
24757         JNZ      @@1\r
24758         CALL     Terminate\r
24759         MOV      EAX, EBX\r
24760         CALL     WaitFor\r
24761 @@1:    MOV      ECX, [EBX].FHandle\r
24762         JECXZ    @@2\r
24763         PUSH     ECX\r
24764         CALL     CloseHandle\r
24765 @@2:    POP      EAX\r
24766         XCHG     EBX, EAX\r
24767         JMP      TObj.Destroy\r
24768 end;\r
24769 {$ELSE ASM_VERSION} //Pascal\r
24770 destructor TThread.Destroy;\r
24771 begin\r
24772   if not FTerminated then\r
24773   begin\r
24774     Terminate;\r
24775     WaitFor;\r
24776   end;\r
24777   if (FHandle <> 0) then\r
24778     CloseHandle(FHandle);\r
24779   inherited;\r
24780 end;\r
24781 {$ENDIF ASM_VERSION}\r
24783 //*\r
24784 //[function TThread.Execute]\r
24785 function TThread.Execute: integer;\r
24786 begin\r
24787   Result := 0;\r
24788   if Assigned( FOnExecute ) then\r
24789      Result := FOnExecute( @Self );\r
24790   if F_AutoFree then\r
24791   begin\r
24792     FTerminated := TRUE; // fake thread object (to prevent terminating while freeing)\r
24793     Free;\r
24794   end;\r
24795 end;\r
24797 //*\r
24798 //[function TThread.GetPriorityCls]\r
24799 function TThread.GetPriorityCls: Integer;\r
24800 begin\r
24801   Result := GetPriorityClass(FHandle);\r
24802 end;\r
24804 //*\r
24805 //[function TThread.GetThrdPriority]\r
24806 function TThread.GetThrdPriority: Integer;\r
24807 begin\r
24808   Result := GetThreadPriority(FHandle);\r
24809 end;\r
24811 //*\r
24812 //[procedure TThread.Resume]\r
24813 procedure TThread.Resume;\r
24814 begin\r
24815   FSuspended := False;\r
24816   if (ResumeThread(FHandle) > 1) then\r
24817     FSuspended := True\r
24818   else\r
24819   if Assigned(FOnResume) then\r
24820     FOnResume(@Self);\r
24821 end;\r
24823 //*\r
24824 //[procedure TThread.SetPriorityCls]\r
24825 procedure TThread.SetPriorityCls(Value: Integer);\r
24826 begin\r
24827   {$IFDEF DEBUG}\r
24828   if not SetPriorityClass(GetCurrentProcess, Value) then\r
24829   begin\r
24830     ShowMessage( SysErrorMessage( GetLastError ) );\r
24831   end;\r
24832   {$ELSE}\r
24833   SetPriorityClass(GetCurrentProcess, Value);\r
24834   {$ENDIF}\r
24835 end;\r
24837 //*\r
24838 //[procedure TThread.SetThrdPriority]\r
24839 procedure TThread.SetThrdPriority(Value: Integer);\r
24840 begin\r
24841   SetThreadPriority(FHandle, Value);\r
24842 end;\r
24844 //*\r
24845 //[procedure TThread.Suspend]\r
24846 procedure TThread.Suspend;\r
24847 begin\r
24848   FSuspended := TRUE;\r
24849   if Assigned(FOnSuspend) then\r
24850     Synchronize( FOnSuspend );\r
24851   SuspendThread(FHandle);\r
24852 end;\r
24854 //*\r
24855 //[procedure CallSynchronized]\r
24856 procedure CallSynchronized( Sender: PObj; Param: Pointer );\r
24857 var Thread: PThread;\r
24858 begin\r
24859   Thread := PThread( Sender );\r
24860   if Param <> nil then\r
24861     Thread.FMethodEx( Thread, Param )\r
24862   else\r
24863     Thread.FMethod( );\r
24864 end;\r
24866 //*\r
24867 //[procedure TThread.Synchronize]\r
24868 procedure TThread.Synchronize(Method: TThreadMethod);\r
24869 begin\r
24870   Global_Synchronized := CallSynchronized;\r
24871   FMethod := Method;\r
24872   if Applet <> nil then\r
24873     SendMessage( Applet.fHandle, CM_EXECPROC, 0, Integer( @Self ) );\r
24874 end;\r
24876 //[procedure TThread.SynchronizeEx]\r
24877 procedure TThread.SynchronizeEx( Method: TThreadMethodEx; Param: Pointer );\r
24878 begin\r
24879   Assert( Param <> nil, 'Parameter must not be NIL' );\r
24880   Global_Synchronized := CallSynchronized;\r
24881   FMethodEx := Method;\r
24882   SendMessage( Applet.fHandle, CM_EXECPROC, Integer( Param ), Integer( @Self ) );\r
24883 end;\r
24885 //*\r
24886 //[procedure TThread.Terminate]\r
24887 procedure TThread.Terminate;\r
24888 begin\r
24889   TerminateThread(FHandle,0);\r
24890   FTerminated := True;\r
24891 end;\r
24893 //*\r
24894 //[function TThread.WaitFor]\r
24895 function TThread.WaitFor: Integer;\r
24896 begin\r
24897   RefInc;\r
24898   Result := -1;\r
24899   if FHandle = 0 then Exit;\r
24900   WaitForSingleObject(FHandle, INFINITE);\r
24901   GetExitCodeThread(FHandle, DWORD(Result));\r
24902   RefDec;\r
24903 end;\r
24907 { TStream }\r
24909 {* This part of the unit contains implementation of streams for KOL. Please note,\r
24910    that both stream types (file stream and memory stream) are incapsulated\r
24911    by a single object type TStream. To avoid including unnedeed code,\r
24912    use constructing functions NewReadFileStream and NewWriteFileStream\r
24913    to work with file streams, which do not require both types of operation. }\r
24915 {* To create new type of stream, define your own methods, and in your\r
24916    constructing function, pass it to _NewStream function (through\r
24917    TStreamMethods record). In a field Custom, You can store a reference to\r
24918    your own data of any type (but do not forget to define correct releasing\r
24919    of such data in your fClose procedure). }\r
24921 //[function TStream.GetPosition]\r
24922 function TStream.GetPosition: DWord;\r
24923 begin\r
24924   Result := Seek( 0, spCurrent );\r
24925 end;\r
24927 //[procedure TStream.SetPosition]\r
24928 procedure TStream.SetPosition(Value: DWord);\r
24929 begin\r
24930   Seek( Value, spBegin );\r
24931 end;\r
24933 {$IFDEF ASM_VERSION}\r
24934 //[function TStream.GetSize]\r
24935 function TStream.GetSize: DWord;\r
24936 asm\r
24937         CALL     [EAX].fMethods.fGetSiz\r
24938 end;\r
24939 {$ELSE ASM_VERSION} //Pascal\r
24940 function TStream.GetSize: DWord;\r
24941 begin\r
24942   Result := fMethods.fGetSiz( @Self );\r
24943 end;\r
24944 {$ENDIF ASM_VERSION}\r
24946 {$IFDEF ASM_VERSION}\r
24947 //[procedure TStream.SetSize]\r
24948 procedure TStream.SetSize(NewSize: DWord);\r
24949 asm\r
24950         CALL     [EAX].fMethods.fSetSiz\r
24951 end;\r
24952 {$ELSE ASM_VERSION} //Pascal\r
24953 procedure TStream.SetSize(NewSize: DWord);\r
24954 begin\r
24955   fMethods.fSetSiz( @Self, NewSize );\r
24956 end;\r
24957 {$ENDIF ASM_VERSION}\r
24959 //[function TStream.GetFileStreamHandle]\r
24960 function TStream.GetFileStreamHandle: THandle;\r
24961 begin\r
24962   Result := fData.fHandle;\r
24963 end;\r
24965 {$IFDEF ASM_VERSION}\r
24966 //[function TStream.Read]\r
24967 function TStream.Read(var Buffer; Count: DWord): DWord;\r
24968 asm\r
24969         CALL     [EAX].fMethods.fRead\r
24970 end;\r
24971 {$ELSE ASM_VERSION} //Pascal\r
24972 function TStream.Read(var Buffer; Count: DWord): DWord;\r
24973 begin\r
24974   Result := fMethods.fRead( @Self, Buffer, Count );\r
24975 end;\r
24976 {$ENDIF ASM_VERSION}\r
24978 //[function TStream.GetCapacity]\r
24979 function TStream.GetCapacity: DWORD;\r
24980 begin\r
24981   Result := fData.fCapacity;\r
24982 end;\r
24984 //[procedure TStream.SetCapacity]\r
24985 procedure TStream.SetCapacity(const Value: DWORD);\r
24986 var OldSize: DWORD;\r
24987 begin\r
24988   if fData.fCapacity >= Value then Exit;\r
24989   OldSize := Size;\r
24990   Size := Value;\r
24991   Size := OldSize;\r
24992 end;\r
24994 //[function TStream.Busy]\r
24995 function TStream.Busy: Boolean;\r
24996 begin\r
24997   Result := Assigned( fData.fThread );\r
24998 end;\r
25000 //[function TStream.DoAsyncRead]\r
25001 function TStream.DoAsyncRead( Sender: PThread ): Integer;\r
25002 begin\r
25003   Read( Pointer( fParam1 )^, fParam2 );\r
25004   fData.fThread := nil;\r
25005   Result := 0;\r
25006 end;\r
25008 //[procedure TStream.ReadAsync]\r
25009 procedure TStream.ReadAsync(var Buffer; Count: DWord);\r
25010 begin\r
25011   if Busy then Wait;\r
25012   fData.fThread := NewThreadAutoFree( nil );\r
25013   fData.fThread.OnExecute := DoAsyncRead;\r
25014   fParam1 := DWORD( @ Buffer );\r
25015   fParam2 := Count;\r
25016   fData.fThread.Resume;\r
25017 end;\r
25019 //[function TStream.DoAsyncSeek]\r
25020 function TStream.DoAsyncSeek( Sender: PThread ): Integer;\r
25021 begin\r
25022   Seek( fParam1, TMoveMethod( fParam2 ) );\r
25023   fData.fThread := nil;\r
25024   Result := 0;\r
25025 end;\r
25027 //[procedure TStream.SeekAsync]\r
25028 procedure TStream.SeekAsync(MoveTo: Integer; MoveMethod: TMoveMethod);\r
25029 begin\r
25030   if Busy then Wait;\r
25031   fData.fThread := NewThreadAutoFree( nil );\r
25032   fData.fThread.OnExecute := DoAsyncSeek;\r
25033   fParam1 := MoveTo;\r
25034   fParam2 := Ord( MoveMethod );\r
25035   fData.fThread.Resume;\r
25036 end;\r
25038 //[function TStream.DoAsyncWrite]\r
25039 function TStream.DoAsyncWrite( Sender: PThread ): Integer;\r
25040 begin\r
25041   Write( Pointer( fParam1 )^, fParam2 );\r
25042   fData.fThread := nil;\r
25043   Result := 0;\r
25044 end;\r
25046 //[procedure TStream.WriteAsync]\r
25047 procedure TStream.WriteAsync(var Buffer; Count: DWord);\r
25048 begin\r
25049   if Busy then Wait;\r
25050   fData.fThread := NewThreadAutoFree( nil );\r
25051   fData.fThread.OnExecute := DoAsyncWrite;\r
25052   fParam1 := DWORD( @ Buffer );\r
25053   fParam2 := Count;\r
25054   fData.fThread.Resume;\r
25055 end;\r
25057 //[procedure TStream.Wait]\r
25058 procedure TStream.Wait;\r
25059 begin\r
25060   if not Assigned( fData.fThread ) then Exit;\r
25061   if Assigned( fMethods.fWait ) then\r
25062     fMethods.fWait( @Self )\r
25063   else\r
25064     fData.fThread.WaitFor;\r
25065 end;\r
25067 {$IFDEF ASM_VERSION}\r
25068 //[function TStream.Write]\r
25069 function TStream.Write(var Buffer; Count: DWord): DWord;\r
25070 asm\r
25071         CALL     [EAX].fMethods.fWrite\r
25072 end;\r
25073 {$ELSE ASM_VERSION} //Pascal\r
25074 function TStream.Write(var Buffer; Count: DWord): DWord;\r
25075 begin\r
25076   Result := fMethods.fWrite( @Self, Buffer, Count );\r
25077 end;\r
25078 {$ENDIF ASM_VERSION}\r
25080 //[function TStream.WriteStr]\r
25081 function TStream.WriteStr(S: String): DWORD;\r
25082 begin\r
25083   if S <> '' then\r
25084     Result := fMethods.fWrite( @Self, S[1], Length( S ) )\r
25085   else\r
25086     Result := 0;\r
25087 end;\r
25089 //[function TStream.ReadStrZ]\r
25090 function TStream.ReadStrZ: String;\r
25091 var C: Char;\r
25092 begin\r
25093   Result := '';\r
25094   REPEAT\r
25095     C := #0;\r
25096     Read( C, 1 );\r
25097     if C <> #0 then Result := Result + C;\r
25098   UNTIL C = #0;\r
25099 end;\r
25101 //[function TStream.ReadStr]\r
25102 function TStream.ReadStr: String;\r
25103 var C: Char;\r
25104 begin\r
25105   Result := '';\r
25106   REPEAT\r
25107     C := #0;\r
25108     Read( C, 1 );\r
25109     if C <> #0 then\r
25110     begin\r
25111       if C = #13 then\r
25112       begin\r
25113         C := #0;\r
25114         Read( C, 1 );\r
25115         if C <> #10 then Position := Position - 1;\r
25116         C := #13;\r
25117       end\r
25118         else\r
25119       if C = #10 then\r
25120         C := #13;\r
25121       if C <> #13 then\r
25122         Result := Result + C;\r
25123     end;\r
25124   UNTIL C in [ #13, #0 ];\r
25125 end;\r
25127 //[function TStream.WriteStrZ]\r
25128 function TStream.WriteStrZ(S: String): DWORD;\r
25129 var C: Char;\r
25130 begin\r
25131   if S = '' then\r
25132     begin\r
25133       C := #0;\r
25134       Result := Write( C, 1 );\r
25135     end\r
25136   else\r
25137     Result := Write( S[ 1 ], Length( S ) + 1 );\r
25138 end;\r
25140 //[function TStream.WriteStrEx]\r
25141 function TStream.WriteStrEx(S: String): DWord;\r
25142 begin\r
25143   result:=length(s);\r
25144   fmethods.fwrite(@self,result,Sizeof(DWORD));\r
25145   if result<>0 then result:=fmethods.fwrite(@self,s[1],result);\r
25146 end;\r
25148 //[function TStream.ReadStrExVar]\r
25149 function TStream.ReadStrExVar(var S: String): DWord;\r
25150 begin\r
25151   fmethods.fread(@self,result,Sizeof(DWORD));\r
25152   setlength(s,result);\r
25153   if result<>0 then result:=fmethods.fread(@self,s[1],result);\r
25154 end;\r
25156 //[function TStream.ReadStrEx]\r
25157 function TStream.ReadStrEx: String;\r
25158 begin\r
25159   readstrexvar(result);\r
25160 end;\r
25162 //[function TStream.WriteStrPas]\r
25163 function TStream.WriteStrPas( S: String ): DWORD;\r
25164 var L: Integer;\r
25165 begin\r
25166   Result := 0;\r
25167   L := Length( S );\r
25168   if L > 255 then L := 255;\r
25169   if Write( L, 1 ) < 1 then Exit;\r
25170   Result := 1;\r
25171   if L > 0 then\r
25172     Result := Write( S[ 1 ], L ) + 1;\r
25173 end;\r
25175 //[function TStream.ReadStrPas]\r
25176 function TStream.ReadStrPas: String;\r
25177 var L: Byte;\r
25178 begin\r
25179   Result := '';\r
25180   if Read( L, 1 ) < 1 then Exit;\r
25181   SetLength( Result, L );\r
25182   L := Read( Result[ 1 ], L );\r
25183   Result := Copy( Result, 1, L );\r
25184 end;\r
25187 {$IFDEF ASM_VERSION}\r
25188 //[function TStream.Seek]\r
25189 function TStream.Seek(MoveTo: integer; MoveMethod: TMoveMethod): DWord;\r
25190 asm\r
25191         CALL     [EAX].fMethods.fSeek\r
25192 end;\r
25193 {$ELSE ASM_VERSION} //Pascal\r
25194 function TStream.Seek(MoveTo: integer; MoveMethod: TMoveMethod): DWord;\r
25195 begin\r
25196   Result := fMethods.fSeek( @Self, MoveTo, MoveMethod );\r
25197 end;\r
25198 {$ENDIF ASM_VERSION}\r
25200 {$IFDEF ASM_VERSION}\r
25201 //[destructor TStream.Destroy]\r
25202 destructor TStream.Destroy;\r
25203 asm\r
25204         PUSH     EAX\r
25205         PUSH     [EAX].fData.fThread\r
25206         CALL     [EAX].fMethods.fClose\r
25207         POP      EAX\r
25208         CALL     TObj.Free\r
25209         POP      EAX\r
25210         CALL     TObj.Destroy\r
25211 end;\r
25212 {$ELSE ASM_VERSION} //Pascal\r
25213 destructor TStream.Destroy;\r
25214 begin\r
25215   fMethods.fClose( @Self );\r
25216   fData.fThread.Free;\r
25217   inherited;\r
25218 end;\r
25219 {$ENDIF ASM_VERSION}\r
25221 //+-\r
25222 //[function _NewStream]\r
25223 function _NewStream( const StreamMethods: TStreamMethods ): PStream;\r
25224 begin\r
25225   {-}\r
25226   New( Result, Create );\r
25227   {+}{++}(*Result := PStream.Create;*){--}\r
25228   Move( StreamMethods, Result.fMethods, Sizeof( TStreamMethods ) );\r
25229   Result.fPMethods := @Result.fMethods;\r
25230 end;\r
25232 //+\r
25233 //[function SeekFileStream]\r
25234 function SeekFileStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;\r
25235 begin\r
25236   Result := FileSeek( Strm.fData.fHandle, MoveTo, MoveFrom );\r
25237 end;\r
25239 //+\r
25240 //[function GetSizeFileStream]\r
25241 function GetSizeFileStream( Strm: PStream ): DWORD;\r
25242 begin\r
25243   Result := GetFileSize( Strm.fData.fHandle, nil );\r
25244   if Result = DWORD( -1 ) then Result := 0;\r
25245 end;\r
25247 //[procedure DummySetSize]\r
25248 procedure DummySetSize( Strm: PStream; Value: DWORD );\r
25249 begin\r
25250 end;\r
25252 //[procedure DummyStreamProc]\r
25253 procedure DummyStreamProc(Strm: PStream);\r
25254 begin\r
25255 end;\r
25257 //[function DummyReadWrite]\r
25258 function DummyReadWrite( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25259 asm\r
25260   XOR EAX, EAX\r
25261 end;\r
25263 //[function ReadFileStream]\r
25264 function ReadFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25265 begin\r
25266   Result := FileRead( Strm.fData.fHandle, Buffer, Count );\r
25267 end;\r
25269 //[function WriteFileStream]\r
25270 function WriteFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25271 begin\r
25272   Result := FileWrite( Strm.fData.fHandle, Buffer, Count );\r
25273 end;\r
25275 //[FUNCTION WriteFileStreamEOF]\r
25276 {$IFDEF ASM_VERSION}\r
25277 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25278 asm\r
25279         PUSH     EBX\r
25280         PUSH     [EAX].TStream.fData.fHandle\r
25281         CALL     WriteFileStream\r
25282         XCHG     EBX, EAX\r
25283         CALL     SetEndOfFile\r
25284         XCHG     EAX, EBX\r
25285         POP      EBX\r
25286 end;\r
25287 {$ELSE ASM_VERSION} //Pascal\r
25288 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25289 begin\r
25290   Result := WriteFileStream( Strm, Buffer, Count );\r
25291   SetEndOfFile( Strm.fData.fHandle );\r
25292 end;\r
25293 {$ENDIF ASM_VERSION}\r
25294 //[END WriteFileStreamEOF]\r
25296 //[procedure CloseFileStream]\r
25297 procedure CloseFileStream( Strm: PStream );\r
25298 begin\r
25299   FileClose( Strm.fData.fHandle );\r
25300 end;\r
25302 //[FUNCTION SeekMemStream]\r
25303 {$IFDEF ASM_VERSION}\r
25304 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;\r
25305 asm\r
25306         PUSH     EBX\r
25307         MOV      EBX, EDX\r
25308         AND      ECX, $FF\r
25309         LOOP     @@not_from_cur\r
25310         ADD      EBX, [EAX].TStream.fData.fPosition\r
25311 @@not_from_cur:\r
25312         LOOP     @@not_from_end\r
25313         ADD      EBX, [EAX].TStream.fData.fSize\r
25314 @@not_from_end:\r
25315         CMP      EBX, [EAX].TStream.fData.fSize\r
25316         JLE      @@space_ok\r
25317         PUSH     EAX\r
25318         MOV      EDX, EBX\r
25319         CALL     TStream.SetSize\r
25320         POP      EAX\r
25321 @@space_ok:\r
25322         XCHG     EAX, EBX\r
25323         MOV      [EBX].TStream.fData.fPosition, EAX\r
25324         POP      EBX\r
25325 end;\r
25326 {$ELSE ASM_VERSION} //Pascal\r
25327 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;\r
25328 var NewPos: DWORD;\r
25329 begin\r
25330   case MoveFrom of\r
25331   spBegin: NewPos := MoveTo;\r
25332   spCurrent: NewPos := Strm.fData.fPosition + DWORD( MoveTo );\r
25333   else //spEnd:\r
25334        NewPos := Strm.fData.fSize + DWORD( MoveTo );\r
25335   end;\r
25336   if NewPos > Strm.fData.fSize then\r
25337     Strm.SetSize( NewPos );\r
25338   Strm.fData.fPosition := NewPos;\r
25339   Result := NewPos;\r
25340 end;\r
25341 {$ENDIF ASM_VERSION}\r
25342 //[END SeekMemStream]\r
25344 //[function GetSizeMemStream]\r
25345 function GetSizeMemStream( Strm: PStream ): DWORD;\r
25346 begin\r
25347   Result := Strm.fData.fSize;\r
25348 end;\r
25350 //[PROCEDURE SetSizeMemStream]\r
25351 {$IFDEF ASM_VERSION}\r
25352 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );\r
25353 asm\r
25354         CMP      [EAX].TStream.fData.fCapacity, EDX\r
25355         JGE      @@cap_ok\r
25356         PUSH     EDX\r
25357         PUSH     EAX\r
25358         MOV      ECX, [EAX].TStream.fMemory\r
25359         JECXZ    @@get_mem\r
25360         TEST     EDX, EDX\r
25361         JZ       @@free_mem\r
25362         LEA      EAX, [EAX].TStream.fMemory\r
25363         CALL     System.@ReallocMem\r
25364         JMP      @@1\r
25365 @@get_mem:\r
25366         XCHG     EAX, EDX\r
25367         CALL     System.@GetMem\r
25368         XCHG     EDX, EAX\r
25369         POP      EAX\r
25370         MOV      [EAX].TStream.fMemory, EDX\r
25371         JMP      @@2\r
25372 @@free_mem:\r
25373         XCHG     EDX, [EAX].TStream.fMemory\r
25374         XCHG     EAX, EDX\r
25375         CALL     System.@FreeMem\r
25376 @@1:\r
25377         POP      EAX\r
25378 @@2:\r
25379         POP      EDX\r
25381 @@cap_ok:\r
25382         MOV      [EAX].TStream.fData.fSize, EDX\r
25383         CMP      [EAX].TStream.fData.fPosition, EDX\r
25384         JLE      @@exit\r
25385         MOV      [EAX].TStream.fData.fPosition, EDX\r
25386 @@exit:\r
25387 end;\r
25388 {$ELSE ASM_VERSION} //Pascal\r
25389 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );\r
25390 var S: PStream;\r
25391 begin\r
25392   S := Strm;\r
25393   if S.fData.fCapacity < NewSize then\r
25394   begin\r
25395     if S.fMemory = nil then\r
25396     begin\r
25397       if NewSize <> 0 then\r
25398          GetMem( S.fMemory, NewSize );\r
25399     end\r
25400       else\r
25401     if NewSize = 0 then\r
25402     begin\r
25403       FreeMem( S.fMemory );\r
25404       S.fMemory := nil;\r
25405     end\r
25406       else\r
25407       ReallocMem( S.fMemory, NewSize );\r
25408     S.fData.fCapacity := NewSize;\r
25409   end;\r
25410   S.fData.fSize := NewSize;\r
25411   if S.fData.fPosition > S.fData.fSize then\r
25412      S.fData.fPosition := S.fData.fSize;\r
25413 end;\r
25414 {$ENDIF ASM_VERSION}\r
25415 //[END SetSizeMemStream]\r
25417 //[FUNCTION ReadMemStream]\r
25418 {$IFDEF ASM_VERSION}\r
25419 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25420 asm\r
25421         PUSH     EBX\r
25422         XCHG     EBX, EAX\r
25423         MOV      EAX, [EBX].TStream.fData.fPosition\r
25424         ADD      EAX, ECX\r
25425         CMP      EAX, [EBX].TStream.fData.fSize\r
25426         JLE      @@count_ok\r
25427         MOV      ECX, [EBX].TStream.fData.fSize\r
25428         SUB      ECX, [EBX].TStream.fData.fPosition\r
25429 @@count_ok:\r
25430         PUSH     ECX\r
25431         MOV      EAX, [EBX].TStream.fMemory\r
25432         ADD      EAX, [EBX].TStream.fData.fPosition\r
25433         CALL     System.Move\r
25434         POP      EAX\r
25435         ADD      [EBX].TStream.fData.fPosition, EAX\r
25436         POP      EBX\r
25437 end;\r
25438 {$ELSE ASM_VERSION} //Pascal\r
25439 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25440 var S: PStream;\r
25441 begin\r
25442   S := Strm;\r
25443   if Count + S.fData.fPosition > S.fData.fSize then\r
25444      Count := S.fData.fSize - S.fData.fPosition;\r
25445   Result := Count;\r
25446   Move( Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Buffer, Result );\r
25447   Inc( S.fData.fPosition, Result );\r
25448 end;\r
25449 {$ENDIF ASM_VERSION}\r
25450 //[END ReadMemStream]\r
25452 //[FUNCTION WriteMemStream]\r
25453 {$IFDEF ASM_VERSION}\r
25454 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25455 asm\r
25456         PUSH     EBX\r
25457         XCHG     EBX, EAX\r
25458         MOV      EAX, [EBX].TStream.fData.fPosition\r
25459         ADD      EAX, ECX\r
25460         CMP      EAX, [EBX].TStream.fData.fSize\r
25461         PUSH     EDX\r
25462         PUSH     ECX\r
25463         JLE      @@count_ok\r
25464         XCHG     EDX, EAX\r
25465         MOV      EAX, EBX\r
25466         CALL     TStream.SetSize\r
25467 @@count_ok:\r
25468         POP      ECX\r
25469         POP      EAX\r
25470         MOV      EDX, [EBX].TStream.fMemory\r
25471         ADD      EDX, [EBX].TStream.fData.fPosition\r
25472         PUSH     ECX\r
25473         CALL     System.Move\r
25474         POP      EAX\r
25475         ADD      [EBX].TStream.fData.fPosition, EAX\r
25476         POP      EBX\r
25477 end;\r
25478 {$ELSE ASM_VERSION} //Pascal\r
25479 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25480 var S: PStream;\r
25481 begin\r
25482   S := Strm;\r
25483   if Count + S.fData.fPosition > S.fData.fSize then\r
25484      S.SetSize( S.fData.fPosition + Count );\r
25485   Result := Count;\r
25486   Move( Buffer, Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Result );\r
25487   Inc( S.fData.fPosition, Result );\r
25488 end;\r
25489 {$ENDIF ASM_VERSION}\r
25490 //[END WriteMemStream]\r
25492 //[PROCEDURE CloseMemStream]\r
25493 {$IFDEF ASM_VERSION}\r
25494 procedure CloseMemStream( Strm: PStream );\r
25495 asm\r
25496         MOV      ECX, [EAX].TStream.fMemory\r
25497         JECXZ    @@exit\r
25498         XCHG     EAX, ECX\r
25499         CALL     System.@FreeMem\r
25500 @@exit:\r
25501 end;\r
25502 {$ELSE ASM_VERSION} //Pascal\r
25503 procedure CloseMemStream( Strm: PStream );\r
25504 var S: PStream;\r
25505 begin\r
25506   S := Strm;\r
25507   if S.fMemory <> nil then\r
25508     FreeMem( S.fMemory );\r
25509 end;\r
25510 {$ENDIF ASM_VERSION}\r
25511 //[END CloseMemStream]\r
25513 const\r
25514   BaseFileMethods: TStreamMethods = (\r
25515     fSeek: SeekFileStream;\r
25516     fGetSiz: GetSizeFileStream;\r
25517     fSetSiz: DummySetSize;\r
25518     fRead: DummyReadWrite;\r
25519     fWrite: DummyReadWrite;\r
25520     fClose: CloseFileStream;\r
25521     fCustom: nil;\r
25522   );\r
25524   MemoryMethods: TStreamMethods = (\r
25525     fSeek: SeekMemStream;\r
25526     fGetSiz: GetSizeMemStream;\r
25527     fSetSiz: SetSizeMemStream;\r
25528     fRead: ReadMemStream;\r
25529     fWrite: WriteMemStream;\r
25530     fClose: CloseMemStream;\r
25531     fCustom: nil;\r
25532   );\r
25534 // by Roman Vorobets:\r
25535 //[procedure SetSizeFileStream]\r
25536 procedure SetSizeFileStream( Strm: PStream; NewSize: DWORD );\r
25537 var\r
25538   P: DWORD;\r
25539 begin\r
25540   P:=Strm.Position;\r
25541   Strm.Position:=NewSize;\r
25542   SetEndOfFile(Strm.Handle);\r
25543   if P < NewSize then\r
25544     Strm.Position:=P;\r
25545 end;\r
25547 //[function NewFileStream]\r
25548 function NewFileStream( const FileName: String; Options: DWORD ): PStream;\r
25549 begin\r
25550   Result := _NewStream( BaseFileMethods );\r
25551   Result.fMethods.fRead := ReadFileStream;\r
25552   Result.fMethods.fWrite := WriteFileStream; // not WriteStreamEOF, Àëåêñåé Øóâàëîâ\r
25553   Result.fMethods.fSetSiz := SetSizeFileStream;\r
25554   Result.fData.fHandle := FileCreate( FileName, Options );\r
25555 end;\r
25557 //[FUNCTION NewReadFileStream]\r
25558 {$IFDEF ASM_VERSION}\r
25559 function NewReadFileStream( const FileName: String ): PStream;\r
25560 asm\r
25561         PUSH     EBX\r
25562         XCHG     EBX, EAX\r
25563         MOV      EAX, offset[BaseFileMethods]\r
25564         CALL     _NewStream\r
25565         MOV      [EAX].TStream.fMethods.fRead, offset[ReadFileStream]\r
25566         XCHG     EBX, EAX\r
25567         MOV      EDX, ofOpenRead or ofOpenExisting or ofShareDenyWrite\r
25568         CALL     FileCreate\r
25569         MOV      [EBX].TStream.fData.fHandle, EAX\r
25570         XCHG     EAX, EBX\r
25571         POP      EBX\r
25572 end;\r
25573 {$ELSE ASM_VERSION} //Pascal\r
25574 function NewReadFileStream( const FileName: String ): PStream;\r
25575 begin\r
25576   Result := _NewStream( BaseFileMethods );\r
25577   Result.fMethods.fRead := ReadFileStream;\r
25578   Result.fData.fHandle := FileCreate( FileName,\r
25579                                       ofOpenRead or ofShareDenyWrite or ofOpenExisting );\r
25580 end;\r
25581 {$ENDIF ASM_VERSION}\r
25582 //[END NewReadFileStream]\r
25584 //[FUNCTION NewWriteFileStream]\r
25585 {$IFDEF ASM_VERSION}\r
25586 function NewWriteFileStream( const FileName: String ): PStream;\r
25587 asm\r
25588         PUSH     EBX\r
25589         XCHG     EBX, EAX\r
25590         MOV      EAX, offset[BaseFileMethods]\r
25591         CALL     _NewStream\r
25592         MOV      [EAX].TStream.fMethods.fWrite, offset[WriteFileStreamEOF]\r
25593         MOV      [EAX].TStream.fMethods.fSetSiz, offset[SetSizeFileStream]\r
25594         XCHG     EBX, EAX\r
25595         MOV      EDX, ofOpenWrite or ofOpenAlways or ofShareDenyWrite\r
25596         CALL     FileCreate\r
25597         MOV      [EBX].TStream.fData.fHandle, EAX\r
25598         XCHG     EAX, EBX\r
25599         POP      EBX\r
25600 end;\r
25601 {$ELSE ASM_VERSION} //Pascal\r
25602 function NewWriteFileStream( const FileName: String ): PStream;\r
25603 begin\r
25604   Result := _NewStream( BaseFileMethods );\r
25605   Result.fMethods.fWrite := WriteFileStreamEOF;\r
25606   Result.fMethods.fSetSiz := SetSizeFileStream;\r
25607   Result.fData.fHandle := FileCreate( FileName,\r
25608                                       //ofOpenWrite or ofCreateAlways );\r
25609                                       ofOpenWrite or ofOpenAlways or ofShareDenyWrite );\r
25610 end;\r
25611 {$ENDIF ASM_VERSION}\r
25612 //[END NewWriteFileStream]\r
25614 //[FUNCTION NewReadWriteFileStream]\r
25615 {$IFDEF ASM_noVERSION}\r
25616 function NewReadWriteFileStream( const FileName: String ): PStream;\r
25617 asm\r
25618         PUSH     EBX\r
25619         XCHG     EBX, EAX\r
25620         MOV      EAX, offset[BaseFileMethods]\r
25621         CALL     _NewStream\r
25622         MOV      [EAX].TStream.fMethods.fRead, offset[ReadFileStream]\r
25623         MOV      [EAX].TStream.fMethods.fWrite, offset[WriteFileStream]\r
25624         MOV      [EAX].TStream.fMethods.fSetSiz, offset[SetSizeFileStream]\r
25625         XCHG     EBX, EAX\r
25627         PUSH     EAX\r
25628         CALL     FileExists\r
25629         MOV      EDX, ofOpenReadWrite or ofCreateAlways or ofShareDenyWrite\r
25630         ADD      DH, AL // $200 (ofCreateAlways) -> $300 (ofCreateExisting)\r
25631         POP      EAX\r
25633         CALL     FileCreate\r
25634         MOV      [EBX].TStream.fData.fHandle, EAX\r
25635         XCHG     EAX, EBX\r
25636         POP      EBX\r
25637 end;\r
25638 {$ELSE ASM_VERSION} //Pascal\r
25639 function NewReadWriteFileStream( const FileName: String ): PStream;\r
25640 var Creation: DWORD;\r
25641 begin\r
25642   Result := _NewStream( BaseFileMethods );\r
25643   Result.fMethods.fRead := ReadFileStream;\r
25644   Result.fMethods.fWrite := WriteFileStream;\r
25645   Result.fMethods.fSetSiz := SetSizeFileStream;\r
25646   Creation := ofCreateAlways;\r
25647   if FileExists( FileName ) then Creation := ofOpenExisting;\r
25648   Result.fData.fHandle := FileCreate( FileName,\r
25649                           ofOpenReadWrite or Creation or ofShareDenyWrite );\r
25650 end;\r
25651 {$ENDIF ASM_VERSION}\r
25652 //[END NewReadWriteFileStream]\r
25654 //[function NewMemoryStream]\r
25655 function NewMemoryStream: PStream;\r
25656 begin\r
25657   Result := _NewStream( MemoryMethods );\r
25658 end;\r
25660 //[FUNCTION WriteExMemoryStream]\r
25661 {$IFDEF ASM_VERSION}\r
25662 function WriteExMemoryStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25663 asm\r
25664         PUSH     EBX\r
25665         XCHG     EBX, EAX\r
25666         MOV      EAX, [EBX].TStream.fData.fSize\r
25667         SUB      EAX, [EBX].TStream.fData.fPosition\r
25668         CMP      EAX, ECX\r
25669         JGE      @@1\r
25670         XCHG     ECX, EAX\r
25671 @@1:\r
25672         PUSH     EDX\r
25673         PUSH     ECX\r
25674         JLE      @@count_ok\r
25675         XCHG     EDX, EAX\r
25676         MOV      EAX, EBX\r
25677         CALL     TStream.SetSize\r
25678 @@count_ok:\r
25679         POP      ECX\r
25680         POP      EAX\r
25681         MOV      EDX, [EBX].TStream.fMemory\r
25682         ADD      EDX, [EBX].TStream.fData.fPosition\r
25683         PUSH     ECX\r
25684         CALL     System.Move\r
25685         POP      EAX\r
25686         ADD      [EBX].TStream.fData.fPosition, EAX\r
25687         POP      EBX\r
25688 end;\r
25689 {$ELSE ASM_VERSION}\r
25690 function WriteExMemoryStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;\r
25691 var S: PStream;\r
25692 begin\r
25693   S := Strm;\r
25694   if Count + S.fData.fPosition > S.fData.fSize then\r
25695     Count := S.fData.fSize - S.fData.fPosition;\r
25696   Result := Count;\r
25697   Move( Buffer, Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Result );\r
25698   Inc( S.fData.fPosition, Result );\r
25699 end;\r
25700 {$ENDIF ASM_VERSION}\r
25701 //[END WriteExMemoryStream]\r
25703 //[procedure DummyClose_ExMemStream]\r
25704 procedure DummyClose_ExMemStream( Strm: PStream );\r
25705 begin\r
25706   // nothing to do - ignore call (memory is not released by any way)\r
25707 end;\r
25709 //[function NewExMemoryStream]\r
25710 function NewExMemoryStream( ExistingMem: Pointer; Size: DWORD ): PStream;\r
25711 begin\r
25712   Result := NewMemoryStream;\r
25713   Result.fMemory := ExistingMem;\r
25714   Result.fData.fCapacity := Size;\r
25715   Result.fData.fSize := Size;\r
25716   Result.fMethods.fWrite := WriteExMemoryStream;\r
25717   Result.fMethods.fSetSiz := DummySetSize;\r
25718   Result.fMethods.fClose := DummyClose_ExMemStream;\r
25719 end;\r
25721 //*\r
25722 //[function Stream2Stream]\r
25723 function Stream2Stream( Dst, Src: PStream; Count: DWORD ): DWORD;\r
25724 var Buf: Pointer;\r
25725 begin\r
25726   if Src.fMemory <> nil then\r
25727   begin\r
25728      if Src.fData.fPosition + Count > Src.fData.fSize then\r
25729         Count := Src.fData.fSize - Src.fData.fPosition;\r
25730      Result := Dst.Write( Pointer(DWORD(Src.fMemory)+Src.fData.fPosition)^,\r
25731                    Count );\r
25732      Inc( Src.fData.fPosition, Result );\r
25733   end\r
25734      else\r
25735   if Dst.fMemory <> nil then\r
25736   begin\r
25737     if Dst.fData.fPosition + Count > Dst.fData.fSize then\r
25738        Dst.SetSize( Dst.fData.fPosition + Count );\r
25739     Result := Src.Read( Pointer( DWORD( Dst.fMemory ) + Dst.fData.fPosition )^,\r
25740                         Count );\r
25741     Inc( Dst.fData.fPosition, Result );\r
25742   end\r
25743      else\r
25744   begin\r
25745     GetMem( Buf, Count );\r
25746     Count := Src.Read( Buf^, Count );\r
25747     Result := Dst.Write( Buf^, Count );\r
25748     FreeMem( Buf );\r
25749   end;\r
25750 end;\r
25752 //[function Stream2StreamEx]\r
25753 function Stream2StreamEx( Dst, Src: PStream; Count: DWORD ): DWORD;\r
25754 begin\r
25755   Result := Stream2StreamExBufSz( Dst, Src, Count, 65536 );\r
25756 end;\r
25758 //[function Stream2StreamExBufSz]\r
25759 function Stream2StreamExBufSz( Dst, Src: PStream; Count, BufSz: DWORD ): DWORD;\r
25760 var\r
25761   buf:pointer;\r
25762   rd, wr:dword;\r
25763 begin\r
25764   if count=0 then result:=0 else\r
25765   begin\r
25766     result:=0;\r
25767     BufSz := Min( BufSz, Count );\r
25768     if BufSz = 0 then BufSz := Count;\r
25769     getmem(buf,BufSz);\r
25770     repeat\r
25771       if count<BufSz then rd:=count else rd:=BufSz;\r
25772       rd:=src.read(buf^,rd);\r
25773       wr := dst.write(buf^,rd);\r
25774       inc(result,wr);\r
25775       dec(Count, rd);\r
25776     until (rd<>BufSz) or (Count=0);\r
25777     freemem(buf);\r
25778   end;\r
25779 end;\r
25781 //[FUNCTION Resource2Stream]\r
25782 {$IFDEF ASM_VERSION}\r
25783 function Resource2Stream( DestStrm : PStream; Inst : HInst;\r
25784                           ResName : PChar; ResType : PChar ): Integer;\r
25785 asm\r
25786         PUSH     EBX\r
25787         PUSH     ESI\r
25788         MOV      EBX, EDX // EBX = Inst\r
25789         PUSH     EAX      // DestStrm\r
25790         PUSH     ResType\r
25791         PUSH     ECX\r
25792         PUSH     EDX\r
25793         CALL     FindResource\r
25794         TEST     EAX, EAX\r
25795         JZ       @@exit0\r
25797         PUSH     EAX\r
25798         PUSH     EBX\r
25799         PUSH     EAX\r
25800         PUSH     EBX\r
25801         CALL     SizeofResource\r
25802         XCHG     EBX, EAX\r
25803         CALL     LoadResource\r
25804         TEST     EAX, EAX\r
25805         JZ       @@exit0\r
25806         XCHG     ESI, EAX\r
25808         PUSH     ESI\r
25809         CALL     GlobalLock\r
25810         TEST     EAX, EAX\r
25811         JNZ      @@P_ok\r
25813         CALL     GetLastError\r
25814         CMP      EAX, ERROR_INVALID_HANDLE\r
25815         JNZ      @@exit_00\r
25816         MOV      EAX, ESI\r
25818 @@P_ok:\r
25819         XCHG     EDX, EAX\r
25820         POP      EAX // DestStrm\r
25821         PUSH     EDX\r
25822         MOV      ECX, EBX\r
25823         CALL     TStream.Write\r
25825         //EAX = Result (length of written data)\r
25826         XCHG     EBX, EAX\r
25827         POP      EAX\r
25828         CMP      ESI, EAX\r
25829         JE       @@not_unlock\r
25831         PUSH     ESI\r
25832         CALL     GlobalUnlock\r
25833 @@not_unlock:\r
25834         XCHG     EAX, EBX\r
25835         JMP      @@exit\r
25837 @@exit_00:\r
25838         XOR      EAX, EAX\r
25839 @@exit0:\r
25840         POP      ECX\r
25841 @@exit:\r
25842         POP      ESI\r
25843         POP      EBX\r
25844 end;\r
25845 {$ELSE ASM_VERSION} //Pascal\r
25846 function Resource2Stream( DestStrm : PStream; Inst : HInst;\r
25847                           ResName : PChar; ResType : PChar ): Integer;\r
25848 var R : HRSRC;\r
25849     G : HGlobal;\r
25850     P : PChar;\r
25851     Sz : DWORD;\r
25852     E : Integer;\r
25853 begin\r
25854   Result := 0;\r
25855   R := FindResource( Inst, ResName, ResType );\r
25856   if R <> 0 then\r
25857   begin\r
25858     Sz := SizeofResource( Inst, R );\r
25859     G := LoadResource( Inst, R );\r
25860     if G <> 0 then\r
25861     begin\r
25862       P := GlobalLock( G );\r
25863       if P = nil then\r
25864       begin\r
25865         E := GetLastError;\r
25866         if E = ERROR_INVALID_HANDLE then\r
25867            P := Pointer( G )\r
25868         else\r
25869            Exit;\r
25870       end;\r
25871       Result := DestStrm.Write( P^, Sz );\r
25872       if P <> Pointer( G ) then\r
25873         GlobalUnlock( G );\r
25874       //FreeResource( G );\r
25875       { from Win32.hlp: "You do not need to call the FreeResource\r
25876         function to free a resource loaded by using the LoadResource\r
25877         function." }\r
25878     end;\r
25879   end;\r
25880 end;\r
25881 {$ENDIF ASM_VERSION}\r
25882 //[END Resource2Stream]\r
25895 ///////////////////////////////////////////////////////////////////////////\r
25896 //\r
25897 //\r
25898 //                        I  N  I  -  F  I  L  E  S\r
25899 //\r
25900 //\r
25901 ///////////////////////////////////////////////////////////////////////////\r
25904 { TIniFile }\r
25906 {$IFDEF ASM_VERSION}\r
25907 //[destructor TIniFile.Destroy]\r
25908 destructor TIniFile.Destroy;\r
25909 asm     //cmd    //opd\r
25910         PUSH     EAX\r
25911         LEA      EDX, [EAX].fFileName\r
25912         PUSH     EDX\r
25913         LEA      EAX, [EAX].fSection\r
25914         CALL     System.@LStrClr\r
25915         POP      EAX\r
25916         CALL     System.@LStrClr\r
25917         POP      EAX\r
25918         CALL     TObj.Destroy\r
25919 end;\r
25920 {$ELSE ASM_VERSION} //Pascal\r
25921 destructor TIniFile.Destroy;\r
25922 begin\r
25923   fFileName := '';\r
25924   fSection := '';\r
25925   inherited;\r
25926 end;\r
25927 {$ENDIF ASM_VERSION}\r
25929 {$IFNDEF _D5orHigher}\r
25930 // Place here correct definition for WritePrivateProfileStruct\r
25931 // and GetPrivateProfileStruct (a bug in Delphi2, Delphi3 and Delphi4)\r
25932 //[API WritePrivateProfileStruct]\r
25933 function WritePrivateProfileStruct(lpszSection, lpszKey: PChar;\r
25934   lpStruct: Pointer; uSizeStruct: UINT; szFile: PChar): BOOL; stdcall;\r
25935   external kernel32 name 'WritePrivateProfileStructA';\r
25936 //[API GetPrivateProfileStruct]\r
25937 function GetPrivateProfileStruct(lpszSection, lpszKey: PAnsiChar;\r
25938   lpStruct: Pointer; uSizeStruct: UINT; szFile: PAnsiChar): BOOL; stdcall;\r
25939   external kernel32 name 'GetPrivateProfileStructA';\r
25941 // + by Slava A. Gavrik:\r
25942 ////////////////////////////////////////////////////////////////////////////\r
25943 //[function WritePrivateProfileSection]\r
25944 function WritePrivateProfileSection(lpAppName, lpString,\r
25945   lpFileName: PChar): BOOL; stdcall;\r
25946   external kernel32 name 'WritePrivateProfileSectionA';\r
25947 //[function GetPrivateProfileSection]\r
25948 function GetPrivateProfileSection(lpAppName: PChar; lpReturnedString: PChar;\r
25949   nSize: DWORD; lpFileName: PChar): DWORD; stdcall;\r
25950   external kernel32 name 'GetPrivateProfileSectionA';\r
25952 //[function GetPrivateProfileSectionNames]\r
25953 function GetPrivateProfileSectionNames(lpszReturnBuffer: PChar; nSize:\r
25954 DWORD;\r
25955   lpFileName: PChar): DWORD; stdcall;\r
25956   external kernel32 name 'GetPrivateProfileSectionNamesA';\r
25957 ////////////////////////////////////////////////////////////////////////////\r
25958 {$ENDIF}\r
25961 //[procedure TIniFile.ClearAll]\r
25962 procedure TIniFile.ClearAll;\r
25963 begin\r
25964   WritePrivateProfileString( nil, nil, nil,\r
25965                              PChar( fFileName ) );\r
25966 end;\r
25968 //[procedure TIniFile.ClearKey]\r
25969 procedure TIniFile.ClearKey(const Key: String);\r
25970 begin\r
25971   WritePrivateProfileString( PChar( fSection ), PChar( Key ), nil,\r
25972                              PChar( fFileName ) );\r
25973 end;\r
25975 //[procedure TIniFile.ClearSection]\r
25976 procedure TIniFile.ClearSection;\r
25977 begin\r
25978   WritePrivateProfileString( PChar( fSection ), nil, nil,\r
25979                              PChar( fFileName ) );\r
25980 end;\r
25982 //[function TIniFile.ValueBoolean]\r
25983 function TIniFile.ValueBoolean(const Key: String; Value: Boolean): Boolean;\r
25984 begin\r
25985   if fMode = ifmRead then\r
25986      Result := GetPrivateProfileInt( PChar( fSection ), PChar( Key ),\r
25987                Integer( Value ), PChar( fFileName ) ) <> 0\r
25988   else\r
25989   begin\r
25990     WritePrivateProfileString( PChar( fSection ), PChar( Key ),\r
25991               PChar( Int2Str( Integer( Value ) ) ), PChar( fFileName ) );\r
25992     Result := Value;\r
25993   end;\r
25994 end;\r
25996 //[function TIniFile.ValueData]\r
25997 function TIniFile.ValueData(const Key: String; Value: Pointer;\r
25998   Count: Integer): Boolean;\r
25999 begin\r
26000   if fMode = ifmRead then\r
26001      Result := GetPrivateProfileStruct( PChar( fSection ), PChar( Key ),\r
26002                Value, Count, PChar( fFileName ) )\r
26003   else\r
26004      Result := WritePrivateProfileStruct( PChar( fSection ), PChar( Key ),\r
26005                Value, Count, PChar( fFileName ) );\r
26006 end;\r
26008 //[function TIniFile.ValueInteger]\r
26009 function TIniFile.ValueInteger(const Key: String; Value: Integer): Integer;\r
26010 begin\r
26011   if fMode = ifmRead then\r
26012      Result := GetPrivateProfileInt( PChar( fSection ), PChar( Key ),\r
26013                Integer( Value ), PChar( fFileName ) )\r
26014   else\r
26015   begin\r
26016      Result := Value;\r
26017      WritePrivateProfileString( PChar( fSection ), PChar( Key ),\r
26018                PChar( Int2Str( Value ) ), PChar( fFileName ) );\r
26019   end;\r
26020 end;\r
26022 //[function TIniFile.ValueString]\r
26023 function TIniFile.ValueString(const Key, Value: String): String;\r
26024 var\r
26025   Buffer: array[0..2047] of Char;\r
26026 begin\r
26027   if fMode = ifmRead then\r
26028   begin\r
26029     Buffer[ 0 ] := #0;\r
26030     GetPrivateProfileString(PChar(fSection),\r
26031          PChar(Key), PChar(Value), Buffer, SizeOf(Buffer), PChar(fFileName));\r
26032     Result := Buffer;\r
26033   end\r
26034     else\r
26035   begin\r
26036      Result := Value;\r
26037      WritePrivateProfileString( PChar( fSection ), PChar( Key ),\r
26038                PChar( Value ), PChar( fFileName ) );\r
26039   end;\r
26040 end;\r
26042 //[function OpenIniFile]\r
26043 function OpenIniFile( const FileName: String ): PIniFile;\r
26044 begin\r
26045   {-}\r
26046   New( Result, Create );\r
26047   {+}{++}(*Result := PIniFile.Create;*){--}\r
26048   Result.fFileName := FileName;\r
26049 end;\r
26051 /////////////////////////////////////////////////// GetSectionNames, SectionData\r
26052 // - by Vyacheslav A. Gavrik :\r
26054 const\r
26055   IniBufferSize = 32767;\r
26056   IniBufferStrSize = IniBufferSize+4;         /// äëÿ ìàõèíàöèé :)\r
26058 {$IFDEF ASM_VERSION}\r
26059 //[procedure _FillStrList]\r
26060 procedure _FillStrList;    // Ýòà ÷àñòü êîäà îáùàÿ äëÿ äâóõ ñëåäóþùèõ ïðîöåäóð\r
26061 asm\r
26062 ///////////////////////////////\r
26063         OR      EAX,0\r
26064         JE      @@EXIT                  //ERROR\r
26065 //        LEA     EAX,[EAX-IniBufferSize]\r
26066 //        JE      @@EXIT\r
26067 //      âîçìîæíà íåõâàòêà Áóôåðà... â ïðèíöèïå íå îøèáêà :)\r
26068 //      âîçâðàùàåì ÷òî âëåçëî...\r
26069 //////////////////////////////\r
26070 @@LOOP:\r
26071         LEA     EAX,[ESI+4]\r
26072         CALL    StrLen\r
26073         MOV     [ESI],EAX\r
26074         LEA     EDX,[ESI+4]\r
26075         INC     EAX\r
26076         ADD     ESI,EAX\r
26078         MOV     EAX,EDI\r
26080         CALL    TStrList.ADD\r
26082         CMP     byte ptr [ESI+4],0\r
26083         JNE     @@LOOP\r
26085 @@EXIT:\r
26086         POP     EAX\r
26087         CALL    System.@FreeMem\r
26090         POP     ECX\r
26091         POP     EBX\r
26092         POP     EDI\r
26093         POP     ESI\r
26094 end;\r
26097 //[procedure TIniFile.GetSectionNames]\r
26098 procedure TIniFile.GetSectionNames(Names: PStrList);\r
26099 asm\r
26100         PUSH    ESI\r
26101         PUSH    EDI\r
26102         PUSH    EBX\r
26103         PUSH    ECX\r
26105         MOV     EBX,EAX\r
26106         MOV     EAX, IniBufferStrSize\r
26107         MOV     EDI,EDX\r
26109         CALL    System.@GetMem\r
26110         MOV     ESI,EAX\r
26111         PUSH    EAX\r
26113         PUSH    [EBX].fFileName\r
26114         MOV     EAX,IniBufferSize\r
26115         PUSH    EAX\r
26117         LEA     EAX,[ESI+4]\r
26118         PUSH    EAX\r
26120         CALL    GetPrivateProfileSectionNames\r
26121         JMP     _FillStrList\r
26122 end;\r
26124 //[procedure TIniFile.SectionData]\r
26125 procedure TIniFile.SectionData(Names: PStrList);\r
26126 asm\r
26127         PUSH    ESI\r
26128         PUSH    EDI\r
26129         PUSH    EBX\r
26130         PUSH    ECX\r
26132         MOV     EBX,EAX\r
26133         MOV     EAX, IniBufferStrSize\r
26134         MOV     EDI,EDX\r
26136         CALL    System.@GetMem\r
26137         MOV     ESI,EAX\r
26138         PUSH    EAX\r
26140         OR     [EBX].fMode,0\r
26141         JNE     @@DOWrite\r
26143         PUSH    [EBX].fFileName\r
26144         MOV     EAX,IniBufferSize\r
26145         PUSH    EAX\r
26147         LEA     EAX,[ESI+4]\r
26148         PUSH    EAX\r
26149         PUSH    [EBX].fSection\r
26151         CALL    GetPrivateProfileSection\r
26152         JMP     _FillStrList\r
26154 @@DOWrite:\r
26156         PUSH    EBX\r
26157         PUSH    ESI\r
26158         PUSH    EDX\r
26159         PUSH    EBP\r
26161         MOV     EDX,0\r
26162         MOV     EBP,[EDI].TStrList.fCount\r
26163         MOV     EBX,IniBufferSize-2 // îñòàâèì ìåñòî äëÿ #0#0\r
26165 {ECM+++>} OR      EBP,EBP  // otherwise GetPChars when StrList.Count = 0 crashed\r
26167 @@LOOP:\r
26168         JE      @@ENDLOOP\r
26170         OR      EBX,EBX\r
26171         JE      @@ENDLOOP\r
26173         PUSH    EDX\r
26174         MOV     EAX,EDI\r
26175         CALL    TStrList.GetPChars\r
26177         PUSH    EAX\r
26178         CALL    StrLen\r
26179         POP     EAX\r
26181         XOR     ECX,-1\r
26182         MOV     EDX,ESI\r
26184         SUB     EBX,ECX\r
26185         JA      @@L1\r
26186         ADD     ECX,EBX\r
26187         XOR     EBX,EBX\r
26188 @@L1:\r
26190         ADD     ESI,ECX\r
26192         CALL    MOVE\r
26193 @@L2:\r
26194         POP     EDX\r
26195         INC     EDX\r
26196         DEC     EBP\r
26197         JMP     @@LOOP\r
26198 @@ENDLOOP:\r
26199         MOV     WORD PTR [ESI],0\r
26201         POP     EBP\r
26202         POP     EDX\r
26203         POP     ESI\r
26204         POP     EBX\r
26205 ///////////////////////////////////\r
26206         MOV     EAX,EBX                 // íîäî î÷èùàòü\r
26207         CALL    ClearSection\r
26208 //////////////////////////////////\r
26210         PUSH    [EBX].fFileName\r
26211         PUSH    ESI\r
26212         PUSH    [EBX].fSection\r
26214         CALL    WritePrivateProfileSection\r
26216         POP     EAX\r
26217         CALL    System.@FreeMem\r
26219         POP     ECX\r
26220         POP     EBX\r
26221         POP     EDI\r
26222         POP     ESI\r
26224 end;\r
26225 {$ELSE ASM_VERSION} //Pascal\r
26227 //[procedure TIniFile.GetSectionNames]\r
26228 procedure TIniFile.GetSectionNames(Names: PStrList);\r
26229 var\r
26230   i:integer;\r
26231   Pc:PChar;\r
26232   PcEnd:PChar;\r
26233   Buffer:Pointer;\r
26234 begin\r
26235   GetMem(Buffer,IniBufferSize);\r
26236   Pc:=Buffer;\r
26237   i := GetPrivateProfileSectionNames(Buffer, IniBufferSize, PChar(fFileName));\r
26238   PcEnd:=Pc+i;\r
26239   repeat\r
26240     Names.Add(Pc);\r
26241     Pc:=PC+Length(PC)+1;\r
26242   until PC>=PcEnd;\r
26243   FreeMem(Buffer);\r
26244 end;\r
26246 //[procedure TIniFile.SectionData]\r
26247 procedure TIniFile.SectionData(Names: PStrList);\r
26248 var\r
26249   i:integer;\r
26250   Pc:PChar;\r
26251   PcEnd:PChar;\r
26252   Buffer:Pointer;\r
26253 begin\r
26254   GetMem(Buffer,IniBufferSize);\r
26255   Pc:=Buffer;\r
26256   if fMode = ifmRead then\r
26257   begin\r
26258     i:=GetPrivateProfileSection(PChar(fSection), Buffer, IniBufferSize, PChar(fFileName));\r
26259     PcEnd:=Pc+i;\r
26260     while PC < PcEnd do // Chg by ECM from REPEAT-UNTIL: i=0 (empty section) => Names.Count=1\r
26261     begin\r
26262       Names.Add(Pc);\r
26263       Pc:=PC+Length(PC)+1;\r
26264     end;\r
26265   end else\r
26266   begin\r
26267     for i:= 0 to Names.Count-1 do\r
26268     begin\r
26269       StrCopy(Pc,Names.ItemPtrs[i]);\r
26270       Pc:=PC+Length(PC)+1;\r
26271     end;\r
26272     Pc[0]:=#0;\r
26273     ClearSection;\r
26274     WritePrivateProfileSection(PChar(fSection), Buffer, PChar(fFileName));\r
26276   end;\r
26277   FreeMem(Buffer);\r
26278 end;\r
26279 {$ENDIF ASM_VERSION}\r
26281 //////////////////////////////////////////////////////////////////////\r
26293 /////////////////////////////////////////////////////////////////////////\r
26294 //\r
26295 //\r
26296 //                                M  E  N  U\r
26297 //\r
26298 //\r
26299 /////////////////////////////////////////////////////////////////////////\r
26301 { -- Menu implementation -- }\r
26303 //[FUNCTION MakeAccelerator]\r
26304 {$IFDEF ASM_VERSION}\r
26305 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;\r
26306 asm\r
26307         MOVZX    EAX, AL\r
26308         PUSH     EAX\r
26309         MOV      [ESP+1], DX\r
26310         POP      EAX\r
26311 end;\r
26312 {$ELSE ASM_VERSION} //Pascal\r
26313 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;\r
26314 begin\r
26315   Result.fVirt := fVirt;\r
26316   Result.Key := Key;\r
26317 end;\r
26318 {$ENDIF ASM_VERSION}\r
26319 //[END MakeAccelerator]\r
26321 //[FUNCTION GetAcceleratorText]\r
26322 function GetAcceleratorText( const Accelerator: TMenuAccelerator ): string;\r
26323 var\r
26324   KeyName: array[0..255] of Char;\r
26326   procedure AddKeyName( Code: Integer );\r
26327   begin\r
26328     Code := MapVirtualKey(Code, 0);\r
26329     if Code = 0 then exit;\r
26330     if GetKeyNameText(Code shl 16, KeyName, SizeOf(KeyName)) > 0 then begin\r
26331       if Result <> '' then\r
26332         Result := Result + '+';\r
26333       Result := Result + KeyName;\r
26334     end;\r
26335   end;\r
26337 begin\r
26338   Result := '';\r
26339   with Accelerator do begin\r
26340     if fVirt and FCONTROL <> 0 then\r
26341       AddKeyName(VK_CONTROL);\r
26342     if fVirt and FSHIFT <> 0 then\r
26343       AddKeyName(VK_SHIFT);\r
26344     if fVirt and FALT <> 0 then\r
26345       AddKeyName(VK_ALT);\r
26346     if fVirt and $20 <> 0 then\r
26347       AddKeyName(VK_LWIN);\r
26348     if fVirt and $40 <> 0 then\r
26349       AddKeyName(VK_RWIN);\r
26351     AddKeyName(Key);\r
26352   end;\r
26353 end;\r
26354 //[END GetAcceleratorText]\r
26357 const\r
26358   MIDATA_CHECKITEM = $40000000;\r
26359   MIDATA_RADIOITEM = $80000000;\r
26361 //[function WndProcMenu]\r
26362 {$IFNDEF NEW_MENU_ACCELL}\r
26363 function WndProcMenu( Sender: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
26364 var M, M1: PMenu;\r
26365     Idx: Integer;\r
26366     Id: Integer;\r
26367 begin\r
26368   Result := False;\r
26369   if Msg.message = WM_COMMAND then\r
26370   begin\r
26371      if (Msg.lParam = 0) and (HIWORD( Msg.wParam ) <= 1) then\r
26372      begin\r
26373        M := PMenu( Sender.fMenuObj );\r
26374        while M <> nil do\r
26375        begin\r
26376          Id := LoWord( Msg.wParam );\r
26377          M1 := M.Items[ Id ];\r
26378          if M1 <> nil then\r
26379          begin\r
26380            Result := True;\r
26381            Rslt := 0;\r
26382            Idx := M.IndexOf( M1 );\r
26383            M.fByAccel := HiWord( Msg.wParam ) <> 0;\r
26384            if M1.FRadioGroup <> 0 then\r
26385              M1.RadioCheckItem\r
26386            else\r
26387            if M1.FIsCheckItem then\r
26388              M1.Checked := not M1.Checked;\r
26389            if Assigned(M1.FOnMenuItem) then\r
26390              M1.FOnMenuItem( M, Idx )\r
26391            else if Assigned( M.FOnMenuItem ) then\r
26392              M.FOnMenuItem( M, Idx );\r
26393            //M.FProcessed := True;\r
26394            break;\r
26395          end;\r
26396          M := M.fNextMenu;\r
26397        end;\r
26398      end;\r
26399   end;\r
26400 end;\r
26402 {$ELSE}\r
26404 function WndProcMenu( Sender: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
26406   function ProcessMenuItem(M: PMenu; Id: Integer): Boolean;\r
26407   var\r
26408     M1: PMenu;\r
26409     Idx: Integer;\r
26410   begin\r
26411     M1 := M.Items[ Id ];\r
26412     Result := (M1 <> nil);\r
26413     if Result then\r
26414     begin\r
26415       Idx := M.IndexOf( M1 );\r
26416       M.fByAccel := HiWord( Msg.wParam ) <> 0;\r
26417       if M1.FRadioGroup <> 0 then\r
26418         M1.RadioCheckItem\r
26419       else\r
26420       if M1.FIsCheckItem then\r
26421         M1.Checked := not M1.Checked;\r
26422       if Assigned(M1.FOnMenuItem) then begin\r
26423       {$IFDEF USE_MENU_CURCTL} // fixed\r
26424         M.fCurCtl := Sender;   // fixed\r
26425       {$ENDIF}                 // fixed\r
26426         M1.FOnMenuItem( M, Idx )\r
26427       end\r
26428       else if Assigned( M.FOnMenuItem ) then\r
26429         M.FOnMenuItem( M, Idx );\r
26430     end;\r
26431   end;\r
26433 var\r
26434   M: PMenu;\r
26435   Id: Integer;\r
26436 begin\r
26437   Result := False;\r
26438   if Msg.message = WM_COMMAND then\r
26439     if (Msg.lParam = 0) and (HIWORD( Msg.wParam ) <= 1) then begin\r
26440       Id := LoWord(Msg.wParam);\r
26441       M := PMenu(Sender.fAutoPopupMenu);\r
26442       if (M <> nil) and ProcessMenuItem(M, Id) then begin\r
26443         Result := True;\r
26444         Rslt := 0;\r
26445       end\r
26446       else begin\r
26447         M := PMenu(Sender.fMenuObj);\r
26448         while M <> nil do begin\r
26449           if ProcessMenuItem(M, Id) then begin\r
26450             Result := True;\r
26451             Rslt := 0;\r
26452             Break;\r
26453           end;\r
26454           M := M.fNextMenu;\r
26455         end;\r
26456       end;\r
26457     end;\r
26458 end;\r
26459 {$ENDIF}\r
26462 var FDynamicMenuID: DWORD = $1000;\r
26464 //[function NewMenu]\r
26465 function NewMenu( AParent : PControl; MaxCmdReserve : DWORD; const Template : array of PChar;\r
26466                       aOnMenuItem: TOnMenuItem ): PMenu;\r
26467 var M: PMenu;\r
26468 begin\r
26469   {-}\r
26470   New( Result, Create );\r
26471   {+}{++}(*Result := PMenu.Create;*){--}\r
26472   Result.FVisible := TRUE;\r
26473   Result.FPopupFlags := TPM_LEFTALIGN or TPM_LEFTBUTTON;\r
26474   Result.FItems := NewList;\r
26475   Result.FOnMenuItem := aOnMenuItem;\r
26476   if (High(Template)>=0) and (Template[0] <> nil) then\r
26477   begin\r
26478     if (AParent <> nil) and (AParent.fMenuObj = nil) and not AParent.fIsControl then\r
26479       Result.FHandle := CreateMenu\r
26480     else\r
26481       Result.FHandle := CreatePopupMenu;\r
26482     Result.FillMenuItems( Result.FHandle, 0, Template );\r
26483   end;\r
26484   if assigned( AParent ) then\r
26485   begin\r
26486     Result.FControl := AParent;\r
26487     if AParent.fMenuObj <> nil then\r
26488     begin\r
26489       // add popup menu to the end of menu chain\r
26490       M := PMenu( AParent.fMenuObj );\r
26491       while M.fNextMenu <> nil do\r
26492         M := M.fNextMenu;\r
26493       M.fNextMenu := Result;\r
26494     end\r
26495        else\r
26496     begin\r
26497       if not AParent.fIsControl then\r
26498         AParent.Menu := Result.FHandle;\r
26499       AParent.fMenuObj := Result;\r
26500       AParent.AttachProc( WndProcMenu );\r
26501     end;\r
26502   end;\r
26503 end;\r
26504 //[END NewMenu]\r
26506 //[function NewMenuEx]\r
26507 function NewMenuEx( AParent : PControl; FirstCmd : Integer; const Template : array of PChar;\r
26508                       aOnMenuItems: array of TOnMenuItem ): PMenu;\r
26509 begin\r
26510   Result := NewMenu( AParent, FirstCmd, Template, nil );\r
26511   Result.AssignEvents( 0, aOnMenuItems );\r
26512 end;\r
26513 //[END NewMenuEx]\r
26515 { TMenu }\r
26517 const\r
26518   Breaks: array[ TMenuBreak ] of DWORD = ( 0, MFT_MENUBREAK, MFT_MENUBARBREAK );\r
26520 { + by AK - Andrzej Kubaszek }\r
26521 //[function MenuStructSize]\r
26522 function MenuStructSize: Integer;\r
26523 begin\r
26524   Result := 44;\r
26525   if not( WinVer in [wv31, wv95, wvNT] ) then\r
26526     Result := {48=} Sizeof( TMenuItemInfo );\r
26527 end;\r
26529 //[destructor TMenu.Destroy]\r
26530 destructor TMenu.Destroy;\r
26531 var Next, Prnt: PMenu;\r
26532 begin\r
26533   if Count > 0 then\r
26534   begin\r
26535     FItems.ReleaseObjects;\r
26536     FItems := NewList;\r
26537   end;\r
26538   if FParent <> nil then\r
26539   begin\r
26540     Prnt := FParent;\r
26541     FParent := nil;\r
26542     Next := Prnt.RemoveSubMenu( FId );\r
26543     Prnt.FItems.Remove( @ Self );\r
26544     if Next = nil then Exit;\r
26545   end;\r
26546    if (FControl <> nil) and (FControl.fMenu = FHandle) and (FHandle <> 0) then\r
26547    begin\r
26548      //if FControl.fHandle <> 0 then\r
26549      begin\r
26550        Windows.SetMenu( FControl.fHandle, 0 );\r
26551        // this removes main menu from window, but does not destroy it\r
26552      end;\r
26553      FControl.fMenu := 0;\r
26554      Next := PMenu( FControl.fMenuObj );\r
26555      while Next <> nil  do\r
26556      begin\r
26557        if Next.fNextMenu = @Self then\r
26558        begin\r
26559          Next.fNextMenu := fNextMenu;\r
26560          break;\r
26561        end;\r
26562        Next := Next.fNextMenu;\r
26563      end;\r
26564    end;\r
26565    Next := fNextMenu;\r
26566    if FBitmap <> 0 then\r
26567      Bitmap := 0;\r
26568    if FHandle <> 0 then\r
26569      DestroyMenu( FHandle );\r
26570    FCaption := '';\r
26571    FItems.Free;\r
26572    inherited;\r
26573    Next.Free;\r
26574    // all later created (popup) menus (of the same control)\r
26575    // are destroyed too\r
26576 end;\r
26578 //[function TMenu.GetInfo]\r
26579 function TMenu.GetInfo( var MII: TMenuItemInfo ): Boolean;\r
26580 begin\r
26581   MII.cbSize := MenuStructSize;\r
26582   Result := GetMenuItemInfo( Parent.FHandle, FId, FALSE,\r
26583             Windows.PMenuitemInfo( @ MII )^ );\r
26584 end;\r
26586 //[procedure TMenu.RedrawFormMenuBar]\r
26587 procedure TMenu.RedrawFormMenuBar;\r
26588 var C: PControl;\r
26589 begin\r
26590   C := TopParent.FControl;\r
26591   if not AppletTerminated then\r
26592   if (C <> nil) and (Pointer( C.fMenuObj ) = Pointer( TopParent )) then\r
26593     DrawMenuBar( C.FHandle );\r
26594 end;\r
26596 //[function TMenu.SetInfo]\r
26597 function TMenu.SetInfo( var MII: TMenuItemInfo ): Boolean;\r
26598 var H: THandle;\r
26599 begin\r
26600   MII.cbSize := MenuStructSize;\r
26601   H := FHandle;\r
26602   if FParent <> nil then\r
26603     H := FParent.FHandle;\r
26604   Result := SetMenuItemInfo( H, FId, FALSE, Windows.PMenuitemInfo( @ MII )^ );\r
26605   if Result and ((FParent = nil) or (FParent.FParent = nil)) then {YS}\r
26606     RedrawFormMenuBar;\r
26607 end;\r
26609 //[function TMenu.SetTypeInfo]\r
26610 function TMenu.SetTypeInfo( var MII: TMenuItemInfo ): Boolean;\r
26611 begin\r
26612   if not FIsSeparator then\r
26613   begin\r
26614     if FBmpItem = 0 then\r
26615       MII.dwTypeData := PChar( FCaption )\r
26616     else\r
26617       MII.dwTypeData := Pointer( FBmpItem );\r
26618     MII.cch := Length( FCaption );\r
26619   end;\r
26620   Result := SetInfo( MII );\r
26621 end;\r
26623 //[function TMenu.GetTopParent]\r
26624 function TMenu.GetTopParent: PMenu;\r
26625 begin\r
26626   Result := @ Self;\r
26627   while Result.FParent <> nil do\r
26628     Result := Result.FParent;\r
26629 end;\r
26631 //[function TMenu.GetControl]\r
26632 function TMenu.GetControl: PControl;\r
26633 begin\r
26634   Result := TopParent.FControl;\r
26635 end;\r
26637 //[function TMenu.GetItems]\r
26638 function TMenu.GetItems( Id: HMenu ): PMenu;\r
26639   function SearchItems( ParentMenu: PMenu; var FromIdx: Integer ): PMenu;\r
26640   var I: Integer;\r
26641   begin\r
26642     Result := ParentMenu;\r
26643     if Id = HMenu( FromIdx ) then Exit;\r
26644     if (Id >= 4096) and (DWORD( ParentMenu.FId ) = Id) then Exit;\r
26645     if ParentMenu.FItems = nil then Exit;\r
26646     for I := 0 to ParentMenu.FItems.FCount-1 do\r
26647     begin\r
26648       Inc( FromIdx );\r
26649       Result := SearchItems( ParentMenu.FItems.Items[ I ], FromIdx );\r
26650       if Result <> nil then Exit;\r
26651     end;\r
26652     Result := nil;\r
26653   end;\r
26654 var I: Integer;\r
26655 begin\r
26656   I := -1;\r
26657   Result := SearchItems( @ Self, I );\r
26658 end;\r
26660 //[function TMenu.GetCount]\r
26661 function TMenu.GetCount: Integer;\r
26662 var I: Integer;\r
26663     SubM: PMenu;\r
26664 begin\r
26665   Result := FItems.FCount;\r
26666   for I := 0 to Result-1 do\r
26667   begin\r
26668     SubM := FItems.Items[ I ];\r
26669     Result := Result + SubM.Count;\r
26670   end;\r
26671 end;\r
26673 //[function TMenu.IndexOf]\r
26674 function TMenu.IndexOf( Item: PMenu ): Integer;\r
26675   function SearchMenu( ParentMenu: PMenu; var FromIdx: Integer ): PMenu;\r
26676   var I: Integer;\r
26677   begin\r
26678     Result := ParentMenu;\r
26679     if Result = Item then Exit;\r
26680     for I := 0 to ParentMenu.FItems.FCount-1 do\r
26681     begin\r
26682       Inc( FromIdx );\r
26683       Result := SearchMenu( ParentMenu.FItems.Items[ I ], FromIdx );\r
26684       if Result <> nil then Exit;\r
26685     end;\r
26686     Result := nil;\r
26687   end;\r
26688 begin\r
26689   Result := -1;\r
26690   if SearchMenu( @ Self, Result ) = nil then\r
26691     Result := -2;\r
26692 end;\r
26694 //[function TMenu.GetState]\r
26695 function TMenu.GetState( const Index: Integer ): Boolean;\r
26696 var MII: TMenuItemInfo;\r
26697 begin\r
26698   if FVisible then\r
26699   begin\r
26700     MII.fMask := MIIM_STATE;\r
26701     if GetInfo( MII ) then\r
26702       FSavedState := MII.fState;\r
26703   end;\r
26704   Result := LongBool( FSavedState and Index );\r
26705   if Index < 0 then\r
26706     Result := not Result;\r
26707 end;\r
26709 //[procedure TMenu.SetState]\r
26710 procedure TMenu.SetState( const Index: Integer; Value: Boolean );\r
26711 var MII: TMenuItemInfo;\r
26712 begin\r
26713   GetState( 0 );\r
26714   if Value xor (Index < 0) then\r
26715     FSavedState := FSavedState or DWORD( Index and $7FFFFFFF )\r
26716   else\r
26717     FSavedState := FSavedState and not DWORD( Index );\r
26718   if FVisible then\r
26719   begin\r
26720     MII.fMask := MIIM_STATE;\r
26721     if GetInfo( MII ) then\r
26722     begin\r
26723       MII.fState := FSavedState;\r
26724       SetInfo( MII );\r
26725     end;\r
26726   end;\r
26727 end;\r
26729 //[procedure TMenu.SetData]\r
26730 procedure TMenu.SetData( Value: Pointer );\r
26731 var MII: TMenuItemInfo;\r
26732 begin\r
26733   MII.fMask := MIIM_DATA;\r
26734   MII.dwItemData := DWORD( Value );\r
26735   SetInfo( MII );\r
26736   FData := Value;\r
26737 end;\r
26739 //[procedure TMenu.ClearBitmaps]\r
26740 procedure TMenu.ClearBitmaps;\r
26741 begin\r
26742   if FBitmap <> 0 then\r
26743     DeleteObject( FBitmap );\r
26744   if FBmpChecked <> 0 then\r
26745     DeleteObject( FBmpChecked );\r
26746   if FBmpItem <> 0 then\r
26747     DeleteObject( FBmpItem );\r
26748 end;\r
26750 //[procedure TMenu.SetBitmap]\r
26751 procedure TMenu.SetBitmap( Value: HBitmap );\r
26752 var MII: TMenuItemInfo;\r
26753 begin\r
26754   if not FClearBitmaps then\r
26755   begin\r
26756     FClearBitmaps := TRUE;\r
26757     Add2AutoFreeEx( ClearBitmaps );\r
26758   end;\r
26759   if Value = FBitmap then Exit;\r
26760   if FBitmap <> 0 then\r
26761     DeleteObject( FBitmap ); // seems not necessary.\r
26762   FBitmap := Value;\r
26763   MII.fMask := MIIM_CHECKMARKS;\r
26764   MII.hbmpChecked := FBmpChecked;\r
26765   MII.hbmpUnchecked := FBitmap;\r
26766   SetInfo( MII );\r
26767 end;\r
26769 //[procedure TMenu.SetBmpChecked]\r
26770 procedure TMenu.SetBmpChecked( Value: HBitmap );\r
26771 var MII: TMenuItemInfo;\r
26772 begin\r
26773   if not FClearBitmaps then\r
26774   begin\r
26775     FClearBitmaps := TRUE;\r
26776     Add2AutoFreeEx( ClearBitmaps );\r
26777   end;\r
26778   if Value = FBmpChecked then Exit;\r
26779   if FBmpChecked <> 0 then\r
26780     DeleteObject( FBmpChecked );\r
26781   FBmpChecked := Value;\r
26782   MII.fMask := MIIM_CHECKMARKS;\r
26783   MII.hbmpChecked := FBmpChecked;\r
26784   MII.hbmpUnchecked := FBitmap;\r
26785   SetInfo( MII );\r
26786 end;\r
26788 //[procedure TMenu.SetBmpItem]\r
26789 procedure TMenu.SetBmpItem( Value: HBitmap );\r
26790 var MII: TMenuItemInfo;\r
26791 begin\r
26792   if not FClearBitmaps then\r
26793   begin\r
26794     FClearBitmaps := TRUE;\r
26795     Add2AutoFreeEx( ClearBitmaps );\r
26796   end;\r
26797   if Value = FBmpItem then Exit;\r
26798   if FBmpItem <> 0 then\r
26799     DeleteObject( FBmpItem );\r
26800   FBmpItem := Value;\r
26801   if WinVer >= wv98 then {AK}\r
26802   begin                                            {AK}\r
26803     MII.fMask := $80 {MIIM_BITMAP} ;               {AK}\r
26804     MII.hbmpItem:=Value;                           {AK}\r
26805   end                                              {AK}\r
26806   else                                             {AK}\r
26807   begin//I haven't possibility to test it in Win95 {AK}\r
26808     MII.fType := MFT_BITMAP;\r
26809     MII.dwItemData := Value;\r
26810   end;                                             {AK}\r
26811   SetInfo( MII );\r
26812 end;\r
26814 //[procedure TMenu.SetAccelerator]\r
26815 {$IFNDEF NEW_MENU_ACCELL}\r
26816 procedure TMenu.SetAccelerator(const Value: TMenuAccelerator);\r
26817 const MaxAccel = 1000;\r
26818 type TAccTab = array[0..10000] of TAccel;\r
26819      PAccTab = ^TAccTab;\r
26820      //TSetAcceleratorProc = procedure( Self_: PMenu; Idx: Integer; const Value: TMenuAccelerator );\r
26821 var AccTab: PAccTab;\r
26822     I, N : Integer;\r
26823     M, SubM: PMenu;\r
26824     C: PControl;\r
26825     Main: Boolean;\r
26826 begin\r
26827   //SetAcceleratorProc := TSetAcceleratorProc( MakeMethod( nil, @TMenu.SetAccelerator ).Code );\r
26828   if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then Exit;\r
26829   FAccelerator := Value;\r
26830   C := TopParent.FControl;\r
26831   if C = nil then Exit;\r
26832   if C.fAccelTable <> 0 then\r
26833      DestroyAcceleratorTable( C.fAccelTable );\r
26834   C.fAccelTable := 0;\r
26835   GetMem( AccTab, sizeof( TAccel ) * MaxAccel );\r
26836   N := 0;\r
26837   M := PMenu( C.fMenuObj );\r
26838   Main := TRUE;\r
26839   while M <> nil do\r
26840   begin\r
26841     if Main or M.Visible then\r
26842     begin\r
26843       for I := 0 to MaxInt-1 do\r
26844       begin\r
26845         SubM := M.Items[ I ];\r
26846         if SubM = nil then break;\r
26847         if SubM.FVisible then\r
26848         if (SubM.FAccelerator.Key <> 0) or (SubM.FAccelerator.fVirt <> 0) then\r
26849         begin\r
26850           AccTab[ N ].fVirt := SubM.FAccelerator.fVirt;\r
26851           AccTab[ N ].key := SubM.FAccelerator.Key;\r
26852           AccTab[ N ].cmd := WORD( SubM.FId );\r
26853           Inc( N );\r
26854           if N > MaxAccel then break;\r
26855         end;\r
26856       end;\r
26857     end;\r
26858     if N > MaxAccel then break;\r
26859     M := M.fNextMenu;\r
26860   end;\r
26861   if N > 0 then\r
26862   begin\r
26863     C.fAccelTable := CreateAcceleratorTable( AccTab[ 0 ], N );\r
26864     C := C.ParentForm;\r
26865     if C <> nil then\r
26866       C.SupportMnemonics;\r
26867   end;\r
26868   FreeMem( AccTab );\r
26869 end;\r
26871 {$ELSE NEW_MENU_ACCELL}\r
26873 procedure TMenu.SetAccelerator(const Value: TMenuAccelerator);\r
26874 var\r
26875   C: PControl;\r
26876   M: PMenu;\r
26877 begin\r
26878   if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then Exit;\r
26879   FAccelerator := Value;\r
26880   C := FControl;\r
26881   M := @Self;\r
26882   while (C = nil) and (M <> nil) do begin\r
26883     M := M.Parent;\r
26884     if (M <> nil) then\r
26885       C := M.FControl;\r
26886   end;\r
26887   if (C <> nil) then\r
26888     C.SupportMnemonics;\r
26889 end;\r
26891 {$ENDIF NEW_MENU_ACCELL}\r
26893 //[procedure TMenu.SetMenuItemCaption]\r
26894 procedure TMenu.SetMenuItemCaption( const Value: String );\r
26895 var MII: TMenuItemInfo;\r
26896 begin\r
26897   FCaption := Value;\r
26898 {AK}if not (WinVer in [wv95,wvNT]) then\r
26899 {AK}  MII.fMask := $40 {MIIM_STRING}\r
26900 {AK}else begin\r
26901   MII.fMask := MIIM_TYPE;\r
26902   MII.fType := MFT_STRING;\r
26903 {AK}end;\r
26904   //+++++++++++++++++++ to fix turning radio mark to check mark in NT4\r
26905   MII.cch := 0;\r
26906   GetInfo( MII );\r
26907   //------------------------------------------------------------------\r
26908   MII.dwTypeData := PChar( Value );\r
26909   MII.cch := Length( Value );\r
26910   SetInfo( MII );\r
26911 end;\r
26913 //[procedure TMenu.SetMenuBreak]\r
26914 procedure TMenu.SetMenuBreak( Value: TMenuBreak );\r
26915 var MII: TMenuItemInfo;\r
26916 begin\r
26917   if FId = 0 then Exit;\r
26918   if FMenuBreak = Value then Exit;\r
26919   FMenuBreak := Value;\r
26920   FillChar( MII, Sizeof( MII ), 0 );\r
26921   MII.fMask := MIIM_TYPE;\r
26922   MII.dwTypeData := nil;\r
26923   if GetInfo( MII ) then\r
26924   begin\r
26925     MII.fType := MII.fType and not( MFT_MENUBREAK or MFT_MENUBARBREAK ) or\r
26926                  Breaks[ Value ];\r
26927     SetTypeInfo( MII );\r
26928   end;\r
26929 end;\r
26931 //[procedure TMenu.SetVisible]\r
26932 procedure TMenu.SetVisible( Value: Boolean );\r
26933 var I, J: Integer;\r
26934     M: PMenu;\r
26935     Before: Integer;\r
26936     ByPosition: Boolean;\r
26937     MII: TMenuItemInfo;\r
26938 begin\r
26939   if Value then\r
26940     if FParent <> nil then\r
26941       FParent.Visible := TRUE;\r
26942   if Value = FVisible then Exit;\r
26943   FVisible := Value;\r
26944   if (FControl <> nil) and (FControl.fMenuObj = @ Self) then\r
26945   begin\r
26946     FControl.GetWindowHandle;\r
26947     if Value then\r
26948       SetMenu( FControl.fHandle, FHandle )\r
26949     else\r
26950       SetMenu( FControl.fHandle, 0 );\r
26951     Exit;\r
26952   end;\r
26953   if FId = 0 then Exit;\r
26954   if FParent = nil then Exit;\r
26955   if Value then\r
26956   begin // show menu item inserting it again into appropriate position\r
26957     Before := -1;\r
26958     ByPosition := TRUE;\r
26959     I := FParent.FItems.IndexOf( @ Self );\r
26960     for J := I + 1 to FParent.FItems.FCount-1 do\r
26961     begin\r
26962       M := FParent.FItems.Items[ J ];\r
26963       if M.FVisible then\r
26964       begin\r
26965         Before := M.FId;\r
26966         ByPosition := FALSE;\r
26967         break;\r
26968       end;\r
26969     end;\r
26971     FillChar( MII, Sizeof( MII ), 0 );\r
26972     MII.cbSize := MenuStructSize;\r
26973     MII.fMask := MIIM_CHECKMARKS or MIIM_ID or MIIM_STATE or\r
26974                  MIIM_TYPE;\r
26975     MII.fType := Breaks[ FMenuBreak ];\r
26976     MII.fState := FSavedState;\r
26977     MII.wID := FId;\r
26978     MII.dwItemData := DWORD( FData );\r
26980     if not FIsSeparator then\r
26981     begin\r
26982       MII.fType := MII.fType or MFT_STRING;\r
26983       MII.dwTypeData := PChar( FCaption );\r
26984       MII.cch := Length( FCaption );\r
26985     end\r
26986       else\r
26987       MII.fType := MII.fType or MFT_SEPARATOR;\r
26989     if FRadioGroup <> 0 then\r
26990       MII.fType := MII.fType or MFT_RADIOCHECK;\r
26992     if FOwnerDraw then\r
26993       MII.fType := MII.fType or MFT_OWNERDRAW;\r
26995     if FBitmap <> 0 then\r
26996     begin\r
26997       MII.fMask := MII.fMask or MIIM_CHECKMARKS;\r
26998       MII.hbmpUnchecked := FBitmap;\r
26999     end;\r
27001     if FHandle <> 0 then\r
27002     begin\r
27003       MII.fMask := MII.fMask or MIIM_SUBMENU;\r
27004       MII.hSubMenu := FHandle;\r
27005     end;\r
27007     InsertMenuItem( FParent.FHandle, Before, ByPosition,\r
27008                     Windows.PMenuitemInfo( @ MII )^ );\r
27009   end\r
27010     else\r
27011   begin // hide menu item removing it\r
27012     GetState( 0 ); // store menu item state in FSavedState to allow\r
27013                    // changing its state while it is not attached to\r
27014                    // a menu\r
27015     RemoveMenu( TopParent.FHandle, FId, MF_BYCOMMAND );\r
27016   end;\r
27017   if (FControl <> nil) or (FParent <> nil) and (FParent.FControl <> nil) then\r
27018     RedrawFormMenuBar;\r
27019 end;\r
27021 //[procedure TMenu.RadioCheckItem]\r
27022 procedure TMenu.RadioCheckItem;\r
27023 var I, J: Integer;\r
27024     M, First, Last: PMenu;\r
27025 begin\r
27026   if (FParent <> nil) and (FRadioGroup <> 0) then\r
27027   begin\r
27028     I := FParent.FItems.IndexOf( @ Self );\r
27029     if I >= 0 then\r
27030     begin\r
27031       First := @ Self;\r
27032       Last := @ Self;\r
27033       for J := I-1 downto 0 do\r
27034       begin\r
27035         M := FParent.FItems.Items[ J ];\r
27036         if M.FRadioGroup <> FRadioGroup then break;\r
27037         if M.FVisible then\r
27038           First := M;\r
27039       end;\r
27040       for J := I+1 to FParent.FItems.FCount-1 do\r
27041       begin\r
27042         M := FParent.FItems.Items[ J ];\r
27043         if M.FRadioGroup <> FRadioGroup then break;\r
27044         if M.FVisible then\r
27045           Last := M;\r
27046       end;\r
27047       if First <> Last then\r
27048       begin\r
27049         CheckMenuRadioItem( FParent.FHandle, First.FId, Last.FId,\r
27050                             FId, MF_BYCOMMAND {or MF_CHECKED} );\r
27051         Exit;\r
27052       end;\r
27053     end;\r
27054   end;\r
27055   Checked := TRUE;\r
27056 end;\r
27058 //[function TMenu.FillMenuItems]\r
27059 function TMenu.FillMenuItems(AHandle: HMenu; StartIdx: Integer;\r
27060   const Template: array of PChar): Integer;\r
27061 var S, S1: PChar;\r
27062     I: Integer;\r
27063     MII: TMenuItemInfo;\r
27064     Item, PrevItem: PMenu;\r
27065 begin\r
27066   PrevItem := nil;\r
27067   I := StartIdx;\r
27068   while I <= High( Template ) do\r
27069   begin\r
27070     S := Template[ I ];\r
27071     if (S = nil) or (S^ = #0) then break;\r
27072     if S = {$IFDEF F_P}'' +{$ENDIF} ')' then\r
27073     begin\r
27074        Result := I + 1;\r
27075        Exit;\r
27076     end;\r
27078     {-}\r
27079     new( Item, Create );\r
27080     {+}{++}(*Item := PMenu.Create;*){--}\r
27081     Item.FVisible := TRUE;\r
27082     Item.FParent := @ Self;\r
27083     Item.FItems := NewList;\r
27084     FItems.Add( Item );\r
27086     FillChar( MII, Sizeof( MII ), 0 );\r
27087     MII.cbSize := MenuStructSize;\r
27088     MII.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_SUBMENU or MIIM_TYPE;\r
27089     if S <> {$IFDEF F_P}'' +{$ENDIF} '-' then\r
27090     begin\r
27091       if (S^ = {$IFDEF F_P}'' +{$ENDIF} '-') or\r
27092          (S^ = {$IFDEF F_P}'' +{$ENDIF} '+') then\r
27093       begin\r
27094         Item.FIsCheckItem := TRUE;\r
27095         MII.dwItemData := MIDATA_CHECKITEM;\r
27096         if S^ <> {$IFDEF F_P}'' +{$ENDIF} '-' then\r
27097           MII.fState := MII.fState or MFS_CHECKED;\r
27098         Inc( S );\r
27099         if S^ = {$IFDEF F_P}'' +{$ENDIF} '!' then\r
27100         begin\r
27101           MII.fType := MII.fType or MFT_RADIOCHECK;\r
27102           MII.dwItemData := MII.dwItemData or MIDATA_RADIOITEM;\r
27103           Inc( S );\r
27104           if PrevItem <> nil then\r
27105           begin\r
27106             if PrevItem.FRadioGroup <> 0 then\r
27107               Item.FRadioGroup := PrevItem.FRadioGroup;\r
27108           end;\r
27109           if Item.FRadioGroup = 0 then\r
27110             Inc( Item.FRadioGroup );\r
27111           if S^ = {$IFDEF F_P}'' +{$ENDIF} '!' then\r
27112           begin\r
27113             Inc( S );\r
27114             Inc( Item.FRadioGroup );\r
27115           end;\r
27116         end;\r
27117       end;\r
27118       Item.FCaption := S;\r
27119     end\r
27120       else\r
27121     begin\r
27122       Item.FIsSeparator := TRUE;\r
27123       MII.fType := MFT_SEPARATOR;\r
27124       MII.fState := MFS_GRAYED;\r
27125       MII.wID := 0;\r
27126     end;\r
27127     Item.FId := FDynamicMenuID;\r
27128     Inc( FDynamicMenuID );\r
27129     MII.wID := Item.FId;\r
27130     if I <> High( Template ) then            //YS\r
27131     begin                                    //YS\r
27132     S1 := Template[ I + 1 ];\r
27133     if S1 = {$IFDEF F_P}'' +{$ENDIF} '(' then Item.FHandle := CreatePopupMenu;\r
27134     end;                                     //YS\r
27135     MII.hSubMenu := Item.FHandle;\r
27136     MII.dwTypeData := PChar( S );\r
27137     MII.cch := StrLen( S );\r
27138     InsertMenuItem( AHandle, DWORD(-1), True, Windows.PMenuitemInfo( @ MII )^ );\r
27139     if Item.FHandle <> 0 then\r
27140       I := Item.FillMenuItems( Item.FHandle, I + 2, Template )\r
27141     else\r
27142       Inc( I );\r
27143     PrevItem := Item;\r
27144   end;\r
27145   Result := I;\r
27146 end;\r
27148 //[procedure TMenu.AssignEvents]\r
27149 procedure TMenu.AssignEvents(StartIdx: Integer;\r
27150   Events: array of TOnMenuItem);\r
27151 var I: Integer;\r
27152     M: PMenu;\r
27153 begin\r
27154   for I := 0 to High(Events) do\r
27155   begin\r
27156     M := Items[ StartIdx ];\r
27157     if M = nil then break;\r
27158     M.FOnMenuItem := Events[ I ];\r
27159     Inc( StartIdx );\r
27160   end;\r
27161 end;\r
27163 //[procedure TMenu.Popup]\r
27164 procedure TMenu.Popup(X, Y: Integer);\r
27165 begin\r
27166   if Assigned( fOnPopup ) then fOnPopup( @Self );\r
27167   if not FNotPopup then\r
27168     TrackPopupMenu( FHandle, FPopupFlags,\r
27169                     X, Y, 0, FControl.Handle, nil );\r
27170 end;\r
27172 //[procedure TMenu.PopupEx]\r
27173 procedure TMenu.PopupEx( X, Y: Integer );\r
27174 var OldBounds: TRect;\r
27175     WasVisible: Boolean;\r
27176 begin\r
27177   WasVisible := TRUE;\r
27178   if FControl <> nil then\r
27179   begin\r
27180     OldBounds := FControl.BoundsRect;\r
27181     if not FControl.fIsControl then\r
27182     begin\r
27183       WasVisible := FControl.Visible;\r
27184       if not WasVisible then\r
27185         FControl.Top := ScreenHeight + 50;\r
27186       FControl.Show;\r
27187     end;\r
27188   end;\r
27190   // -- by Martin Larsen: -----------------------\\r
27191   FControl.ProcessMessage; // specific for Win9x |\r
27192   //---------------------------------------------/\r
27194   Popup( X, Y );\r
27195   if FControl <> nil then\r
27196   begin\r
27197     if FControl.Top = ScreenHeight + 50 then\r
27198     begin\r
27199       if not WasVisible then\r
27200         FControl.Visible := FALSE;\r
27201       FControl.BoundsRect := OldBounds;\r
27202     end;\r
27203   end;\r
27204 end;\r
27206 //[function TMenu.GetItemChecked]\r
27207 function TMenu.GetItemChecked( Item : Integer ) : Boolean;\r
27208 begin\r
27209   Result := Items[ Item ].Checked;\r
27210 end;\r
27212 //[procedure TMenu.SetItemChecked]\r
27213 procedure TMenu.SetItemChecked( Item : Integer; Value : Boolean );\r
27214 begin\r
27215   Items[ Item ].Checked := Value;\r
27216 end;\r
27218 //[function TMenu.GetMenuItemHandle]\r
27219 function TMenu.GetMenuItemHandle( Idx : Integer ): DWORD;\r
27220 begin\r
27221   Result := Items[ Idx ].FId;\r
27222 end;\r
27224 //[procedure TMenu.RadioCheck]\r
27225 procedure TMenu.RadioCheck( Idx : Integer );\r
27226 begin\r
27227   Items[ Idx ].RadioCheckItem;\r
27228 end;\r
27230 //[function TMenu.GetItemBitmap]\r
27231 function TMenu.GetItemBitmap(Idx: Integer): HBitmap;\r
27232 begin\r
27233   Result := Items[ Idx ].Bitmap;\r
27234 end;\r
27236 //[procedure TMenu.SetItemBitmap]\r
27237 procedure TMenu.SetItemBitmap(Idx: Integer; const Value: HBitmap);\r
27238 begin\r
27239   Items[ Idx ].Bitmap := Value;\r
27240 end;\r
27242 //[procedure TMenu.AssignBitmaps]\r
27243 procedure TMenu.AssignBitmaps(StartIdx: Integer; Bitmaps: array of HBitmap);\r
27244 var I: Integer;\r
27245 begin\r
27246   for I := 0 to High(Bitmaps) do\r
27247     ItemBitmap[ I + StartIdx ] := Bitmaps[ I ];\r
27248 end;\r
27250 //[function TMenu.GetItemText]\r
27251 function TMenu.GetItemText(Idx: Integer): String;\r
27252 begin\r
27253   Result := Items[ Idx ].FCaption;\r
27254 end;\r
27256 //[procedure TMenu.SetItemText]\r
27257 procedure TMenu.SetItemText(Idx: Integer; const Value: String);\r
27258 begin\r
27259   Items[ Idx ].Caption := Value;\r
27260 end;\r
27262 //[function TMenu.GetItemEnabled]\r
27263 function TMenu.GetItemEnabled(Idx: Integer): Boolean;\r
27264 begin\r
27265   Result := Items[ Idx ].Enabled;\r
27266 end;\r
27268 //[procedure TMenu.SetItemEnabled]\r
27269 procedure TMenu.SetItemEnabled(Idx: Integer; const Value: Boolean);\r
27270 begin\r
27271   Items[ Idx ].Enabled := Value;\r
27272 end;\r
27274 //[function TMenu.GetItemVisible]\r
27275 function TMenu.GetItemVisible(Idx: Integer): Boolean;\r
27276 begin\r
27277   Result := Items[ Idx ].Visible;\r
27278 end;\r
27280 //[procedure TMenu.SetItemVisible]\r
27281 procedure TMenu.SetItemVisible(Idx: Integer; const Value: Boolean);\r
27282 begin\r
27283   Items[ Idx ].Visible := Value;\r
27284 end;\r
27286 //[function TMenu.ParentItem]\r
27287 function TMenu.ParentItem( Idx: Integer ): Integer;\r
27288 begin\r
27289   Result := TopParent.IndexOf( Items[ Idx ].FParent );\r
27290 end;\r
27292 //[function TMenu.GetItemAccelerator]\r
27293 function TMenu.GetItemAccelerator(Idx: Integer): TMenuAccelerator;\r
27294 begin\r
27295   Result := Items[ Idx ].Accelerator;\r
27296 end;\r
27298 //[procedure TMenu.SetItemAccelerator]\r
27299 procedure TMenu.SetItemAccelerator(Idx: Integer; const Value: TMenuAccelerator);\r
27300 begin\r
27301   Items[ Idx ].Accelerator := Value;\r
27302 end;\r
27304 //[function TMenu.GetItemSubMenu]\r
27305 function TMenu.GetItemSubMenu( Idx: Integer ): HMenu;\r
27306 begin\r
27307   Result := Items[ Idx ].SubMenu;\r
27308 end;\r
27310 //[function WndProcHelp FORWARD DECLARATION]\r
27311 function WndProcHelp( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
27312 forward;\r
27314 //[procedure TMenu.SetHelpContext]\r
27315 procedure TMenu.SetHelpContext( Value: Integer );\r
27316 var Form, C: PControl;\r
27317 begin\r
27318   if TopParent <> @ Self then Exit;\r
27319   // Help context can not be associated with individual menu items\r
27320   FHelpContext := Value;\r
27321   C := FControl;\r
27322   if C = nil then Exit;\r
27323   Form := C.ParentForm;\r
27324   Form.AttachProc( WndProcHelp );\r
27325   SetMenuContextHelpID( FHandle, Value );\r
27326 end;\r
27328 //[procedure TMenu.SetSubmenu]\r
27329 procedure TMenu.SetSubmenu( Value: HMenu );\r
27330 var MII: TMenuItemInfo;\r
27331 begin\r
27332   MII.fMask := MIIM_SUBMENU;\r
27333   MII.hSubMenu := Value;\r
27334   SetInfo( MII );\r
27335   FHandle := Value;\r
27336 end;\r
27338 //[function WndProcMeasureItem]\r
27339 function WndProcMeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
27340 var MIS: PMeasureItemStruct;\r
27341     M, SM: PMenu;\r
27342     H, I: Integer;\r
27343 begin\r
27344   Result := FALSE;\r
27345   if (Msg.message = WM_MEASUREITEM) and (Msg.wParam = 0) then\r
27346   begin\r
27347     MIS := Pointer( Msg.lParam );\r
27348     if MIS.CtlType = ODT_MENU then\r
27349     begin\r
27350       M := Pointer( Sender.fMenuObj );\r
27351       while M <> nil do\r
27352       begin\r
27353         SM := M.Items[ MIS.itemID ];\r
27354         if SM <> nil then\r
27355         begin\r
27356           Sender.CallDefWndProc( Msg );\r
27357           I := M.IndexOf( SM );\r
27358           if Assigned( SM.OnMeasureItem ) then\r
27359             M := SM;\r
27360           if not Assigned( M.OnMeasureItem ) then\r
27361             Exit;\r
27362           H := M.OnMeasureItem( M, I );\r
27363           if HiWord( H ) <> 0 then\r
27364             MIS.itemWidth := HiWord( H );\r
27365           if LoWord( H ) <> 0 then\r
27366             MIS.itemHeight := LoWord( H );\r
27367           Rslt := 1;\r
27368           Result := TRUE;\r
27369           break;\r
27370         end;\r
27371         M := M.fNextMenu;\r
27372       end;\r
27373     end;\r
27374   end;\r
27375 end;\r
27377 //[procedure TMenu.SetOnMeasureItem]\r
27378 procedure TMenu.SetOnMeasureItem( const Value: TOnMeasureItem );\r
27379 var C: PControl;\r
27380 begin\r
27381   FOnMeasureItem := Value;\r
27382   C := TopParent.FControl;\r
27383   if C <> nil then\r
27384     C.AttachProc( WndProcMeasureItem );\r
27385 end;\r
27387 //[function WndProcDrawItem]\r
27388 function WndProcDrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
27389 type PDrawAction = ^TDrawAction;\r
27390      PDrawState = ^TDrawState;\r
27391 var DIS: PDrawItemStruct;\r
27392     M, SM: PMenu;\r
27393     I: Integer;\r
27394 begin\r
27395   Result := FALSE;\r
27396   if (Msg.message = WM_DRAWITEM) and (Msg.wParam = 0) then\r
27397   begin\r
27398     DIS := Pointer( Msg.lParam );\r
27399     if DIS.CtlType = ODT_MENU then\r
27400     begin\r
27401       M := Pointer( Sender.fMenuObj );\r
27402       while M <> nil do\r
27403       begin\r
27404         SM := M.Items[ DIS.itemID ];\r
27405         if SM <> nil then\r
27406         begin\r
27407           I := M.IndexOf( SM );\r
27408           if Assigned( SM.OnDrawItem ) then\r
27409             M := SM;\r
27410           if Assigned( M.OnDrawItem ) then\r
27411           begin\r
27412             if not M.OnDrawItem( M, DIS.hDC, DIS.rcItem, I,\r
27413                           PDrawAction( @ DIS.itemAction )^,\r
27414                           PDrawState( @ DIS.itemState )^ ) then Exit;\r
27415           end\r
27416             else Exit;\r
27417           Rslt := 1;\r
27418           Result := TRUE;\r
27419           break;\r
27420         end;\r
27421         M := M.fNextMenu;\r
27422       end;\r
27423     end;\r
27424   end;\r
27425 end;\r
27427 //[procedure TMenu.SetOnDrawItem]\r
27428 procedure TMenu.SetOnDrawItem( const Value: TOnDrawItem );\r
27429 var C: PControl;\r
27430 begin\r
27431   FOnDrawItem := Value;\r
27432   C := TopParent.FControl;\r
27433   if C <> nil then\r
27434     C.AttachProc( WndProcDrawItem );\r
27435 end;\r
27437 //[procedure TMenu.SetOwnerDraw]\r
27438 procedure TMenu.SetOwnerDraw( Value: Boolean );\r
27439 const Masks: array[ Boolean ] of DWORD = ( 0, $FFFFFFFF );\r
27440 var MII: TMenuItemInfo;\r
27441 begin\r
27442   FOwnerDraw := Value;\r
27443   FillChar( MII, Sizeof( MII ), 0 );\r
27444   MII.fMask := MIIM_TYPE;\r
27445   MII.dwTypeData := nil;\r
27446   if GetInfo( MII ) then\r
27447   begin\r
27448     MII.fType := MII.fType and not MFT_OWNERDRAW or\r
27449               (MFT_OWNERDRAW and Masks[ Value ]);\r
27450     SetTypeInfo( MII );\r
27451   end;\r
27452 end;\r
27454 //[function TMenu.Insert]\r
27455 function TMenu.Insert(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;\r
27456              Options: TMenuOptions): PMenu;\r
27457 const\r
27458   MenuStateFlags: array[TMenuOption] of Integer = (MFS_DEFAULT, MFS_DISABLED, MFS_CHECKED, 0, 0,\r
27459                   MFS_DISABLED, 0, 0, 0, 0);\r
27460   MenuTypeFlags: array[TMenuOption] of Integer =  (0, 0, 0, 0, MFT_RADIOCHECK, MFT_SEPARATOR, MFT_BITMAP, 0,\r
27461                  MFT_MENUBREAK, MFT_MENUBARBREAK);\r
27462 var M: PMenu;\r
27463     MII: TMenuItemInfo;\r
27464 begin\r
27465   {-}\r
27466   new( Result, Create );\r
27467   {+}{++}(*Result := PMenu.Create;*){--}\r
27468   Result.FVisible := TRUE;\r
27469   Result.FParent := @ Self;\r
27470   Result.FItems := NewList;\r
27471   Result.FIsSeparator := moSeparator in Options;\r
27472   if FHandle = 0 then\r
27473     SetSubMenu( CreatePopupMenu );\r
27474   M := nil;\r
27475   if (InsertBefore >= 0) and (InsertBefore < 4096) then\r
27476   begin\r
27477     M := Items[ InsertBefore ];\r
27478     if M <> nil then\r
27479     begin\r
27480       InsertBefore := M.FId;\r
27481       M.Parent.FItems.Insert( M.Parent.FItems.IndexOf( M ), Result );\r
27482     end;\r
27483   end;\r
27484   if M = nil then\r
27485   begin\r
27486     InsertBefore := -1;\r
27487     FItems.Add( Result );\r
27488   end;\r
27489   Result.FOnMenuItem := Event;\r
27491   FillChar( MII, Sizeof( MII ), 0 );\r
27492   MII.cbSize := MenuStructSize;\r
27493   MII.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_SUBMENU or MIIM_TYPE;\r
27495   MII.fState := MakeFlags( Pointer( @Options ), MenuStateFlags);\r
27496   MII.fType := MakeFlags( Pointer( @Options ), MenuTypeFlags);\r
27497   Result.FId := FDynamicMenuID;\r
27498   Inc( FDynamicMenuID );\r
27499   MII.wID := Result.FId;\r
27500   if moSubMenu in Options\r
27501   then begin\r
27502     Result.FHandle := CreatePopupMenu;\r
27503     MII.hSubMenu := Result.FHandle;\r
27504   end;\r
27505   MII.dwTypeData := ACaption;\r
27506   if not (moBitmap in Options) then MII.cch := StrLen( ACaption );\r
27507   InsertMenuItem( FHandle, InsertBefore, InsertBefore = -1,\r
27508                   Windows.PMenuItemInfo( @ MII )^ );\r
27509   if moBitmap in Options then\r
27510   begin\r
27511     Result.BitmapItem := DWORD( ACaption );\r
27512   end\r
27513   else\r
27514     Result.FCaption := ACaption;\r
27515   RedrawFormMenuBar;\r
27516 end;\r
27518 //[function TMenu.AddItem]\r
27519 function TMenu.AddItem(ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;\r
27520 begin\r
27521   Result := InsertItem( -1, ACaption, Event, Options );\r
27522 end;\r
27524 //[function TMenu.InsertItem]\r
27525 function TMenu.InsertItem( InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;\r
27526   Options: TMenuOptions): Integer;\r
27527 begin\r
27528   Result := InsertItemEx( InsertBefore, ACaption, Event, Options, FALSE );\r
27529 end;\r
27531 //[function TMenu.InsertItemEx]\r
27532 function TMenu.InsertItemEx(InsertBefore: Integer; ACaption: PChar;\r
27533   Event: TOnMenuItem; Options: TMenuOptions; ByPosition: Boolean): Integer;\r
27534 var M: PMenu;\r
27535 begin\r
27536   M := Insert( InsertBefore, ACaption, Event, Options );\r
27537   Result := M.FId;\r
27538 end;\r
27540 //[procedure TMenu.InsertSubMenu]\r
27541 procedure TMenu.InsertSubMenu( SubMenuToInsert: PMenu; InsertBefore: Integer );\r
27542 var AFlags: DWORD;\r
27543     M: PMenu;\r
27544     MII: TMenuItemInfo;\r
27545 begin\r
27546   if SubMenuToInsert.FParent <> nil then\r
27547     SubMenuToInsert := SubMenuToInsert.FParent.RemoveSubMenu( SubMenuToInsert.FId );\r
27548   if SubMenuToInsert = nil then Exit;\r
27550   AFlags := MF_BYPOSITION;\r
27551   M := nil;\r
27552   if (InsertBefore >= 0) and (InsertBefore < 4096) then\r
27553   begin\r
27554     M := Items[ InsertBefore ];\r
27555     if M = nil then\r
27556       InsertBefore := -1\r
27557     else\r
27558       InsertBefore := M.FId;\r
27559   end;\r
27560   if M = nil then\r
27561   begin\r
27562     FItems.Add( SubMenuToInsert );\r
27563     SubMenuToInsert.FParent := @ Self;\r
27564   end\r
27565     else\r
27566   begin\r
27567     M.FParent.FItems.Insert( M.FParent.FItems.IndexOf( M ), SubMenuToInsert );\r
27568     SubMenuToInsert.FParent := M.FParent;\r
27569   end;\r
27571   if InsertBefore > 0 then\r
27572     AFlags := MF_BYCOMMAND;\r
27573   if SubMenuToInsert.FBmpItem <> 0 then\r
27574     InsertMenu( FHandle, InsertBefore, AFlags or MF_BITMAP or MF_POPUP, SubMenuToInsert.FHandle,\r
27575                 PChar( SubMenuToInsert.FBmpItem ) )\r
27576   else\r
27577     InsertMenu( FHandle, InsertBefore, AFlags or MF_STRING or MF_POPUP, SubMenuToInsert.FHandle,\r
27578                 PChar( SubMenuToInsert.Caption ) );\r
27579   if SubMenuToInsert.FId = 0 then\r
27580   begin\r
27581     SubMenuToInsert.FId := FDynamicMenuID;\r
27582     Inc( FDynamicMenuID );\r
27583     MII.cbSize := MenuStructSize;\r
27584     MII.fMask := MIIM_ID;\r
27585     MII.wID := SubMenuToInsert.FId;\r
27586     SetMenuItemInfo( SubMenuToInsert.FParent.FHandle, SubMenuToInsert.FParent.FItems.IndexOf( SubMenuToInsert ),\r
27587                      TRUE, Windows.PMenuItemInfo( @ MII )^ );\r
27588   end;\r
27589   RedrawFormMenuBar;\r
27590 end;\r
27592 //[function TMenu.RemoveSubMenu]\r
27593 function TMenu.RemoveSubMenu( ItemToRemove: Integer ): PMenu;\r
27594 {$IFDEF DEBUG_MENU}var OK: Boolean; {$ENDIF}\r
27595 begin\r
27596   Result := Items[ ItemToRemove ];\r
27597   if Result = nil then Exit;\r
27598   if Result.FParent <> nil then\r
27599     {$IFDEF DEBUG_MENU} OK := {$ENDIF}\r
27600     RemoveMenu( Result.FParent.FHandle, Result.FId, MF_BYCOMMAND )\r
27601   else\r
27602     {$IFDEF DEBUG_MENU} OK := {$ENDIF}\r
27603     RemoveMenu( FHandle, Result.FId, MF_BYCOMMAND );\r
27604   {$IFDEF DEBUG_MENU}\r
27605   if not OK then\r
27606     ShowMessage( 'Error removing menu: ' + Int2Str( GetLastError ) + ' - ' +\r
27607                  SysErrorMessage( GetLastError ) );\r
27608   {$ENDIF}\r
27609   if Count = 0 then\r
27610   begin\r
27611     Result.Free;\r
27612     Result := nil;\r
27613   end;\r
27614   RedrawFormMenuBar;\r
27615 end;\r
27617 //[procedure ClearText]\r
27618 procedure ClearText( Sender: PControl );\r
27619 begin\r
27620   Sender.Caption := '';\r
27621 end;\r
27623 //[procedure ClearListbox]\r
27624 procedure ClearListbox( Sender: PControl );\r
27625 begin\r
27626   Sender.Perform( LB_RESETCONTENT, 0, 0 );\r
27627 end;\r
27629 //[procedure ClearCombobox]\r
27630 procedure ClearCombobox( Sender: PControl );\r
27631 begin\r
27632   Sender.Perform( CB_RESETCONTENT, 0, 0 );\r
27633 end;\r
27635 //[procedure ClearListView]\r
27636 procedure ClearListView( Sender: PControl );\r
27637 begin\r
27638   Sender.Perform( LVM_DELETEALLITEMS, 0, 0 );\r
27639 end;\r
27641 //[procedure ClearToolbar]\r
27642 procedure ClearToolbar( Sender: PControl );\r
27643 begin\r
27644   while Sender.TBButtonCount > 0 do\r
27645     Sender.TBDeleteButton( Sender.TBIndex2Item( 0 ) );\r
27646   Sender.Perform( TB_SETBITMAPSIZE, 0, 0 );\r
27647 end;\r
27649 { -- Constructor of canvas -- }\r
27650 //[function NewCanvas]\r
27651 function NewCanvas( DC: HDC ): PCanvas;\r
27652 begin\r
27653   {-}\r
27654   New( Result, Create );\r
27655   {+}\r
27656   {++}(*\r
27657   Result := PCanvas.Create;\r
27658   *){--}\r
27659   Result.ModeCopy := cmSrcCopy;\r
27660   if DC <> 0 then\r
27661   begin\r
27662     Result.SetHandle( DC );\r
27663     //Result.fIsPaintDC := True; // If Canvas will be destroyed, DC will not be deleted\r
27664   end;\r
27665 end;\r
27666 //[END NewCanvas]\r
27668 { -- Contructors of controls -- }\r
27670 {$IFDEF ASM_VERSION}\r
27671 //[FUNCTION _NewTControl]\r
27672 function _NewTControl( AParent: PControl ): PControl;\r
27673 begin\r
27674   New( Result, CreateParented( AParent ) );\r
27675 end;\r
27676 //[END _NewTControl]\r
27678 //[function _NewWindowed]\r
27679 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;\r
27680 asm\r
27681         PUSH     EBX\r
27682         PUSH     ESI\r
27683         PUSH     EDI\r
27685         PUSH     ECX // Ctl3D\r
27686         PUSH     EDX // ControlClassName\r
27688         MOV      ESI, EAX // ESI = AParent\r
27689         CALL     _NewTControl\r
27690         XCHG     EBX, EAX // EBX = Result\r
27691         POP      [EBX].TControl.fControlClassName\r
27692         INC      [EBX].TControl.fWindowed\r
27694         INC      EAX\r
27695         POP      EDX // DL = parameter Ctl3D\r
27696         TEST     ESI, ESI\r
27697         JZ       @@no_parent\r
27699         LEA      ESI, [ESI].TControl.fWndProcResizeFlicks\r
27700         LEA      EDI, [EBX].TControl.fWndProcResizeFlicks\r
27701         MOVSD    // fWndProcResizeFlicks\r
27702         MOVSD    // fGotoControl\r
27703         //MOVSW    // fDoubleBuffered, fTransparent\r
27704         LODSB    // fCtl3Dchild\r
27705         STOSB\r
27706         DEC      AL\r
27707         LODSB    // fCtl3D\r
27708         JZ       @@passed3D\r
27709         XOR      EDX, EDX\r
27710 @@passed3D:\r
27711         XCHG     EAX, EDX\r
27712         STOSB    // fCtl3D\r
27714         MOVSD    // fTextColor\r
27715         LODSD\r
27716         XCHG     EDX, EAX\r
27717         XOR      EAX, EAX\r
27718         PUSH     EDX\r
27719         CALL     TGraphicTool.Assign\r
27720         STOSD    // fFont\r
27721         POP      EDX\r
27722         XCHG     ECX, EAX\r
27723         JECXZ    @@no_font\r
27724         MOV      [ECX].TGraphicTool.fParentGDITool, EDX\r
27725         MOV      [ECX].TGraphicTool.fOnChange.TMethod.Code, offset[TControl.FontChanged]\r
27726         MOV      [ECX].TGraphicTool.fOnChange.TMethod.Data, EBX\r
27727         MOV      EAX, EBX\r
27728         MOV      EDX, ECX\r
27729         CALL     TControl.FontChanged\r
27730 @@no_font:\r
27732         MOVSD    // fColor\r
27733         LODSD\r
27734         XCHG     EDX, EAX\r
27735         XOR      EAX, EAX\r
27736         PUSH     EDX\r
27737         CALL     TGraphicTool.Assign\r
27738         STOSD    // fBrush\r
27739         POP      EDX\r
27740         XCHG     ECX, EAX\r
27741         JECXZ    @@no_brush\r
27742         MOV      [ECX].TGraphicTool.fParentGDITool, EDX\r
27743         MOV      [ECX].TGraphicTool.fOnChange.TMethod.Code, offset[TControl.BrushChanged]\r
27744         MOV      [ECX].TGraphicTool.fOnChange.TMethod.Data, EBX\r
27745         MOV      EAX, EBX\r
27746         MOV      EDX, ECX\r
27747         CALL     TControl.BrushChanged\r
27748 @@no_brush:\r
27750         LODSD\r
27751         STOSD    // fMargin\r
27752         STOSD    // fBoundsRect.Left\r
27753         PUSH     EAX\r
27754         ADD      EAX, [ESI+16] // AParent.fClientTop\r
27755         STOSD    // fBoundsRect.Top\r
27756         POP      EAX\r
27757         ADD      EAX, 64\r
27758         STOSD    // fBoundsRect.Right\r
27759         STOSD    // fBoundsRect.Bottom\r
27761 @@no_parent:\r
27762         XCHG     EAX, EBX\r
27763         //DEC      byte ptr [EAX].TControl.fAlphaBlend\r
27764         //INC      byte ptr [EAX].TControl.fEraseUpdRgn\r
27765         POP      EDI\r
27766         POP      ESI\r
27767         POP      EBX\r
27768 end;\r
27769 {$ELSE ASM_VERSION} //Pascal\r
27770 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;\r
27771 begin\r
27772   {-}\r
27773   New( Result, CreateParented( AParent ) );\r
27774   {+}{++}(*Result := PControl.CreateParented( AParent );*){--}\r
27775   Result.fControlClassName := ControlClassName;\r
27776   if AParent <> nil then\r
27777   begin\r
27778      Result.fWndProcResizeFlicks := AParent.fWndProcResizeFlicks;\r
27779      Result.fGotoControl := AParent.fGotoControl;\r
27780      //Result.fDoubleBuffered := AParent.fDoubleBuffered;\r
27781      //Result.fTransparent := AParent.fTransparent;\r
27782      Result.fCtl3Dchild := AParent.fCtl3Dchild;\r
27783      if AParent.fCtl3Dchild then\r
27784        Result.fCtl3D := Ctl3D\r
27785      else\r
27786        Result.fCtl3D := False;\r
27787      Result.fMargin := AParent.fMargin;\r
27788      with Result.fBoundsRect do\r
27789      begin\r
27790        Left := AParent.fMargin + AParent.fClientLeft;\r
27791        Top  := AParent.fMargin + AParent.fClientTop;\r
27792        Right := Left + 64;\r
27793        Bottom := Top + 64;\r
27794      end;\r
27795      Result.fTextColor := AParent.fTextColor;\r
27796      Result.fFont := Result.fFont.Assign( AParent.fFont );\r
27797      if Result.fFont <> nil then\r
27798      begin\r
27799        Result.fFont.fParentGDITool := AParent.fFont;\r
27800        Result.fFont.fOnChange := Result.FontChanged;\r
27801        Result.FontChanged( Result.fFont );\r
27802      end;\r
27803      Result.fColor := AParent.fColor;\r
27804      Result.fBrush := Result.fBrush.Assign( AParent.fBrush );\r
27805      if Result.fBrush <> nil then\r
27806      begin\r
27807        Result.fBrush.fParentGDITool := AParent.fBrush;\r
27808        Result.fBrush.fOnChange := Result.BrushChanged;\r
27809        Result.BrushChanged( Result.fBrush );\r
27810      end;\r
27811   end;\r
27812   //Result.fAlphaBlend := 255;\r
27813   //Result.fEraseUpdRgn := TRUE;\r
27814 end;\r
27815 //[END _NewWindowed]\r
27816 {$ENDIF ASM_VERSION}\r
27818 //===================== Form ========================//\r
27820 {$IFDEF USE_CONSTRUCTORS}\r
27821 //[function NewForm]\r
27822 function NewForm( AParent: PControl; const Caption: String ): PControl;\r
27823 begin\r
27824   new( Result, CreateForm( AParent, Caption ) );\r
27825 end;\r
27826 //[END NewForm]\r
27827 {$ELSE not_USE_CONSTRUCTORS}\r
27829 //[FUNCTION NewForm]\r
27830 {$IFDEF ASM_VERSION}\r
27831 function NewForm( AParent: PControl; const Caption: String ): PControl;\r
27832 const FormClass: array[ 0..4 ] of Char = ( 'F', 'o', 'r', 'm', #0 );\r
27833 asm\r
27834         PUSH     EBX\r
27835         PUSH     EDX\r
27836         MOV      EDX, offset[FormClass]\r
27837         MOV      CL, 1\r
27838         CALL     _NewWindowed\r
27839         MOV      EBX, EAX\r
27840         INC      [EBX].TControl.fSizeGrip\r
27841         OR       byte ptr [EBX].TControl.fClsStyle, CS_DBLCLKS\r
27842         MOV      EDX, offset[WndProcForm]\r
27843         CALL     TControl.AttachProc\r
27844         MOV      EDX, offset[WndProcDoEraseBkgnd]\r
27845         MOV      EAX, EBX\r
27846         CALL     TControl.AttachProc\r
27847         POP      EDX\r
27848         MOV      EAX, EBX\r
27849         CALL     TControl.SetCaption\r
27850         INC      [EBX].TControl.fSizeGrip\r
27851         INC      [EBX].TControl.fIsForm\r
27852         XCHG     EAX, EBX\r
27853         POP      EBX\r
27854 end;\r
27855 {$ELSE ASM_VERSION} //Pascal\r
27856 function NewForm( AParent: PControl; const Caption: String ): PControl;\r
27857 begin\r
27858   Result := _NewWindowed( AParent, 'Form', True );\r
27859   Result.fClsStyle := Result.fClsStyle or CS_DBLCLKS;\r
27860   Result.AttachProc( WndProcForm );\r
27861   Result.AttachProc( WndProcDoEraseBkgnd );\r
27862   Result.Caption := Caption;\r
27863   Result.fSizeGrip := TRUE;\r
27864   Result.fIsForm := TRUE;\r
27865 end;\r
27866 {$ENDIF ASM_VERSION}\r
27867 //[END NewForm]\r
27869 {$ENDIF USE_CONSTRUCTORS}\r
27871 //===================== Applet button ========================//\r
27873 //{$DEFINE WNDPROCAPP_USED}\r
27874 {$IFDEF WNDPROCAPP_USED}\r
27876 //[FUNCTION WndProcApp]\r
27877 {$IFDEF ASM_VERSION}\r
27878   {$IFDEF WNDPROCAPP_ASM_USED}\r
27879   function WndProcApp(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
27880   asm\r
27881           CMP      word ptr [EDX].TMsg.message, WM_SETFOCUS\r
27882           JNZ      @@chk_CLOSE\r
27883           MOV      ECX, [EAX].TControl.FCurrentControl\r
27884           JECXZ    @@ret_false\r
27885           XCHG     EAX, ECX\r
27886           PUSH     EAX\r
27887           CALL     CallTControlCreateWindow\r
27888           POP      EAX\r
27889           PUSH     [EAX].TControl.fHandle\r
27890           CALL     SetFocus\r
27891           MOV      AL, 1\r
27892           RET\r
27893   @@chk_CLOSE:\r
27894           CMP      word ptr [EDX].TMsg.message, WM_SYSCOMMAND\r
27895           JNZ      @@ret_false\r
27896           MOV      EDX, dword ptr [EDX].TMsg.wParam\r
27897           AND      DX, $FFF0\r
27898           CMP      DX, SC_CLOSE\r
27899           JNZ      @@ret_false\r
27900           PUSH     ECX\r
27901           MOV      ECX, [EAX].TControl.fChildren\r
27902           JECXZ    @@ret_false1\r
27903           XCHG     EAX, ECX\r
27904           MOV      ECX, [EAX].TList.fCount\r
27905           JECXZ    @@ret_false1\r
27906           MOV      EAX, [EAX].TList.fItems\r
27907           MOV      ECX, dword ptr [EAX]\r
27908           JECXZ    @@ret_false1\r
27909           XCHG     EAX, ECX\r
27910           PUSH     EAX\r
27911           CALL     TControl.IsMainWindow\r
27912           TEST     EAX, EAX\r
27913           POP      EAX\r
27914           JZ       @@ret_false1\r
27915           CALL     TControl.Close\r
27916           POP      ECX\r
27917           XOR      EAX, EAX\r
27918           MOV      dword ptr [ECX], EAX\r
27919           INC      EAX\r
27920           JMP      @@exit     \r
27921   @@ret_false1:\r
27922           POP      ECX\r
27923   @@ret_false:\r
27924           XOR      EAX, EAX\r
27925   @@exit:\r
27926   end;\r
27927   {$ENDIF}\r
27928 {$ELSE ASM_VERSION} //Pascal\r
27929 function WndProcApp(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
27930 begin\r
27931   Result := False;\r
27932   case Msg.message of\r
27933   WM_SETFOCUS:\r
27934     {$IFDEF NEW_MODAL}\r
27935     if Self_.fModalForm <> nil then\r
27936       SetFocus( Self_.fModalForm.fHandle )\r
27937     else if ( Self_.FCurrentControl <> nil ) and not\r
27938             ( Self_.fCurrentControl.IsForm xor Self_.fIsApplet ) then\r
27939     {$ELSE not_NEW_MODAL}\r
27940     if Self_.FCurrentControl <> nil then\r
27941     {$ENDIF NEW_MODAL}\r
27942     begin\r
27943       Self_.FCurrentControl.CreateWindow; //virtual!!!\r
27944       SetFocus( Self_.FCurrentControl.fHandle );\r
27945       Result := True;\r
27946     end;\r
27947   WM_SYSCOMMAND:\r
27948     if Msg.wParam and $FFF0 = SC_CLOSE then\r
27949     if (Self_.fChildren <> nil) and (Self_.fChildren.fCount > 0) and\r
27950        PControl( Self_.fChildren.fItems[ 0 ] ).IsMainWindow then\r
27951     begin\r
27952       PControl( Self_.fChildren.fItems[ 0 ] ).Close;\r
27953       Rslt := 0;\r
27954       Result := TRUE;\r
27955     end;\r
27956   end;\r
27957 end;\r
27958 {$ENDIF ASM_VERSION}\r
27959 //[END WndProcApp]\r
27961 {$ENDIF WNDPROCAPP_USED}\r
27963 {$IFDEF USE_CONSTRUCTORS}\r
27964 {$DEFINE CREATEAPPBUTTON_USED}\r
27965 //[function NewApplet]\r
27966 function NewApplet( const Caption: String ): PControl;\r
27967 begin\r
27968   new( Result, CreateApplet( Caption ) );\r
27969 end;\r
27970 //[END NewApplet]\r
27971 {$ELSE not_USE_CONSTRUCTORS}\r
27973 //[FUNCTION NewApplet]\r
27974 {$IFDEF ASM_VERSION}\r
27975 function NewApplet( const Caption: String ): PControl;\r
27976 const AppClass: array[ 0..3 ] of Char = ( 'A', 'p', 'p', #0 );\r
27977 asm\r
27978         XOR      ECX, ECX\r
27979         INC      ECX\r
27980         MOV      [AppButtonUsed], CL\r
27981         PUSH     EAX\r
27982         MOV      EDX, offset[AppClass]\r
27983         XOR      EAX, EAX\r
27984         CALL     _NewWindowed\r
27985         INC      [EAX].TControl.FIsApplet\r
27986         MOV      word ptr [EAX].TControl.fStyle + 2, $90CA //WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX or WS_CAPTION\r
27987         MOV      byte ptr [EAX].TControl.fExStyle + 2, WS_EX_APPWINDOW shr 16 // WS_EX_APPWINDOW = $40000\r
27988         CALL     @@newapp1\r
27990         // BODY of CreateAppButton here:\r
27991         PUSH     ESI\r
27992         PUSH     0\r
27993         PUSH     [EAX].TControl.fHandle\r
27994         CALL     GetSystemMenu\r
27995         MOV      ESI, offset[DeleteMenu]\r
27997         XCHG     ECX, EAX\r
27998         MOV      EAX, SC_MAXIMIZE\r
27999         CDQ\r
28001         PUSH     EDX\r
28002         PUSH     EAX\r
28003         PUSH     ECX\r
28005         PUSH     EDX\r
28006         {$IFDEF PARANOIA}\r
28007         DB $2C, $20\r
28008         {$ELSE}\r
28009         SUB      AL, $20  // SC_MOVE\r
28010         {$ENDIF}\r
28011         PUSH     EAX\r
28012         PUSH     ECX\r
28014         PUSH     EDX\r
28015         {$IFDEF PARANOIA}\r
28016         DB $2C, $10\r
28017         {$ELSE}\r
28018         SUB      AL, $10  // SC_SIZE\r
28019         {$ENDIF}\r
28020         PUSH     EAX\r
28021         PUSH     ECX\r
28023         PUSH     1    // MF_GRAYED or MF_BYCOMMAND\r
28024         MOV      AX, SC_RESTORE\r
28025         PUSH     EAX\r
28026         PUSH     ECX\r
28028         CALL     EnableMenuItem\r
28029         CALL     ESI\r
28030         CALL     ESI\r
28031         CALL     ESI\r
28032         POP      ESI\r
28033 @@ret_false:\r
28034         XOR      EAX, EAX\r
28035         RET\r
28037 @@chk_CLOSE:\r
28038           CMP      word ptr [EDX].TMsg.message, WM_SYSCOMMAND\r
28039           JNZ      @@ret_false\r
28040           MOV      EDX, dword ptr [EDX].TMsg.wParam\r
28041           AND      DX, $FFF0\r
28042           CMP      DX, SC_CLOSE\r
28043           JNZ      @@ret_false\r
28044           PUSH     ECX\r
28045           MOV      ECX, [EAX].TControl.fChildren\r
28046           JECXZ    @@ret_false1\r
28047           XCHG     EAX, ECX\r
28048           MOV      ECX, [EAX].TList.fCount\r
28049           JECXZ    @@ret_false1\r
28050           MOV      EAX, [EAX].TList.fItems\r
28051           MOV      ECX, dword ptr [EAX]\r
28052           JECXZ    @@ret_false1\r
28053           XCHG     EAX, ECX\r
28054           PUSH     EAX\r
28055           CALL     TControl.IsMainWindow\r
28056           TEST     EAX, EAX\r
28057           POP      EAX\r
28058           JZ       @@ret_false1\r
28059           CALL     TControl.Close\r
28060           POP      ECX\r
28061           XOR      EAX, EAX\r
28062           MOV      dword ptr [ECX], EAX\r
28063           INC      EAX\r
28064           RET\r
28065   @@ret_false1:\r
28066           POP      ECX\r
28067           JMP      @@ret_false\r
28069 @@newapp1:\r
28070         //MOV      [EAX].TControl.FCreateWndExt, offset[CreateAppButton]\r
28071         POP      [EAX].TControl.FCreateWndExt\r
28072         PUSH     EAX\r
28073         CALL     @@newapp2\r
28075         // BODY of WndProcApp here:\r
28076         CMP      word ptr [EDX].TMsg.message, WM_SETFOCUS\r
28077         JNZ      @@chk_CLOSE\r
28078         MOV      ECX, [EAX].TControl.FCurrentControl\r
28079         JECXZ    @@ret_false\r
28080         XCHG     EAX, ECX\r
28082         PUSH     EAX\r
28083         CALL     CallTControlCreateWindow\r
28084         POP      EAX\r
28085         PUSH     [EAX].TControl.fHandle\r
28087         CALL     SetFocus\r
28088         MOV      AL, 1\r
28089         RET\r
28091 @@newapp2:\r
28092         POP      EDX\r
28093         CALL     TControl.AttachProc\r
28094         POP      EAX\r
28095         POP      EDX\r
28096         PUSH     EAX\r
28097         CALL     TControl.SetCaption\r
28098         POP      EAX\r
28099 end;\r
28101 {$ELSE ASM_VERSION} //Pascal\r
28103 //[procedure CreateAppButton]\r
28104 procedure CreateAppButton( App: PControl );\r
28105 var M: HMenu;\r
28106 begin\r
28107   M := GetSystemMenu( App.fHandle, False );\r
28108   DeleteMenu( M, SC_MAXIMIZE, MF_BYCOMMAND );\r
28109   DeleteMenu( M, SC_MOVE, MF_BYCOMMAND );\r
28110   DeleteMenu( M, SC_SIZE, MF_BYCOMMAND );\r
28111   EnableMenuItem( M, SC_RESTORE, MF_GRAYED or MF_BYCOMMAND );\r
28112 end;\r
28114 //[function NewApplet]\r
28115 function NewApplet( const Caption: String ): PControl;\r
28116 begin\r
28117   AppButtonUsed := True;\r
28118   Result := _NewWindowed( nil, 'App', True );\r
28119   Result.FIsApplet := TRUE;\r
28120   Result.fStyle := WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX or WS_CAPTION;\r
28121   Result.fExStyle := WS_EX_APPWINDOW;\r
28122   Result.FCreateWndExt := CreateAppButton;\r
28123   Result.AttachProc( WndProcApp );\r
28124   Result.Caption := Caption;\r
28125 end;\r
28126 {$ENDIF ASM_VERSION}\r
28127 //[END NewApplet]\r
28128 {$ENDIF USE_CONSTRUCTORS}\r
28130 {$IFDEF CREATEAPPBUTTON_USED}\r
28131 procedure CreateAppButton( App: PControl );\r
28132 asm\r
28133   {$IFDEF F_P}\r
28134         MOV      EAX, [App]\r
28135   {$ENDIF F_P}\r
28136         PUSH     ESI\r
28137         PUSH     0\r
28138         PUSH     [EAX].TControl.fHandle\r
28139         CALL     GetSystemMenu\r
28140         MOV      ESI, offset[DeleteMenu]\r
28142         XCHG     ECX, EAX\r
28143         MOV      EAX, SC_MAXIMIZE\r
28144         CDQ\r
28146         PUSH     EDX\r
28147         PUSH     EAX\r
28148         PUSH     ECX\r
28150         PUSH     EDX\r
28151         {$IFDEF PARANOIA}\r
28152         DB $2C, $20\r
28153         {$ELSE}\r
28154         SUB      AL, $20  // SC_MOVE\r
28155         {$ENDIF}\r
28156         PUSH     EAX\r
28157         PUSH     ECX\r
28159         PUSH     EDX\r
28160         {$IFDEF PARANOIA}\r
28161         DB $2C, $10\r
28162         {$ELSE}\r
28163         SUB      AL, $10  // SC_SIZE\r
28164         {$ENDIF}\r
28165         PUSH     EAX\r
28166         PUSH     ECX\r
28168         PUSH     1    // MF_GRAYED or MF_BYCOMMAND\r
28169         MOV      AX, SC_RESTORE\r
28170         PUSH     EAX\r
28171         PUSH     ECX\r
28173         CALL     EnableMenuItem\r
28174         CALL     ESI\r
28175         CALL     ESI\r
28176         CALL     ESI\r
28177         POP      ESI\r
28178 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};\r
28179 {$ENDIF CREATEAPPBUTTON_USED}\r
28181 var CtlIdCount: WORD = $8000;\r
28183 {-}\r
28184 {$IFNDEF ASM_VERSION}\r
28185   //{$DEFINE CREATEPARAMS2_USED}\r
28186 {$ENDIF}\r
28187 {$IFDEF USE_CONSTRUCTORS}\r
28188   //{$DEFINE CREATEPARAMS2_USED}\r
28189 {$ENDIF}\r
28190 {+}\r
28192 {$IFDEF CREATEPARAMS2_USED} // seems not needed more\r
28193 //[procedure CreateParams2]\r
28194 procedure CreateParams2( Self_: PControl; var Params: TCreateParams);\r
28195 begin\r
28196   Self_.CreateSubclass( Params, Self_.fControlClassName );\r
28197 end;\r
28198 {$ENDIF}\r
28200 //[FUNCTION _NewControl]\r
28201 {$IFDEF ASM_VERSION}\r
28202 function _NewControl( AParent: PControl; ControlClassName: PChar;\r
28203                       Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;\r
28204 const szActions = sizeof(TCommandActions);\r
28205 asm\r
28206         PUSH     EBX\r
28207         PUSH     EAX  // push AParent\r
28208         PUSH     ECX  // push Style\r
28209         MOVZX    ECX, Ctl3D\r
28210         CALL     _NewWindowed\r
28211         XCHG     EBX, EAX\r
28212         INC      [EBX].TControl.fIsControl\r
28213         INC      [EBX].TControl.fVerticalAlign\r
28214         MOV      EAX, Actions\r
28215         TEST     EAX, EAX\r
28216         JZ       @@noActions\r
28217         LEA      EDX, [EBX].TControl.fCommandActions\r
28218         XOR      ECX, ECX\r
28219         MOV      CL, szActions\r
28220         CALL     System.Move\r
28221 @@noActions:\r
28222         POP      EDX  // pop Style\r
28223         OR       EDX, WS_CLIPSIBLINGS or WS_CLIPCHILDREN\r
28224         MOV      byte ptr [EBX].TControl.fLookTabKeys, $0F\r
28225         CMP      [EBX].TControl.fCtl3D, 0\r
28226         JZ       @@noCtl3D\r
28227         AND      EDX, not WS_BORDER\r
28228         OR       byte ptr [EBX].TControl.fExStyle + 1, WS_EX_CLIENTEDGE shr 8\r
28229 @@noCtl3D:\r
28230         MOV      [EBX].TControl.fStyle, EDX\r
28231         TEST     EDX, WS_VISIBLE\r
28232         SETNZ    AL\r
28233         MOV      [EBX].TControl.fVisible, AL\r
28234         TEST     EDX, WS_TABSTOP\r
28235         POP      ECX // pop AParent\r
28236         PUSHFD\r
28237         JECXZ    @@noParent\r
28238         MOV      EAX, [ECX].TControl.fCursor\r
28239         MOV      [EBX].TControl.fCursor, EAX\r
28240         XCHG     EAX, ECX\r
28241         CALL     TControl.ParentForm\r
28242         XCHG     ECX, EAX\r
28243         JECXZ    @@noParent\r
28244         INC      [ECX].TControl.fTabOrder\r
28245         MOV      EDX, [ECX].TControl.fTabOrder\r
28246         MOV      [EBX].TControl.fTabOrder, EDX\r
28247 @@noParent:\r
28248         POPFD\r
28249         JZ       @@noTabStop\r
28250         INC      [EBX].TControl.fTabstop\r
28251         JECXZ    @@noTabstop\r
28252         XCHG     EAX, ECX\r
28253         MOV      ECX, [EAX].TControl.FCurrentControl\r
28254         INC      ECX\r
28255         LOOP     @@noTabStop\r
28256         MOV      [EAX].TControl.FCurrentControl, EBX\r
28257 @@noTabStop:\r
28258         MOVZX    EDX, [CtlIdCount]\r
28259         INC      [CtlIdCount]\r
28260         MOV      [EBX].TControl.fMenu, EDX\r
28261         MOV      EDX, offset[WndProcCtrl]\r
28262         MOV      EAX, EBX\r
28263         CALL     TControl.AttachProc\r
28264         XCHG     EAX, EBX\r
28265         POP      EBX\r
28266 end;\r
28267 {$ELSE ASM_VERSION} //Pascal\r
28268 function _NewControl( AParent: PControl; ControlClassName: PChar;\r
28269                       Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;\r
28270 var Form: PControl;\r
28271 begin\r
28272   Result := _NewWindowed( AParent, ControlClassName, Ctl3D );\r
28273   if Actions <> nil then\r
28274     Result.fCommandActions := Actions^;\r
28275   Result.fIsControl := True;\r
28276   Result.fStyle := Style or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;\r
28277   Result.fVerticalAlign := vaTop;\r
28278   Result.fVisible := (Style and WS_VISIBLE) <> 0;\r
28279   Result.fTabstop := (Style and WS_TABSTOP) <> 0;\r
28280   if (AParent <> nil) then\r
28281   begin\r
28282     Inc( AParent.ParentForm.fTabOrder );\r
28283     Result.fTabOrder := AParent.ParentForm.fTabOrder;\r
28284     Result.fCursor := AParent.fCursor;\r
28285   end;\r
28286   Result.fLookTabKeys := [ tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn ];\r
28287   if Result.fCtl3D then\r
28288   begin\r
28289     Result.fStyle := Result.fStyle and not WS_BORDER;\r
28290     Result.fExStyle := Result.fExStyle or WS_EX_CLIENTEDGE;\r
28291   end;\r
28292   if (Style and WS_TABSTOP) <> 0 then\r
28293   begin\r
28294     Form := Result.ParentForm;\r
28295     if Form <> nil then\r
28296     if Form.FCurrentControl = nil then\r
28297        Form.FCurrentControl := Result;\r
28298   end;\r
28299   //Result.fCreateParamsExt := CreateParams2;\r
28300   Result.fMenu := CtlIdCount;\r
28301   Inc( CtlIdCount );\r
28302   Result.AttachProc( WndProcCtrl );\r
28303 end;\r
28304 {$ENDIF ASM_VERSION}\r
28305 //[END _NewControl]\r
28307 //===================== Button ========================//\r
28309 //[function TControl.SetButtonIcon]\r
28310 function TControl.SetButtonIcon(aIcon: HIcon): PControl;\r
28311 var PrevImg: THandle;\r
28312 begin\r
28313   Style := Style or BS_ICON;\r
28314   PrevImg := Perform( BM_SETIMAGE, IMAGE_ICON, aIcon );\r
28315   if PrevImg <> 0 then\r
28316     DeleteObject( PrevImg );\r
28317   Result := @ Self;\r
28318 end;\r
28320 //[function TControl.SetButtonBitmap]\r
28321 function TControl.SetButtonBitmap(aBmp: HBitmap): PControl;\r
28322 var PrevImg: THandle;\r
28323 begin\r
28324   Style := Style or BS_BITMAP;\r
28325   PrevImg := Perform( BM_SETIMAGE, IMAGE_BITMAP, aBmp );\r
28326   if PrevImg <> 0 then\r
28327     DeleteObject( PrevImg );\r
28328   Result := @ Self;\r
28329 end;\r
28331 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}\r
28332 //[function WndProcBtnReturnClick]\r
28333 function WndProcBtnReturnClick( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
28334 begin\r
28335   Result := FALSE;\r
28336   if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP) or\r
28337       (Msg.message = WM_CHAR)) and (Msg.wParam = 13) then\r
28338     Msg.wParam := 32;\r
28339 end;\r
28340 {$ENDIF}\r
28342 {$IFDEF USE_CONSTRUCTORS}\r
28343 //[function NewButton]\r
28344 function NewButton( AParent: PControl; const Caption: String ): PControl;\r
28345 begin\r
28346   new( Result, CreateButton( AParent, Caption ) );\r
28347 end;\r
28348 {$ELSE USE_CONSTRUCTORS}\r
28350 {$IFDEF ASM_VERSION}\r
28351 const ButtonClass: array[ 0..6 ] of Char = ( 'B','U','T','T','O','N',#0 );\r
28352 {$ENDIF ASM_VERSION}\r
28354 //[FUNCTION NewButton]\r
28355 {$IFDEF ASM_VERSION}\r
28356 function NewButton( AParent: PControl; const Caption: String ): PControl;\r
28357 const szActions = sizeof(TCommandActions);\r
28358 asm\r
28359         PUSH     EDX\r
28361         PUSH     0\r
28362         PUSH     offset[ButtonActions]\r
28364         MOV      EDX, offset[ButtonClass]\r
28365         MOV      ECX, WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or WS_TABSTOP\r
28366         CALL     _NewControl\r
28367         INC      [EAX].TControl.fIgnoreDefault\r
28368         MOV      EDX, [EAX].TControl.fBoundsRect.Top\r
28369         ADD      EDX, 22\r
28370         MOV      [EAX].TControl.fBoundsRect.Bottom, EDX\r
28371         MOV      [EAX].TControl.fTextAlign, taCenter\r
28372         INC      [EAX].TControl.fIsButton\r
28374         POP      EDX\r
28375         PUSH     EAX\r
28376         CALL     TControl.SetCaption\r
28377         POP      EAX\r
28378         {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}\r
28379         PUSH     EAX\r
28380         MOV      EDX, offset[WndProcBtnReturnClick]\r
28381         CALL     TControl.AttachProc\r
28382         POP      EAX\r
28383         {$ENDIF}\r
28384 end;\r
28385 {$ELSE ASM_VERSION} //Pascal\r
28386 function NewButton( AParent: PControl; const Caption: String ): PControl;\r
28387 begin\r
28388   Result := _NewControl( AParent, 'BUTTON',\r
28389             WS_VISIBLE or WS_CHILD or\r
28390             BS_PUSHLIKE or WS_TABSTOP, False, @ButtonActions );\r
28391   Result.fIgnoreDefault := TRUE;\r
28392   Result.fCtl3D := TRUE;\r
28393   with Result.fBoundsRect do\r
28394     Bottom := Top + 22;\r
28395   Result.fTextAlign := taCenter;\r
28396   Result.Caption := Caption;\r
28397   Result.fIsButton := TRUE;\r
28398   {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}\r
28399   Result.AttachProc( WndProcBtnReturnClick );\r
28400   {$ENDIF}\r
28401 end;\r
28402 {$ENDIF ASM_VERSION}\r
28403 //[END NewButton]\r
28405 {$ENDIF USE_CONSTRUCTORS}\r
28407 //----------------- BitBtn -----------------------\r
28409 //[FUNCTION WndProc_DrawItem]\r
28410 {$IFDEF ASM_VERSION}\r
28411 function WndProc_DrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )\r
28412                           : Boolean;\r
28413 asm     //cmd    //opd\r
28414        CMP       word ptr [EDX].TMsg.message, WM_DRAWITEM\r
28415        JNZ       @@ret_false\r
28416        MOV       EAX, [EDX].TMsg.lParam\r
28417        MOV       ECX, [EAX].TDrawItemStruct.hwndItem\r
28418        JECXZ     @@ret_false\r
28419        PUSH      EDX\r
28420        PUSH      offset[ID_SELF]\r
28421        PUSH      ECX\r
28422        CALL      GetProp\r
28423        POP       EDX\r
28424        TEST      EAX, EAX\r
28425        JZ        @@ret_false\r
28426        PUSH      [EDX].TMsg.lParam\r
28427        PUSH      [EDX].TMsg.wParam\r
28428        PUSH      CN_DRAWITEM\r
28429        PUSH      EAX\r
28430        CALL      TControl.Perform\r
28431        MOV       AL, 1\r
28432        RET\r
28433 @@ret_false:\r
28434        XOR       EAX, EAX\r
28435 end;\r
28436 {$ELSE ASM_VERSION} //Pascal\r
28437 function WndProc_DrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )\r
28438                           : Boolean;\r
28439 var DI: PDrawItemStruct;\r
28440     Control: PControl;\r
28441 begin\r
28442   Result := FALSE;\r
28443   if Msg.message = WM_DRAWITEM then\r
28444   begin\r
28445     DI := Pointer( Msg.lParam );\r
28446     Control := Pointer( GetProp( DI.hwndItem, ID_SELF ) );\r
28447     if Control <> nil then\r
28448     begin\r
28449       {Rslt := Integer(\r
28450       Control.OnDrawItem( Control, DI.hDC, DI.rcItem, DI.itemID,\r
28451                          TDrawAction( Byte( DI.itemAction ) ),\r
28452                          TDrawState( Word( DI.itemState ) ) ) );}\r
28453       Rslt := Control.Perform( CN_DRAWITEM, Msg.wParam, Msg.lParam );\r
28454       Result := TRUE;\r
28455     end;\r
28456       //else Rslt := 0;\r
28457   end;\r
28458 end;\r
28459 {$ENDIF ASM_VERSION}\r
28460 //[END WndProc_DrawItem]\r
28462 //[function ExcludeAmpersands]\r
28463 function ExcludeAmpersands( Self_: PControl; const S: String ): String;\r
28464 var I: Integer;\r
28465 begin\r
28466   Result := S;\r
28467   if not Self_.FBitBtnDrawMnemonic then Exit;\r
28468   for I := Length( Result ) downto 1 do\r
28469   begin\r
28470     if Result[ I ] = '&' then\r
28471       Delete( Result, I, 1 );\r
28472   end;\r
28473 end;\r
28475 //[procedure BitBtnExtDraw]\r
28476 procedure BitBtnExtDraw( Self_: PControl; DC: HDC; X, Y: Integer; const R: TRect;\r
28477           const CapText, CapTxtOrig: String; Color: TColor );\r
28478 var I, J, W, H: Integer;\r
28479     Sz: TSize;\r
28480     Pen, OldPen: HPen;\r
28481 begin\r
28482   if not Self_.FBitBtnDrawMnemonic then Exit;\r
28483   J := 0;\r
28484   for I := 1 to Length( CapTxtOrig ) do\r
28485   begin\r
28486     if CapTxtOrig[ I ] <> '&' then\r
28487       Inc( J )\r
28488     else\r
28489     begin\r
28490       Windows.GetTextExtentPoint32( DC, PChar( CapText ), J, Sz );\r
28491       W := Sz.cx;\r
28492       Windows.GetTextExtentPoint32( DC, '_', 1, Sz );\r
28493       H := Sz.cy - 1;\r
28494       Windows.GetTextExtentPoint32( DC, @ CapTxtOrig[ I + 1 ], 1, Sz );\r
28495       Windows.MoveToEx( DC, X + W, Y + H, nil );\r
28497       Pen := CreatePen( PS_SOLID, 0, Color2RGB( Color ) );\r
28498       OldPen := SelectObject( DC, Pen );\r
28500       Windows.LineTo( DC, X + W + Sz.cx, Y + H );\r
28502       SelectObject( DC, OldPen );\r
28503       DeleteObject( Pen );\r
28504     end;\r
28505   end;\r
28506 end;\r
28508 //[procedure TControl.SetBitBtnDrawMnemonic]\r
28509 procedure TControl.SetBitBtnDrawMnemonic(const Value: Boolean);\r
28510 begin\r
28511   FBitBtnDrawMnemonic := Value;\r
28512   FBitBtnGetCaption := ExcludeAmpersands;\r
28513   FBitBtnExtDraw := BitBtnExtDraw;\r
28514   Invalidate;\r
28515 end;\r
28517 //[function TControl.GetBitBtnImgIdx]\r
28518 function TControl.GetBitBtnImgIdx: Integer;\r
28519 begin\r
28520   Result := LoWord( fGlyphCount );\r
28521 end;\r
28523 //[procedure TControl.SetBitBtnImgIdx]\r
28524 procedure TControl.SetBitBtnImgIdx(const Value: Integer);\r
28525 begin\r
28526   if not( bboImageList in fBitBtnOptions ) then Exit;\r
28527   fGlyphCount := HiWord( fGlyphCount ) or (Value and $FFFF);\r
28528   Invalidate;\r
28529 end;\r
28531 //[function TControl.GetBitBtnImageList]\r
28532 function TControl.GetBitBtnImageList: THandle;\r
28533 begin\r
28534   Result := 0;\r
28535   if bboImageList in fBitBtnOptions then\r
28536     Result := fGlyphBitmap;\r
28537 end;\r
28539 //[procedure TControl.SetBitBtnImageList]\r
28540 procedure TControl.SetBitBtnImageList(const Value: THandle);\r
28541 begin\r
28542   fGlyphBitmap := Value;\r
28543   if Value <> 0 then\r
28544   begin\r
28545     fBitBtnOptions := fBitBtnOptions + [ bboImageList ];\r
28546     ImageList_GetIconSize( Value, fGlyphWidth, fGlyphHeight );\r
28547   end\r
28548   else\r
28549     fBitBtnOptions := fBitBtnOptions - [ bboImageList ];\r
28550   Invalidate;\r
28551 end;\r
28553 //[FUNCTION WndProcBitBtn]\r
28554 {$IFDEF ASM_noVERSION} // remove &-s from view //+ TextShift & if Y < 0 then Y := 0; // + glyph + TextShift if not glyphOver\r
28555 function WndProcBitBtn( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
28556 const szBitmapInfo = sizeof(TBitmapInfo);\r
28557 asm\r
28558         CMP      word ptr [EDX].TMsg.message, WM_LBUTTONDBLCLK\r
28559         JNZ      @@noWM_LBUTTONDBLCLK\r
28560         PUSH     ECX\r
28561         PUSH     [EDX].TMsg.wParam\r
28562         PUSH     [EDX].TMsg.lParam\r
28563         PUSH     WM_LBUTTONDOWN\r
28564         PUSH     EAX\r
28565         CALL     TControl.Perform\r
28566         POP      ECX\r
28567         MOV      [ECX], EAX\r
28568         MOV      AL, 1\r
28569         RET\r
28570 @@noWM_LBUTTONDBLCLK:\r
28571         PUSH     EBX\r
28572         CMP      [EDX].TMsg.message, CN_DRAWITEM\r
28573         JNZ      @@noCN_DRAWITEM\r
28574         PUSH     EDI\r
28575         PUSH     ESI\r
28576         XCHG     EDI, EAX // EDI = @Self\r
28577         MOV      dword ptr [ECX], 1\r
28578         MOV      ESI, [EDX].TMsg.lParam // ESI = DIS\r
28579         XOR      EBX, EBX // G = 0\r
28580         MOV      EAX, [ESI].TDrawItemStruct.itemState\r
28581         TEST     byte ptr [EDI].TControl.fBitBtnOptions, 8 //1 shl Ord(bboFixed)\r
28582         JNZ      @@fixed_in_options\r
28583         {$IFDEF PARANOIA}\r
28584         DB $A8, ODS_SELECTED\r
28585         {$ELSE}\r
28586         TEST     AL, ODS_SELECTED\r
28587         {$ENDIF}\r
28588         JZ       @@not1\r
28589         JMP      @@1\r
28590 @@fixed_in_options:\r
28591         TEST     byte ptr [EDI].TControl.fChecked, 1\r
28592         JZ       @@not1\r
28593 @@1:    INC      EBX\r
28594 @@not1:\r
28595         {$IFDEF PARANOIA}\r
28596         DB $A8, ODS_DISABLED\r
28597         {$ELSE}\r
28598         TEST     AL, ODS_DISABLED\r
28599         {$ENDIF}\r
28600         JZ       @@not2\r
28601         MOV      BL, 2\r
28602 @@not2: TEST     EBX, EBX\r
28603         JNZ      @@not3\r
28604         {$IFDEF PARANOIA}\r
28605         DB $A8, ODS_FOCUS\r
28606         {$ELSE}\r
28607         TEST     AL, ODS_FOCUS\r
28608         {$ENDIF}\r
28609         JZ       @@not3\r
28610         MOV      BL, 3\r
28611 @@not3: CMP      [EDI].TControl.fMouseInControl, BH\r
28612         JZ       @@not4\r
28613         TEST     EBX, EBX\r
28614         JZ       @@4\r
28615         CMP      BL, 3\r
28616         JNZ      @@not4\r
28617 @@4:    MOV      BL, 4\r
28618 @@not4: MOV      ECX, [EDI].TControl.fOnBitBtnDraw.TMethod.Code\r
28619         TEST     ECX, ECX\r
28620         JZ       @@noOnBitBtnDraw\r
28621         //JECXZ    @@noOnBitBtnDraw\r
28622         MOV      EAX, [EDI].TControl.fCanvas\r
28623           PUSH     EAX\r
28624         TEST     EAX, EAX\r
28625         JZ       @@noCanvas\r
28626         MOV      EDX, [ESI].TDrawItemStruct.hDC\r
28627         CALL     TCanvas.SetHandle\r
28628 @@noCanvas:\r
28629         MOV      EAX, [EDI].TControl.fOnBitBtnDraw.TMethod.Data\r
28630         MOV      EDX, EDI\r
28631         PUSH     EBX\r
28632         XCHG     ECX, EBX\r
28633         CALL     EBX\r
28634         POP      EBX\r
28635           POP      ECX // Canvas\r
28636         PUSH     EAX\r
28637         JECXZ    @@noCanvas2\r
28638         XCHG     EAX, ECX\r
28639         XOR      EDX, EDX\r
28640         CALL     TCanvas.SetHandle\r
28641 @@noCanvas2:\r
28642         POP      EAX\r
28643         TEST     AL, AL\r
28644         JNZ      @@exit_draw\r
28645 @@noOnBitBtnDraw:\r
28646         TEST     byte ptr [EDI].TControl.fBitBtnOptions, 2 //1 shl Ord(bboNoBorder)\r
28647         JNZ      @@noborder\r
28648         TEST     byte ptr [ESI].TDrawItemStruct.itemState, ODS_FOCUS\r
28649         JZ       @@noDefaultBorder\r
28650         PUSH     BLACK_BRUSH\r
28651         CALL     GetStockObject\r
28652         LEA      EDX, [ESI].TDrawItemStruct.rcItem\r
28653         OR       ECX, -1\r
28654         PUSH     ECX\r
28655         PUSH     ECX\r
28656         PUSH     EDX\r
28657         PUSH     EAX\r
28658         PUSH     EDX\r
28659         PUSH     [ESI].TDrawItemStruct.hDC\r
28660         CALL     Windows.FrameRect\r
28661         CALL     InflateRect\r
28662         XOR      ECX, ECX\r
28663         JMP      @@noFlat\r
28664 @@noDefaultBorder:\r
28665         MOVZX    ECX, [EDI].TControl.fFlat\r
28666         JECXZ    @@noFlat\r
28667         AND      CL, [EDI].TControl.fMouseInControl\r
28668         JZ       @@noborder\r
28669 @@noFlat:\r
28670         TEST     byte ptr [ESI].TDrawItemStruct.itemState, ODS_SELECTED\r
28671         MOV      CL, BDR_SUNKENOUTER or BDR_SUNKENINNER\r
28672         JNZ      @@border_sunken\r
28673         MOV      CL, BDR_RAISEDOUTER or BDR_RAISEDINNER\r
28674 @@border_sunken:\r
28675         LEA      EDX, [ESI].TDrawItemStruct.rcItem\r
28676         OR       EAX, -1\r
28677         PUSH     EAX\r
28678         PUSH     EAX\r
28679         PUSH     EDX\r
28680         PUSH     BF_ADJUST or BF_RECT\r
28681         PUSH     ECX\r
28682         PUSH     EDX\r
28683         PUSH     [ESI].TDrawItemStruct.hDC\r
28684         CALL     DrawEdge\r
28685         CALL     InflateRect\r
28686 @@noborder:\r
28687         PUSH     [ESI].TDrawItemStruct.rcItem.Bottom\r
28688         PUSH     [ESI].TDrawItemStruct.rcItem.Right\r
28689         PUSH     [ESI].TDrawItemStruct.rcItem.Top\r
28690         PUSH     [ESI].TDrawItemStruct.rcItem.Left\r
28691         MOV      EAX, [EDI].TControl.fGlyphWidth\r
28692         MOV      EDX, [EDI].TControl.fGlyphHeight\r
28693         TEST     EAX, EAX\r
28694         JLE      @@noglyph\r
28695         TEST     EDX, EDX\r
28696         JLE      @@noglyph\r
28697         PUSH     EBP\r
28698         MOV      EBP, ESP\r
28699         // [EBP+4] = TxRect\r
28701         PUSH     EDX // ImgH -> [EBP-4]\r
28702         PUSH     EAX // ImgW -> [EBP-8]\r
28703         PUSH     EDX // OutH -> [EBP-12]\r
28704         PUSH     EAX // OutW -> [EBP-16]\r
28705         MOV      EAX, [ESI].TDrawItemStruct.rcItem.Left // X = DIS.rcItem.Left\r
28706         MOV      EDX, [ESI].TDrawItemStruct.rcItem.Top  // Y = DIS.rcItem.Top\r
28707         MOV      ECX, [ESI].TDrawItemStruct.rcItem.Bottom\r
28708         SUB      ECX, EDX\r
28709         PUSH     ECX // H -> [EBP-20]\r
28710         MOV      ECX, [ESI].TDrawItemStruct.rcItem.Right\r
28711         SUB      ECX, EAX\r
28712         PUSH     ECX // W -> [EBP-24]\r
28713         MOVZX    ECX, [EDI].TControl.fGlyphLayout\r
28714         PUSH     EBX\r
28715         INC      ECX\r
28716         LOOP     @@noGlyphLeft\r
28717         MOV      EBX, EAX      // X\r
28718         ADD      EBX, [EBP-16] // +OutW\r
28719         MOV      [EBP+4].TRect.Left, EBX // TxRect.Left = X+OutW\r
28720         JMP      @@centerY\r
28721 @@noGlyphLeft:\r
28722         LOOP     @@noGlyphTop\r
28723         MOV      EBX, EDX      // Y\r
28724         ADD      EBX, [EBP-12] // +OutH\r
28725         MOV      [EBP+4].TRect.Top, EBX // TxRect.Top = Y+OutH\r
28726         LOOP     @@centerX // always JMP, ECX := -1\r
28727 @@noGlyphTop:\r
28728         LOOP     @@noGlyphRight\r
28729         MOV      EAX, [ESI].TDrawItemStruct.rcItem.Right\r
28730         SUB      EAX, [EBP-16] // -OutW -> X\r
28731         MOV      [EBP+4].TRect.Right, EAX\r
28732 @@centerY:\r
28733         MOV      EBX, [EBP-20] // H\r
28734         SUB      EBX, [EBP-12] // -OutH\r
28735         JLE      @@noGlyphRight\r
28736         SAR      EBX, 1\r
28737         ADD      EDX, EBX      // Y = Y + (H-OutH)/2\r
28738 @@noGlyphRight:\r
28739         LOOP     @@noGlyphBottom\r
28740         MOV      EDX, [ESI].TDrawItemStruct.rcItem.Bottom\r
28741         SUB      EDX, [EBP-12] // -OutH -> Y\r
28742         MOV      [EBP+4].TRect.Bottom, EDX\r
28743         LOOP     @@centerX // always JMP, ECX := -1\r
28744 @@noGlyphBottom:\r
28745         LOOP     @@noGlyphOver\r
28746 @@centerX:\r
28747         MOV      EBX, [EBP-24] // W\r
28748         SUB      EBX, [EBP-16] // -OutW\r
28749         SHR      EBX, 1        // /2\r
28750         ADD      EAX, EBX      // +EAX, X = X + (W-OutW)/2\r
28751         JECXZ    @@centerY\r
28752 @@noGlyphOver:\r
28753         MOV      ECX, [ESI].TDrawItemStruct.rcItem.Left\r
28754         CMP      EAX, ECX\r
28755         JGE      @@ok1\r
28756         XCHG     EAX, ECX\r
28757 @@ok1:  CMP      EDX, [ESI].TDrawItemStruct.rcItem.Top\r
28758         {$IFDEF USE_CMOV}\r
28759         CMOVL    EDX, [ESI].TDrawItemStruct.rcItem.Top\r
28760         {$ELSE}\r
28761         JGE      @@ok2\r
28762         MOV      EDX, [ESI].TDrawItemStruct.rcItem.Top\r
28763 @@ok2:  {$ENDIF}\r
28765         MOV      ECX, [ESI].TDrawItemStruct.rcItem.Right\r
28766         SUB      ECX, EAX\r
28767         CMP      [EBP-16], ECX\r
28768         JLE      @@ok3\r
28769         MOV      [EBP-16], ECX // OutW := rcItem.Right - X;\r
28770 @@ok3:  MOV      ECX, [ESI].TDrawItemStruct.rcItem.Bottom\r
28771         SUB      ECX, EDX\r
28772         CMP      ECX, [EBP-12]\r
28773         JGE      @@ok4\r
28774         MOV      [EBP-12], ECX // OutH := rcItem.Bottom - Y;\r
28775 @@ok4:\r
28776         POP      EBX // EBX = G\r
28777         TEST     byte ptr [EDI].TControl.fBitBtnOptions, 1 //1 shl Ord(bboImageList)\r
28778         JZ       @@draw_bitmap\r
28779         MOVZX    ECX, word ptr [EDI].TControl.fGlyphCount\r
28780         CMP      word ptr [EDI].TControl.fGlyphCount + 2, BX\r
28781         JLE      @@no_add_glyphIdx\r
28782         ADD      ECX, EBX\r
28783 @@no_add_glyphIdx:\r
28784         XOR      EBX, EBX\r
28785         PUSH     ILD_TRANSPARENT // Flags = 1 (ILD_TRANSPARENT)\r
28786         PUSH     EBX // Blend = 0\r
28787         PUSH     -1  // Bk = CLR_NONE\r
28788         PUSH     EBX // 0\r
28789         PUSH     EBX // 0\r
28790         PUSH     EDX\r
28791         PUSH     EAX\r
28792         PUSH     [ESI].TDrawItemStruct.hDC\r
28793         PUSH     ECX\r
28794         PUSH     [EDI].TControl.fGlyphBitmap\r
28795         CMP      [EDI].TControl.fTransparent, BL\r
28796         JNZ      @@imgl_transp\r
28797         MOV      EAX, [EDI].TControl.fColor\r
28798         CALL     Color2RGB\r
28799         MOV      [ESP+32], EAX // Bk = Color2RGB(fColor)\r
28800         MOV      [ESP+40], EBX // Flags = 0\r
28801 @@imgl_transp:\r
28802         INC      EBX\r
28803         CMP      word ptr [EDI].TControl.fGlyphCount + 2, BX\r
28804         JNZ      @@draw_imagelist\r
28805         DEC      byte ptr [ESP+36+3] // $FF, CLR_DEFAULT = $FF000000\r
28806         TEST     byte ptr [ESI].TDrawItemStruct.itemState, ODS_FOCUS\r
28807         JZ       @@draw_imagelist\r
28808         OR       byte ptr [ESP+40], ILD_BLEND25 // Flags != 2\r
28809 @@draw_imagelist:\r
28810         CALL     ImageList_DrawEx\r
28811         JMP      @@glyph_drawn\r
28813 @@draw_bitmap:\r
28814         PUSH     EAX // PlaceHold for DC\r
28815         PUSH     EAX // PlaceHold for OldBmp\r
28816         PUSH     SRCCOPY\r
28817         PUSH     dword ptr [EBP-4] // ImgH\r
28818         PUSH     dword ptr [EBP-8] // ImgW\r
28819         PUSH     0\r
28820         PUSH     EAX // PlaceHold for I\r
28821         PUSH     EAX // PlaceHold for DC\r
28822         PUSH     dword ptr [EBP-12] // OutH\r
28823         PUSH     dword ptr [EBP-16] // OutW\r
28824         PUSH     EDX // Y\r
28825         PUSH     EAX // X\r
28826         PUSH     [ESI].TDrawItemStruct.hDC\r
28828         PUSH     0\r
28829         CALL     CreateCompatibleDC\r
28830         MOV      [ESP+48], EAX // save DC\r
28831         MOV      [ESP+20], EAX // place DC\r
28832         PUSH     [EDI].TControl.fGlyphBitmap\r
28833         PUSH     EAX\r
28834         CALL     SelectObject\r
28835         MOV      [ESP+44], EAX // save OldBitmap\r
28836         XOR      EAX, EAX\r
28837         CMP      [EDI].TControl.fGlyphCount, EBX\r
28838         JLE      @@no_incGlyIdx\r
28839         MOV      EAX, [EBP-8] // ImgW\r
28840         IMUL     EBX\r
28841 @@no_incGlyIdx:\r
28842         MOV      [ESP+24], EAX // place I\r
28843         CALL     StretchBlt\r
28844         CALL     FinishDC\r
28846 @@glyph_drawn:\r
28847         MOV      ESP, EBP\r
28848         POP      EBP\r
28850 @@noglyph:\r
28851         TEST     byte ptr[EDI].TControl.fBitBtnOptions, 4 //1 shl Ord(bboNoCaption)\r
28852         JNZ      @@noCaption\r
28855         POP      EAX\r
28856         PUSH     EAX\r
28857         MOV      EDX, [ESP].TRect.Right\r
28858         CMP      EDX, EAX\r
28859         JLE      @@noCaption\r
28860         MOV      EDX, [ESP].TRect.Bottom\r
28861         CMP      EDX, [ESP].TRect.Top\r
28862         JLE      @@noCaption\r
28864         XOR      EBX, EBX\r
28865         PUSH     EBX                      // > CapText\r
28866         MOV      EDX, ESP\r
28867         MOV      EAX, EDI\r
28868         CALL     TControl.GetCaption\r
28869         PUSH     EBX                      // > Bk\r
28870         PUSH     EBX                      // > Blend\r
28871         CMP      [EDI].TControl.fTransparent, BL\r
28872         MOV      BL, ETO_CLIPPED\r
28873         JNZ      @@drwTxTransparent\r
28874         CMP      [EDI].TControl.fGlyphLayout, glyphOver\r
28875         JNZ      @@drwTxOpaque\r
28876 @@drwTxTransparent:\r
28877         PUSH     TRANSPARENT\r
28878         PUSH     [ESI].TDrawItemStruct.hDC\r
28879         CALL     SetBkMode\r
28880         MOV      [ESP+4], EAX // Bk := SetBkMode( DIS.hDC, TRANSPARENT )\r
28881         JMP      @@drwTx1\r
28882 @@drwTxOpaque:\r
28883         MOV      BL, ETO_CLIPPED or ETO_OPAQUE\r
28884         MOV      EAX, [EDI].TControl.fColor\r
28885         CALL     Color2RGB\r
28886         PUSH     EAX\r
28887         PUSH     [ESI].TDrawItemStruct.hDC\r
28888         CALL     SetBkColor\r
28889         POP      ECX\r
28890         PUSH     EAX // Blend := SetBkColor(DIS.hDC,fColor)\r
28891 @@drwTx1:\r
28892         PUSH     0   // > OldFont\r
28893         PUSH     0   // > OldTextColor\r
28895         PUSH     0                 // push <nil>\r
28896         MOV      EDX, [ESP+20] // CapText\r
28897         CALL     EDX2PChar\r
28898         PUSH     dword ptr [EDX-4] // push Length(CapText)\r
28899         PUSH     EDX               // push PChar(CapText)\r
28900         LEA      EAX, [ESP+32]\r
28901         PUSH     EAX               // push @TxRect\r
28902         PUSH     EBX               // push Flags\r
28904         MOV      EBX, [ESI].TDrawItemStruct.hDC\r
28906         MOV      ECX, [EDI].TControl.fFont\r
28907         JECXZ    @@drwTx_noFont\r
28908         XCHG     EAX, ECX\r
28909         CALL     TGraphicTool.GetHandle\r
28910         PUSH     EAX\r
28911         PUSH     EBX\r
28912         CALL     SelectObject\r
28913         MOV      [ESP+24], EAX // OldFont := SelectObject...\r
28914 @@drwTx_noFont:\r
28915         MOV      EAX, [EDI].TControl.fTextColor\r
28916         CALL     Color2RGB\r
28917         PUSH     EAX\r
28918         PUSH     EBX\r
28919         CALL     SetTextColor\r
28920         MOV      [ESP+20], EAX // OldTextColor := SetTextColor...\r
28922         PUSH     EAX\r
28923         PUSH     EAX\r
28924         PUSH     ESP\r
28925         MOV      ECX, [ESP+48] // ECX = CapText\r
28926         XOR      EAX, EAX\r
28927         JECXZ    @@drwTx0\r
28928         MOV      EAX, [ECX-4]  // EAX = Length(CapText)\r
28929 @@drwTx0:\r
28930         PUSH     EAX\r
28931         PUSH     ECX\r
28932         PUSH     EBX\r
28933         CALL     GetTextExtentPoint32\r
28934         POP      ECX // ECX = TextSz.cx\r
28935         POP      EDX // EDX = TextSz.cy\r
28936         MOV      EAX, [ESP+40].TRect.Bottom\r
28937         SUB      EAX, [ESP+40].TRect.Top\r
28938         SUB      EAX, EDX\r
28939         JGE      @@yOk\r
28940         XOR      EAX, EAX\r
28941 @@yOk:  SHR      EAX, 1\r
28942         ADD      EAX, [ESP+40].TRect.Top\r
28943         PUSH     EAX                      // push Y\r
28944         MOV      EDX, [ESP+44].TRect.Right\r
28945         MOV      EAX, [ESP+44].TRect.Left // EAX = TxRect.Left\r
28946         SUB      EDX, EAX // EDX = W\r
28947         PUSH     EAX\r
28948         CMP      [EDI].TControl.fTextAlign, taRight\r
28949         JL       @@chk_X\r
28950         JE       @@alignR\r
28951         SUB      ECX, EDX\r
28952         SAR      ECX, 1\r
28953         JMP      @@alignC\r
28954 @@alignR:\r
28955         ADD      EAX, EDX\r
28956 @@alignC:\r
28957         SUB      EAX, ECX\r
28958 @@chk_X:POP      EDX\r
28959         CMP      EAX, EDX\r
28960         JGE      @@xOk\r
28961         XCHG     EAX, EDX\r
28962 @@xOk:  PUSH     EAX                      // push X\r
28963         PUSH     EBX                      // push hDC\r
28964         CALL     ExtTextOut\r
28966         PUSH     EBX\r
28967         CALL     SetTextColor\r
28968         POP      ECX\r
28969         JECXZ    @@noRestoreFont\r
28970         PUSH     ECX\r
28971         PUSH     EBX\r
28972         CALL     SelectObject\r
28973 @@noRestoreFont:\r
28974         POP      ECX // Blend\r
28975         JECXZ    @@restoreBk\r
28976         PUSH     ECX\r
28977         PUSH     EBX\r
28978         CALL     SetBkColor\r
28979         POP      ECX\r
28980         JMP      @@delCaption\r
28981 @@restoreBk:\r
28982         PUSH     EBX\r
28983         CALL     SetBkMode\r
28984 @@delCaption:\r
28985         CALL     RemoveStr\r
28987 @@noCaption:\r
28988         ADD      ESP, 16\r
28990 @@exit_draw:\r
28991         POP      ESI\r
28992         POP      EDI\r
28993         POP      EBX\r
28994         MOV      AL, 1\r
28995         RET\r
28997 @@noCN_DRAWITEM:\r
28998         CMP      word ptr [EDX].TMsg.message, WM_LBUTTONDOWN\r
28999         JZ       @@doDown\r
29000         CMP      word ptr [EDX].TMsg.message, WM_KEYDOWN\r
29001         JNZ      @@noWM_LBUTTONDOWN\r
29002         CMP      [EDX].TMsg.wParam, 32\r
29003         JNZ      @@noWM_LBUTTONDOWN\r
29004 @@doDown:\r
29005         PUSH     EDX\r
29006         XCHG     EBX, EAX\r
29008         CALL     @@fixed_proc\r
29009         MOV      ECX, [EBX].TControl.fRepeatInterval\r
29010         JECXZ    @@exit_LBUTTONDOWN\r
29011         //MOV      EAX, EBX\r
29012         //CALL     TControl.DoClick\r
29013         POP      EDX\r
29014         PUSH     EDX\r
29015         CMP      word ptr [EDX].TMsg.message, WM_KEYDOWN\r
29016         JZ       @@not_SetTimer\r
29017         PUSH     0\r
29018         PUSH     [EBX].TControl.fRepeatInterval\r
29019         PUSH     1\r
29020         PUSH     [EBX].TControl.fHandle\r
29021         CALL     SetTimer\r
29022 @@exit_LBUTTONDOWN:\r
29023 @@not_SetTimer:\r
29024         POP      EDX\r
29025         JMP      @@invalidate\r
29027 @@noWM_LBUTTONDOWN:\r
29028         CMP      word ptr [EDX].TMsg.message, WM_TIMER\r
29029         JNZ      @@noWM_TIMER\r
29031         XCHG      EBX, EAX\r
29032         PUSH     0\r
29033         PUSH     0\r
29034         PUSH     BM_GETSTATE\r
29035         PUSH     EBX\r
29036         CALL     TControl.Perform\r
29037         {$IFDEF PARANOIA}\r
29038         DB $A8, 4\r
29039         {$ELSE}\r
29040         TEST AL, BST_PUSHED\r
29041         {$ENDIF}\r
29042         JNZ      @@pushed\r
29043         PUSH     1\r
29044         PUSH     [EBX].TControl.fHandle\r
29045         CALL     KillTimer\r
29046         CALL     ReleaseCapture\r
29047         JMP      @@noWM_TIMER\r
29048 @@fixed_proc:\r
29049         TEST     byte ptr [EBX].TControl.fBitBtnOptions, 8 // bboFixed\r
29050         JZ       @@not_fixed\r
29051         XOR      [EBX].TControl.fChecked, 1\r
29052         MOV      ECX, [EBX].TControl.fOnChange.TMethod.Code\r
29053         JECXZ    @@not_fixed\r
29054         MOV      EAX, [EBX].TControl.fOnChange.TMethod.Data\r
29055         MOV      EDX, EBX\r
29056         JMP      ECX\r
29057 @@pushed:\r
29058         CALL     @@fixed_proc\r
29059         MOV      EAX, EBX\r
29060         CALL     TControl.DoClick\r
29061 @@invalidate:\r
29062         XCHG     EAX, EBX\r
29063         CALL     TControl.Invalidate\r
29064 @@noWM_TIMER:\r
29065         XOR      EAX, EAX\r
29066         POP      EBX\r
29067 @@not_fixed:\r
29068 end;\r
29069 {$ELSE ASM_VERSION} //Pascal\r
29070 function WndProcBitBtn( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
29071 var DIS: PDrawItemStruct;\r
29072     IsDown, IsDefault, IsDisabled: Boolean;\r
29073     Flags: Integer;\r
29074     X, Y, W, H, ImgW, ImgH, OutW, OutH, I, G, Bk, Blend: Integer;\r
29075     //BI: TBitmapInfo;\r
29076     //Dib: TDibSection;\r
29077     TxRect: TRect;\r
29078     OldFont: HFont;\r
29079     OldTextColor: TColor;\r
29080     CapText, CapTxtOrig: String;\r
29081     TextSz: TSize;\r
29082     DC: HDC;\r
29083     OldBmp: HBitmap;\r
29084     Handled: Boolean;\r
29085     //Br: HBrush;\r
29086 begin\r
29087   Result := False;\r
29088   if (Msg.message = WM_LBUTTONDBLCLK) then\r
29089   begin\r
29090     Rslt := Self_.Perform( WM_LBUTTONDOWN, Msg.wParam, Msg.lParam );\r
29091     Result := True;\r
29092     Exit;\r
29093   end;\r
29094   if (Msg.message = CN_DRAWITEM) then\r
29095   begin\r
29096     Result := True;\r
29097     Rslt := 1;\r
29098     DIS := Pointer( Msg.lParam );\r
29099     IsDown := DIS.itemState and ODS_SELECTED <> 0;\r
29100     IsDefault := DIS.itemState and ODS_FOCUS <> 0;\r
29101     IsDisabled := DIS.itemState and ODS_DISABLED <> 0;\r
29102     G := 0;\r
29103     if IsDown and not(bboFixed in Self_.fBitBtnOptions)\r
29104     or (bboFixed in Self_.fBitBtnOptions) and Self_.fChecked then\r
29105       G := 1;\r
29106     if IsDisabled then\r
29107       G := 2;\r
29108     if (G = 0) and IsDefault then\r
29109       G := 3;\r
29110     if ((G = 0) or (G = 3)) and Self_.MouseInControl then\r
29111       G := 4;\r
29112     if Assigned( Self_.fOnBitBtnDraw ) then\r
29113     begin\r
29114       if Assigned( Self_.fCanvas ) then\r
29115         Self_.fCanvas.SetHandle( DIS.hDC );\r
29116       Handled := Self_.fOnBitBtnDraw( Self_, G );\r
29117       if Assigned( Self_.fCanvas ) then\r
29118         Self_.fCanvas.SetHandle( 0 );\r
29119       if Handled then Exit;\r
29120     end;\r
29121     if not ( bboNoBorder in Self_.fBitBtnOptions ) then\r
29122     begin\r
29123       if IsDefault then\r
29124       begin\r
29125         Windows.FrameRect( DIS.hDC, DIS.rcItem, GetStockObject( BLACK_BRUSH ) );\r
29126         InflateRect( DIS.rcItem, -1, -1 );\r
29127       end;\r
29128       if not Self_.fFlat or Self_.fMouseInControl or IsDefault then\r
29129       begin\r
29130         if IsDown then\r
29131           Flags := BDR_SUNKENOUTER or BDR_SUNKENINNER\r
29132         else\r
29133           Flags := BDR_RAISEDOUTER or BDR_RAISEDINNER;\r
29134         DrawEdge( DIS.hDC, DIS.rcItem, Flags, BF_ADJUST or BF_RECT );\r
29135         InflateRect( DIS.rcItem, -1, -1 );\r
29136       end;\r
29137     end;\r
29138     TxRect := DIS.rcItem;\r
29139     if Self_.fGlyphBitmap <> 0 then\r
29140     begin\r
29141       ImgW := Self_.fGlyphWidth;\r
29142       ImgH := Self_.fGlyphHeight;\r
29143       if (ImgW > 0) and (ImgH > 0) then\r
29144       begin\r
29145         OutW := ImgW;\r
29146         OutH := ImgH;\r
29147         W := DIS.rcItem.Right - DIS.rcItem.Left;\r
29148         H := DIS.rcItem.Bottom - DIS.rcItem.Top;\r
29149         X := DIS.rcItem.Left;\r
29150         Y := DIS.rcItem.Top;\r
29151         if isDown and (Self_.fGlyphLayout <> glyphOver) then\r
29152         begin\r
29153           Inc( X, Self_.TextShiftX );\r
29154           Inc( Y, Self_.TextShiftY );\r
29155         end;\r
29156         case Self_.fGlyphLayout of\r
29157           glyphLeft:\r
29158             begin\r
29159               Y := Y + (H - OutH) div 2;\r
29160               TxRect.Left := X + OutW;\r
29161             end;\r
29162           glyphTop:\r
29163             begin\r
29164               X := X + (W - OutW) div 2;\r
29165               TxRect.Top := Y + OutH;\r
29166             end;\r
29167           glyphRight:\r
29168             begin\r
29169               X := DIS.rcItem.Right - OutW;\r
29170               TxRect.Right := X;\r
29171               Y := Y + (H - OutH) div 2;\r
29172             end;\r
29173           glyphBottom:\r
29174             begin\r
29175               Y := DIS.rcItem.Bottom - OutH;\r
29176               TxRect.Bottom := Y;\r
29177               X := X + (W - OutW) div 2;\r
29178             end;\r
29179           glyphOver:\r
29180             begin\r
29181               X := X + (W - OutW) div 2;\r
29182               Y := Y + (H - OutH) div 2;\r
29183             end;\r
29184         end;\r
29185         if X < DIS.rcItem.Left then\r
29186           X := DIS.rcItem.Left;\r
29187         if Y < DIS.rcItem.Top then\r
29188           Y := DIS.rcItem.Top;\r
29189         if X + OutW > DIS.rcItem.Right then\r
29190           OutW := DIS.rcItem.Right - X;\r
29191         if Y + OutH > DIS.rcItem.Bottom then\r
29192           OutH := DIS.rcItem.Bottom - Y;\r
29194         //Br := CreateSolidBrush( Color2RGB( Self_.fColor ) );\r
29195         //Windows.FillRect( DIS.hDC, MakeRect( X, DIS.rcItem.Top, X + OutW, DIS.rcItem.Bottom ), Br );\r
29196         //DeleteObject( Br );\r
29198         if bboImageList in Self_.fBitBtnOptions then\r
29199           begin\r
29200             I := LoWord( Self_.fGlyphCount );\r
29201             if //(HiWord( Self_.fGlyphCount ) > 1) and\r
29202                (HiWord( Self_.fGlyphCount ) > G) then\r
29203                I := I + G;\r
29204             Flags := 0; // ILD_NORMAL\r
29205             Blend := 0;\r
29206             if not Self_.fTransparent then\r
29207               Bk := Color2RGB( Self_.fColor )\r
29208             else\r
29209               begin\r
29210                 Bk := Integer(CLR_NONE);\r
29211                 Flags := ILD_TRANSPARENT;\r
29212               end;\r
29213             if HiWord( Self_.fGlyphCount ) = 1 then\r
29214             begin\r
29215               Blend := Integer(CLR_DEFAULT);\r
29216               if IsDefault then\r
29217                 Flags := Flags or ILD_BLEND25;\r
29218             end;\r
29219             ImageList_DrawEx( Self_.fGlyphBitmap, I, DIS.hDC, X, Y, 0, 0,\r
29220               Bk, Blend, Flags );\r
29221           end\r
29222         else\r
29223           begin\r
29224             DC := CreateCompatibleDC( 0 );\r
29225             OldBmp := SelectObject( DC, Self_.fGlyphBitmap );\r
29227             I := 0;\r
29228             if Self_.fGlyphCount > G then\r
29229               I := I + G * ImgW;\r
29230             StretchBlt( DIS.hDC, X, Y, OutW, OutH, DC, I, 0, ImgW, ImgH, SRCCOPY );\r
29232             SelectObject( DC, OldBmp );\r
29233             DeleteDC( DC );\r
29234           end;\r
29235       end;\r
29236     end;\r
29237     if not (bboNoCaption in Self_.fBitBtnOptions) then\r
29238     //if (Self_.Text <> '') then\r
29239     if (TxRect.Right > TxRect.Left) and (TxRect.Bottom > TxRect.Top) then\r
29240     begin\r
29241       CapText := Self_.Caption;\r
29242       /////////////////////////////////////////////  added 19 Nov 2001\r
29243       CapTxtOrig := CapText;\r
29244       if Assigned( Self_.FBitBtnGetCaption ) then\r
29245         CapText := Self_.FBitBtnGetCaption( Self_, CapText );\r
29246       /////////////////////////////////////////////\r
29248       Bk := 0;\r
29249       Blend := 0;\r
29250       Flags := ETO_CLIPPED;\r
29251       if Self_.fTransparent or (Self_.fGlyphLayout = glyphOver) then\r
29252         Bk := SetBkMode( DIS.hDC, TRANSPARENT )\r
29253       else\r
29254       begin\r
29255         Flags := Flags or ETO_OPAQUE;\r
29256         Blend := SetBkColor( DIS.hDC, Color2RGB( Self_.fColor ) );\r
29257       end;\r
29258         // Returned previous BkMode is either OPAQUE=1 or TRANSPARENT=2\r
29260       OldFont := 0;\r
29261       if assigned( Self_.fFont ) then\r
29262         OldFont := SelectObject( DIS.hDC, Self_.fFont.Handle );\r
29263       OldTextColor := SetTextColor( DIS.hDC, Color2RGB( Self_.fTextColor ) );\r
29265       Windows.GetTextExtentPoint32( DIS.hDC, PChar( CapText ), Length( CapText ),\r
29266         TextSz );\r
29267       W := TxRect.Right - TxRect.Left;\r
29268       H := TxRect.Bottom - TxRect.Top;\r
29269       Y := TxRect.Top + (H - TextSz.cy) div 2;\r
29270       case Self_.fTextAlign of\r
29271         taLeft: X := TxRect.Left;\r
29272         taCenter: X := TxRect.Left + (W - TextSz.cx) div 2;\r
29273         else {taRight:} X := TxRect.Right - TextSz.cx;\r
29274       end;\r
29275       if isDown then\r
29276       begin\r
29277         Inc( X, Self_.TextShiftX );\r
29278         Inc( Y, Self_.TextShiftY );\r
29279       end;\r
29280       if Y < 0 then\r
29281         Y := 0;\r
29282       if X < TxRect.Left then\r
29283         X := TxRect.Left;\r
29285       Windows.ExtTextOut( DIS.hDC, X, Y, Flags, @TxRect,\r
29286         PChar( CapText ), Length( CapText ), nil );\r
29288       //////////////////////////////////////////////////////////////////////////\r
29289       //  added 19 Nov 2001 to provide underlying mnemonic characters\r
29290       if Assigned( Self_.FBitBtnExtDraw ) then\r
29291         Self_.FBitBtnExtDraw( Self_, DIS.hDC, X, Y, TxRect, CapText, CapTxtOrig,\r
29292                               OldTextColor );\r
29293       //////////////////////////////////////////////////////////////////////////\r
29295       SetTextColor( DIS.hDC, OldTextColor );\r
29296       if OldFont <> 0 then\r
29297         SelectObject( DIS.hDC, OldFont );\r
29299       if Blend = 0 then\r
29300         SetBkMode( DIS.hDC, Bk )\r
29301       else\r
29302         SetBkColor( DIS.hDC, Blend );\r
29303     end;\r
29304   end;\r
29305   if (Msg.message = WM_LBUTTONDOWN) or (Msg.message = WM_KEYDOWN) and (Msg.wParam = 32) then\r
29306   begin\r
29307     if bboFixed in Self_.fBitBtnOptions then\r
29308     begin\r
29309       Self_.fChecked := not Self_.fChecked;\r
29310       if Assigned( Self_.fOnChange ) then\r
29311         Self_.fOnChange( Self_ );\r
29312     end;\r
29313     if Self_.fRepeatInterval > 0 then\r
29314     begin\r
29315       //Self_.DoClick;\r
29316       if Msg.message <> WM_KEYDOWN then\r
29317         SetTimer( Self_.fHandle, 1, Self_.fRepeatInterval, nil );\r
29318       Self_.Invalidate;\r
29319     end;\r
29320   end;\r
29322   // added 15 Aug 2002 to repaint when focus lost:\r
29323   if Msg.message = WM_KILLFOCUS then\r
29324     Self_.Invalidate;\r
29326   if Msg.message = WM_TIMER then\r
29327   begin\r
29328     if Self_.Perform( BM_GETSTATE, 0, 0 ) and BST_PUSHED = 0 then\r
29329     begin\r
29330       KillTimer( Self_.fHandle, 1 );\r
29331       ReleaseCapture;\r
29332     end\r
29333        else\r
29334     begin\r
29335       if bboFixed in Self_.fBitBtnOptions then\r
29336       begin\r
29337         Self_.fChecked := not Self_.fChecked;\r
29338         if Assigned( Self_.fOnChange ) then\r
29339           Self_.fOnChange( Self_ );\r
29340       end;\r
29341       Self_.DoClick;\r
29342       Self_.Invalidate;\r
29343     end;\r
29344   end;\r
29345 end;\r
29346 {$ENDIF ASM_VERSION}\r
29347 //[END WndProcBitBtn]\r
29349 {$IFDEF USE_CONSTRUCTORS}\r
29350 //[function NewBitBtn]\r
29351 function NewBitBtn( AParent: PControl; const Caption: String;\r
29352          Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap;\r
29353          GlyphCount: Integer ): PControl;\r
29354 begin\r
29355   new( Result, CreateBitBtn( AParent, Caption, Options, Layout, GlyphBitmap, GlyphCount ) );\r
29356 end;\r
29357 //[END NewBitBtn]\r
29358 {$ELSE not_USE_CONSTRUCTORS}\r
29360 //[FUNCTION NewBitBtn]\r
29361 {$IFDEF ASM_VERSION}\r
29362 function NewBitBtn( AParent: PControl; const Caption: String;\r
29363          Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap; GlyphCount: Integer ): PControl;\r
29364 const szBitmapInfo = sizeof(TBitmapInfo);\r
29365 asm\r
29366         PUSH     EBX\r
29367         PUSH     EDX\r
29368         PUSH     ECX\r
29370         PUSH     0\r
29371         PUSH     offset[ButtonActions]\r
29372         MOV      EDX, offset[ButtonClass]\r
29373         MOV      ECX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or BS_OWNERDRAW\r
29374         CALL     _NewControl\r
29375         XCHG     EBX, EAX\r
29376         INC      [EBX].TControl.fIgnoreDefault\r
29377         INC      [EBX].TControl.fIsButton\r
29378         MOV      byte ptr [EBX].TControl.fCommandActions.aAutoSzX, 8\r
29379         MOV      byte ptr [EBX].TControl.fCommandActions.aAutoSzY, 8\r
29380         POP      EAX\r
29381         MOV      [EBX].TControl.fBitBtnOptions, AL\r
29382         MOVZX    EDX, Layout\r
29383         MOV      [EBX].TControl.fGlyphLayout, DL\r
29384         MOV      ECX, GlyphBitmap\r
29385         MOV      [EBX].TControl.fGlyphBitmap, ECX\r
29386         MOV      EDX, [EBX].TControl.fBoundsRect.Top\r
29387         ADD      EDX, 22\r
29388         MOV      [EBX].TControl.fBoundsRect.Bottom, EDX\r
29389         TEST     ECX, ECX\r
29390         JZ       @@noGlyphWH\r
29391         {$IFDEF PARANOIA}\r
29392         DB $A8, 01\r
29393         {$ELSE}\r
29394         TEST AL, bboImageList\r
29395         {$ENDIF}\r
29396         JZ       @@getBmpWH\r
29397         PUSH     EAX\r
29398         MOV      EAX, ESP\r
29399         PUSH     EAX\r
29400         MOV      EDX, ESP\r
29401         PUSH     EAX\r
29402         PUSH     EDX\r
29403         PUSH     ECX\r
29404         CALL     ImageList_GetIconSize\r
29405         POP      EAX\r
29406         POP      EDX\r
29407         MOV      ECX, GlyphCount\r
29408         JMP      @@WHready\r
29409 @@getBmpWH:\r
29410         ADD      ESP, -szBitmapInfo\r
29411         PUSH     ESP\r
29412         PUSH     szBitmapInfo\r
29413         PUSH     ECX\r
29414         CALL     GetObject\r
29415         XCHG     ECX, EAX\r
29416         POP      EAX\r
29417         POP      EAX\r
29418         POP      EDX\r
29419         ADD      ESP, szBitmapInfo-12\r
29420         TEST     ECX, ECX\r
29421         JZ       @@noGlyphWH\r
29422         MOV      ECX, GlyphCount\r
29423         INC      ECX\r
29424         LOOP     @@GlyphCountOK\r
29425         PUSH     EAX\r
29426         PUSH     EDX\r
29427         XCHG     EDX, ECX\r
29428         DIV      ECX\r
29429         XCHG     ECX, EAX\r
29430         POP      EDX\r
29431         POP      EAX\r
29432 @@GlyphCountOK:\r
29433         CMP      ECX, 1\r
29434         JLE      @@WHReady\r
29435         PUSH     EDX\r
29436         CDQ\r
29437         IDIV     ECX\r
29438         POP      EDX\r
29439 @@WHReady:\r
29440         MOV      [EBX].TControl.fGlyphWidth, EAX\r
29441         MOV      [EBX].TControl.fGlyphHeight, EDX\r
29442         MOV      [EBX].TControl.fGlyphCount, ECX\r
29443         POP      ECX     // ECX = @ Caption[ 1 ]\r
29444         PUSH     ECX\r
29445         PUSH     EDX\r
29446         PUSH     EAX\r
29447         TEST     EAX, EAX\r
29448         JLE      @@noWidthResize\r
29449         JECXZ    @@addWLeft\r
29450         CMP      [Layout], glyphOver\r
29451         JE       @@addWLeft\r
29452         MOVZX    ECX, byte ptr[ECX]\r
29453         JECXZ    @@addWLeft\r
29454         // else\r
29455         CMP      [Layout], glyphLeft\r
29456         JZ       @@addWRight\r
29457         CMP      [Layout], glyphRight\r
29458         JNZ      @@noWidthResize\r
29459 @@addWRight:\r
29460         ADD      [EBX].TControl.fBoundsRect.Right, EAX\r
29461         ADD      [EBX].TControl.fCommandActions.aAutoSzX, AX\r
29462         JMP      @@noWidthResize\r
29463 @@addWLeft:\r
29464         // then\r
29465         ADD      EAX, [EBX].TControl.fBoundsRect.Left\r
29466         MOV      [EBX].TControl.fBoundsRect.Right, EAX\r
29467         MOV      byte ptr [EBX].TControl.fCommandActions.aAutoSzX, 0\r
29468 @@noWidthResize:\r
29469         TEST     EDX, EDX\r
29470         JLE      @@noHeightResize\r
29471         CMP      [Layout], glyphTop\r
29472         JE       @@addHBottom\r
29473         CMP      [Layout], glyphBottom\r
29474         JNE      @@addHTop\r
29475 @@addHBottom:\r
29476         ADD      [EBX].TControl.fBoundsRect.Bottom, EDX\r
29477         ADD      [EBX].TControl.fCommandActions.aAutoSzY, DX\r
29478         JMP      @@noHeightResize\r
29479 @@addHTop:\r
29480         ADD      EDX, [EBX].TControl.fBoundsRect.Top\r
29481         MOV      [EBX].TControl.fBoundsRect.Bottom, EDX\r
29482         MOV      [EBX].TControl.fCommandActions.aAutoSzY, 0\r
29483 @@noHeightResize:\r
29484         POP      ECX\r
29485         POP      EAX\r
29486         CDQ\r
29487         MOV      DL, 4\r
29488         TEST     [EBX].TControl.fBitBtnOptions, 2 //1 shl bboNoBorder\r
29489         JNZ      @@noBorderResize\r
29490         JECXZ    @@noBorderWinc\r
29491         ADD      [EBX].TControl.fBoundsRect.Right, EDX\r
29492         CMP      [EBX].TControl.fCommandActions.aAutoSzX, 0\r
29493         JZ       @@noBorderWinc\r
29494         ADD      [EBX].TControl.fCommandActions.aAutoSzX, DX\r
29495 @@noBorderWinc:\r
29496         TEST     EAX, EAX\r
29497         JLE      @@noBorderResize\r
29498         ADD      [EBX].TControl.fBoundsRect.Bottom, EDX\r
29499         CMP      [EBX].TControl.fCommandActions.aAutoSzY, 0\r
29500         JZ       @@noBorderResize\r
29501         ADD      [EBX].TControl.fCommandActions.aAutoSzY, DX\r
29502 @@noBorderResize:\r
29503 @@noGlyphWH:\r
29504         MOV      ECX, [EBX].TControl.fParent\r
29505         JECXZ    @@notAttach2Parent\r
29506         XCHG     EAX, ECX\r
29507         MOV      EDX, offset[WndProc_DrawItem]\r
29508         CALL     TControl.AttachProc\r
29509 @@notAttach2Parent:\r
29510         MOV      EAX, EBX\r
29511         MOV      EDX, offset[WndProcBitBtn]\r
29512         CALL     TControl.AttachProc\r
29513         MOV      EAX, EBX\r
29514         POP      EDX\r
29515         CALL     TControl.SetCaption\r
29516         MOV      [EBX].TControl.fTextAlign, taCenter\r
29517         {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}\r
29518         MOV      EAX, EBX\r
29519         MOV      EDX, offset[WndProcBtnReturnClick]\r
29520         CALL     TControl.AttachProc\r
29521         {$ENDIF}\r
29522         XCHG     EAX, EBX\r
29523         POP      EBX\r
29524 end;\r
29525 {$ELSE ASM_VERSION} //Pascal\r
29526 function NewBitBtn( AParent: PControl; const Caption: String;\r
29527          Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap;\r
29528          GlyphCount: Integer ): PControl;\r
29529 var\r
29530     B: TBitmapInfo;\r
29531     W, H: Integer;\r
29532 begin\r
29533   Result := _NewControl( AParent, 'BUTTON', WS_VISIBLE or WS_CHILD or\r
29534             WS_TABSTOP or BS_OWNERDRAW, False, @ButtonActions );\r
29535   Result.fIgnoreDefault := TRUE;\r
29536   Result.fIsButton := TRUE;\r
29537   Result.fCommandActions.aAutoSzX := 8;\r
29538   Result.fCommandActions.aAutoSzY := 8;\r
29539   //Result.fExStyle := Result.fExStyle and not WS_EX_CONTROLPARENT;\r
29540   Result.fBitBtnOptions := Options;\r
29541   Result.fGlyphLayout := Layout;\r
29542   Result.fGlyphBitmap := GlyphBitmap;\r
29543   with Result.fBoundsRect do\r
29544   begin\r
29545     Bottom := Top + 22;\r
29546     W := 0; H := 0;\r
29547     if GlyphBitmap <> 0 then\r
29548     begin\r
29549       if bboImageList in Options then\r
29550         ImageList_GetIconSize( GlyphBitmap, W, H )\r
29551       else\r
29552         begin\r
29553           if GetObject( GlyphBitmap, Sizeof(B), @B ) > 0 then\r
29554           begin\r
29555             W := B.bmiHeader.biWidth;\r
29556             H := B.bmiHeader.biHeight;\r
29557             if GlyphCount = 0 then\r
29558               GlyphCount := W div H;\r
29559             if GlyphCount > 1 then\r
29560               W := W div GlyphCount;\r
29561           end;\r
29562         end;\r
29563       if W > 0 then\r
29564       begin\r
29565         if (Caption = '') or (Layout = glyphOver) then\r
29566         begin\r
29567           Right := Left + W;\r
29568           Result.fCommandActions.aAutoSzX := 0;\r
29569         end\r
29570           else\r
29571         if Layout in [ glyphLeft, glyphRight ] then\r
29572         begin\r
29573           Right := Right + W;\r
29574           Inc( Result.fCommandActions.aAutoSzX, W );\r
29575         end;\r
29576       end;\r
29577       if H > 0 then\r
29578       begin\r
29579         if Layout in [ glyphTop, glyphBottom ] then\r
29580         begin\r
29581           Bottom := Bottom + H;\r
29582           Inc( Result.fCommandActions.aAutoSzY, H );\r
29583         end\r
29584           else\r
29585         begin\r
29586           Bottom := Top + H;\r
29587           Result.fCommandActions.aAutoSzY := 0;\r
29588         end;\r
29589       end;\r
29590       if not ( bboNoBorder in Options ) then\r
29591       begin\r
29592         if W > 0 then\r
29593         begin\r
29594           Inc( Right, 4 );\r
29595           if Result.fCommandActions.aAutoSzX > 0 then\r
29596             Inc( Result.fCommandActions.aAutoSzX, 4 );\r
29597         end;\r
29598         if H > 0 then\r
29599         begin\r
29600           Inc( Bottom, 4 );\r
29601           if Result.fCommandActions.aAutoSzY > 0 then\r
29602             Inc( Result.fCommandActions.aAutoSzY, 4 );\r
29603         end;\r
29604       end;\r
29605     end;\r
29606     Result.fGlyphWidth := W;\r
29607     Result.fGlyphHeight := H;\r
29608   end;\r
29609   Result.fGlyphCount := GlyphCount;\r
29610   if AParent <> nil then\r
29611     AParent.AttachProc( WndProc_DrawItem );\r
29612   Result.AttachProc( WndProcBitBtn );\r
29613   //Result.AttachProc( WndProcDoEraseBkgnd );\r
29614   Result.fTextAlign := taCenter;\r
29615   Result.Caption := Caption;\r
29616   {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}\r
29617   Result.AttachProc( WndProcBtnReturnClick );\r
29618   {$ENDIF}\r
29619 end;\r
29620 {$ENDIF ASM_VERSION}\r
29621 //[END NewBitBtn]\r
29623 {$ENDIF USE_CONSTRUCTORS}\r
29625 //===================== Check box ========================//\r
29627 {$IFDEF USE_CONSTRUCTORS}\r
29628 //[function NewCheckbox]\r
29629 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;\r
29630 begin\r
29631   new( Result, CreateCheckbox( AParent, Caption ) );\r
29632 end;\r
29633 //[END NewCheckbox]\r
29634 {$ELSE not_USE_CONSTRUCTORS}\r
29636 //[FUNCTION NewCheckbox]\r
29637 {$IFDEF ASM_VERSION}\r
29638 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;\r
29639 asm\r
29640         CALL     NewButton\r
29641         MOV      EDX, [EAX].TControl.fBoundsRect.Left\r
29642         ADD      EDX, 72\r
29643         MOV      [EAX].TControl.fBoundsRect.Right, EDX\r
29644         MOV      [EAX].TControl.fStyle, WS_VISIBLE or WS_CHILD or BS_AUTOCHECKBOX or WS_TABSTOP\r
29645         MOV      [EAX].TControl.fCommandActions.aAutoSzX, 24\r
29646 end;\r
29647 {$ELSE ASM_VERSION} //Pascal\r
29648 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;\r
29649 begin\r
29650   Result := NewButton( AParent, Caption );\r
29651   with Result.fBoundsRect do\r
29652   begin\r
29653     Right := Left + 72;\r
29654   end;\r
29655   Result.fStyle := WS_VISIBLE or WS_CHILD or\r
29656             BS_AUTOCHECKBOX or WS_TABSTOP;\r
29657   Result.fCommandActions.aAutoSzX := 24;\r
29658 end;\r
29659 {$ENDIF ASM_VERSION}\r
29660 //[END NewCheckbox]\r
29662 {$ENDIF USE_CONSTRUCTORS}\r
29664 //[function NewCheckBox3State]\r
29665 function NewCheckBox3State( AParent: PControl; const Caption: String ): PControl;\r
29666 begin\r
29667   Result := NewCheckbox( AParent, Caption );\r
29668   Result.fStyle := Result.fStyle and not BS_AUTOCHECKBOX or BS_AUTO3STATE;\r
29669 end;\r
29671 //===================== Radiobox ========================//\r
29673 //[FUNCTION ClickRadio]\r
29674 {$IFDEF ASM_VERSION}\r
29675 procedure ClickRadio( Sender:PObj );\r
29676 asm\r
29677         MOV      ECX, [EAX].TControl.fParent\r
29678         JECXZ    @@exit\r
29679         PUSH     [EAX].TControl.fMenu\r
29680         PUSH     [ECX].TControl.fRadioLast\r
29681         PUSH     [ECX].TControl.fRadio1st\r
29682         PUSH     [ECX].TControl.fHandle\r
29683         CALL     CheckRadioButton\r
29684 @@exit:\r
29685 end;\r
29686 {$ELSE ASM_VERSION} //Pascal\r
29687 procedure ClickRadio( Sender:PObj );\r
29688 var Self_:PControl;\r
29689 begin\r
29690   Self_ := PControl( Sender );\r
29691   if Self_.FParent <> nil then\r
29692     CheckRadioButton( Self_.fParent.fHandle,\r
29693                       Self_.fParent.fRadio1st,\r
29694                       Self_.fParent.fRadioLast,\r
29695                       Self_.fMenu );\r
29696 end;\r
29697 {$ENDIF ASM_VERSION}\r
29698 //[END ClickRadio]\r
29700 {$IFDEF USE_CONSTRUCTORS}\r
29701 //[function NewRadiobox]\r
29702 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;\r
29703 begin\r
29704   new( Result, CreateRadiobox( AParent, Caption ) );\r
29705 end;\r
29706 //[END NewRadiobox]\r
29707 {$ELSE not_USE_CONSTRUCTORS}\r
29709 //[FUNCTION NewRadiobox]\r
29710 {$IFDEF ASM_VERSION}\r
29711 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;\r
29712 const\r
29713   RadioboxStyles = WS_VISIBLE or WS_CHILD or BS_RADIOBUTTON or\r
29714                    WS_TABSTOP or WS_GROUP or BS_NOTIFY;\r
29715 asm\r
29716         PUSH     EBX\r
29717         PUSH     EAX\r
29718         CALL     NewCheckbox\r
29719         XCHG     EBX, EAX\r
29720         MOV      [EBX].TControl.fStyle, RadioboxStyles\r
29721         MOV      [EBX].TControl.fControlClick, offset[ClickRadio]\r
29722         POP      ECX\r
29723         JECXZ    @@exit\r
29724         MOV      EDX, [EBX].TControl.fMenu\r
29725         MOV      [ECX].TControl.fRadioLast, EDX\r
29726         MOV      EAX, [ECX].TControl.fRadio1st\r
29727         TEST     EAX, EAX\r
29728         JNZ      @@exit\r
29729         MOV      [ECX].TControl.fRadio1st, EDX\r
29730         MOV      EAX, EBX\r
29731         CALL     TControl.SetRadioChecked\r
29732 @@exit: XCHG     EAX, EBX\r
29733         POP      EBX\r
29734 end;\r
29735 {$ELSE ASM_VERSION} //Pascal\r
29736 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;\r
29737 begin\r
29738   Result := NewCheckbox( AParent, Caption );\r
29739   Result.fStyle := WS_VISIBLE or WS_CHILD or\r
29740             BS_RADIOBUTTON or WS_TABSTOP or WS_GROUP or BS_NOTIFY;\r
29741   Result.fControlClick := ClickRadio;\r
29742   if AParent <> nil then\r
29743   begin\r
29744     AParent.fRadioLast := Result.fMenu;\r
29745     if AParent.fRadio1st = 0 then\r
29746     begin\r
29747        AParent.fRadio1st := Result.fMenu;\r
29748        Result.SetRadioChecked;\r
29749     end;\r
29750   end;\r
29751 end;\r
29752 {$ENDIF ASM_VERSION}\r
29753 //[END NewRadiobox]\r
29755 {$ENDIF USE_CONSTRUCTORS}\r
29757 //===================== Label ========================//\r
29759 {$IFNDEF USE_CONSTRUCTORS}\r
29760 {$IFDEF ASM_VERSION}\r
29761 const StaticClass: array[0..6]of Char=('S','T','A','T','I','C',#0);\r
29762 {$ENDIF ASM_VERSION}\r
29763 {$ENDIF USE_CONSTRUCTORS}\r
29765 {$IFDEF USE_CONSTRUCTORS}\r
29766 //[function NewLabel]\r
29767 function NewLabel( AParent: PControl; const Caption: String ): PControl;\r
29768 begin\r
29769   new( Result, CreateLabel( AParent, Caption ) );\r
29770 end;\r
29771 //[END NewLabel]\r
29772 {$ELSE not_USE_CONSTRUCTORS}\r
29774 //[FUNCTION NewLabel]\r
29775 {$IFDEF ASM_VERSION}\r
29776 function NewLabel( AParent: PControl; const Caption: String ): PControl;\r
29777 asm\r
29778         PUSH     EDX\r
29780         PUSH     0\r
29781         PUSH     offset[LabelActions]\r
29782         MOV      ECX, WS_VISIBLE or WS_CHILD or SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY\r
29783         MOV      EDX, offset[StaticClass]\r
29784         CALL     _NewControl\r
29785         INC      [EAX].TControl.fIsStaticControl\r
29786         INC      [EAX].TControl.fSizeRedraw\r
29787         MOV      EDX, [EAX].TControl.fBoundsRect.Top\r
29788         ADD      EDX, 22\r
29789         MOV      [EAX].TControl.fBoundsRect.Bottom, EDX\r
29790         POP      EDX\r
29791         PUSH     EAX\r
29792         CALL     TControl.SetCaption\r
29793         POP      EAX\r
29794 end;\r
29795 {$ELSE ASM_VERSION} //Pascal\r
29796 function NewLabel( AParent: PControl; const Caption: String ): PControl;\r
29797 begin\r
29798   Result := _NewControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or\r
29799                          SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY,\r
29800                          False, @LabelActions );\r
29801   Result.fIsStaticControl := True;\r
29802   Result.fSizeRedraw := True;\r
29803   with Result.fBoundsRect do\r
29804   begin\r
29805     //Right := Left + 64;\r
29806     Bottom := Top + 22;\r
29807   end;\r
29808   Result.Caption := Caption;\r
29809 end;\r
29810 {$ENDIF ASM_VERSION}\r
29811 //[END NewLabel]\r
29813 {$ENDIF USE_CONSTRUCTORS}\r
29815 //===================== word wrap Label ========================//\r
29817 {$IFDEF USE_CONSTRUCTORS}\r
29818 //[function NewWordWrapLabel]\r
29819 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;\r
29820 begin\r
29821   new( Result, CreateWordWrapLabel( AParent, Caption ) );\r
29822 end;\r
29823 //[END NewWordWrapLabel]\r
29824 {$ELSE not_USE_CONSTRUCTORS}\r
29826 //[FUNCTION NewWordWrapLabel]\r
29827 {$IFDEF ASM_VERSION}\r
29828 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;\r
29829 asm\r
29830         CALL     NewLabel\r
29831         MOV      EDX, [EAX].TControl.fBoundsRect.Top\r
29832         ADD      EDX, 44\r
29833         MOV      [EAX].TControl.fBoundsRect.Bottom, EDX\r
29834         INC      [EAX].TControl.fWordWrap\r
29835         AND      byte ptr [EAX].TControl.fStyle, not SS_LEFTNOWORDWRAP\r
29836 end;\r
29837 {$ELSE ASM_VERSION} //Pascal\r
29838 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;\r
29839 begin\r
29840   Result := NewLabel( AParent, Caption );\r
29841   Result.fWordWrap := TRUE;\r
29842   with Result.fBoundsRect do\r
29843   begin\r
29844     Bottom := Top + 44;\r
29845   end;\r
29846   Result.fStyle := Result.fStyle and not SS_LEFTNOWORDWRAP;\r
29847 end;\r
29848 {$ENDIF ASM_VERSION}\r
29849 //[END NewWordWrapLabel]\r
29851 {$ENDIF USE_CONSTRUCTORS}\r
29853 //===================== Label Effect ========================//\r
29855 {$IFDEF USE_CONSTRUCTORS}\r
29856 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;\r
29857 begin\r
29858   new( Result, CreateLabelEffect( AParent, Caption, ShadowDeep ) );\r
29859 end;\r
29860 {$ELSE not_USE_CONSTRUCTORS}\r
29862 //[FUNCTION NewLabelEffect]\r
29863 {$IFDEF ASM_VERSION}\r
29864 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;\r
29865 asm\r
29866         PUSH     EBX\r
29868         PUSH     ECX\r
29869         PUSH     EDX\r
29870         XOR      EDX, EDX\r
29871         CALL     NewLabel\r
29872         MOV      EBX, EAX\r
29873         DEC      [EBX].TControl.fIsStaticControl\r
29874         MOV      EDX, offset[WndProcLabelEffect]\r
29875         CALL     TControl.AttachProc\r
29877         //MOV      EAX, EBX\r
29878         //CALL     TControl.GetWindowHandle\r
29880         POP      EDX\r
29881         MOV      EAX, EBX\r
29882         CALL     TControl.SetCaption\r
29884         MOV      EDX, offset[WndProcDoEraseBkgnd]\r
29885         MOV      EAX,EBX\r
29886         CALL     TControl.AttachProc\r
29887         MOV      [EBX].TControl.fTextAlign, taCenter\r
29888         MOV      [EBX].TControl.fTextColor, clWindowText\r
29889         POP      [EBX].TControl.fShadowDeep\r
29890         INC      [EBX].TControl.fIgnoreWndCaption\r
29891         ADD      [EBX].TControl.fBoundsRect.Bottom, 40 - 22\r
29892         MOV      [EBX].TControl.fColor2, clNone\r
29894         XCHG     EAX, EBX\r
29895         POP      EBX\r
29896 end;\r
29897 {$ELSE ASM_VERSION} //Pascal\r
29898 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;\r
29899 begin\r
29900   Result := NewLabel( AParent, '' );\r
29901   Result.fIsStaticControl := False;\r
29902   Result.AttachProc( WndProcLabelEffect );\r
29903   //Result.GetWindowHandle;\r
29904   Result.Caption := Caption;\r
29905   Result.AttachProc( WndProcDoEraseBkgnd );\r
29906   Result.fTextAlign := taCenter;\r
29907   Result.fTextColor := clWindowText;\r
29908   Result.fShadowDeep := ShadowDeep;\r
29909   Result.fIgnoreWndCaption := True;\r
29910   with Result.fBoundsRect do\r
29911   begin\r
29912     Bottom := Top + 40;\r
29913   end;\r
29914   Result.fColor2 := clNone;\r
29915 end;\r
29916 {$ENDIF ASM_VERSION}\r
29917 //[END NewLabelEffect]\r
29919 {$ENDIF USE_CONSTRUCTORS}\r
29921 //===================== Paint box ========================//\r
29923 {$IFDEF USE_CONSTRUCTORS}\r
29924 //[function NewPaintbox]\r
29925 function NewPaintbox( AParent: PControl ): PControl;\r
29926 begin\r
29927   new( Result, CreatePaintBox( AParent ) );\r
29928 end;\r
29929 {$ELSE not_USE_CONSTRUCTORS}\r
29931 //[FUNCTION NewPaintbox]\r
29932 {$IFDEF ASM_VERSION}\r
29933 function NewPaintbox( AParent: PControl ): PControl;\r
29934 asm\r
29935         XOR      EDX, EDX\r
29936         CALL     NewLabel\r
29937         //PUSH     EAX\r
29938         //MOV      EDX, offset[WndProcPaintBox]\r
29939         //CALL     TControl.AttachProc\r
29940         //POP      EAX\r
29941         ADD      [EAX].TControl.fBoundsRect.Right, 40-64\r
29942         ADD      [EAX].TControl.fBoundsRect.Bottom, 40-22\r
29943 end;\r
29944 {$ELSE ASM_VERSION} //Pascal\r
29945 function NewPaintbox( AParent: PControl ): PControl;\r
29946 begin\r
29947   Result := NewLabel( AParent, '' );\r
29948   //Result.AttachProc( WndProcPaintBox );\r
29949   with Result.fBoundsRect do\r
29950   begin\r
29951     Right := Left + 40;\r
29952     Bottom := Top + 40;\r
29953   end;\r
29954 end;\r
29955 {$ENDIF ASM_VERSION}\r
29956 //[END NewPaintbox]\r
29958 {$ENDIF USE_CONSTRUCTORS}\r
29960 {$IFDEF _D2}\r
29961 //[API SetBrushOrgEx]\r
29962 function SetBrushOrgEx(DC: HDC; X, Y: Integer; PrevPt: PPoint): BOOL; stdcall;\r
29963 external gdi32 name 'SetBrushOrgEx';\r
29964 {$ENDIF}\r
29966 //[FUNCTION WndProcDoEraseBkgnd]\r
29967 {$IFDEF ASM_VERSION}\r
29968 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
29969 asm     //        //\r
29970         CMP       word ptr [EDX].TMsg.message, WM_ERASEBKGND\r
29971         JNE       @@ret_false\r
29972         MOV       byte ptr [ECX], 1\r
29973         PUSH      EBX\r
29974         PUSH      EDI\r
29975         MOV       EBX, EAX\r
29976         MOV       EDI, [EDX].TMsg.wParam\r
29978         CALL      TControl.CreateChildWindows\r
29979         CMP       [EBX].TControl.fTransparent, 0\r
29980         JNE       @@exit\r
29982         PUSH      OPAQUE\r
29983         PUSH      EDI\r
29984         CALL      SetBkMode\r
29985         MOV       EAX, [EBX].TControl.fColor\r
29986         CALL      Color2RGB\r
29987         PUSH      EAX\r
29988         PUSH      EDI\r
29989         CALL      SetBkColor\r
29990         XOR       EAX, EAX\r
29991         PUSH      EAX\r
29992         PUSH      EAX\r
29993         PUSH      EAX\r
29994         PUSH      EDI\r
29995         CALL      SetBrushOrgEx\r
29996         SUB       ESP, 16\r
29997         PUSH      ESP\r
29998         PUSH      [EBX].TControl.fHandle\r
29999         CALL      GetClientRect\r
30000         MOV       EAX, EBX\r
30001         CALL      dword ptr[Global_GetCtlBrushHandle]\r
30002         MOV       EDX, ESP\r
30003         PUSH      EAX\r
30004         PUSH      EDX\r
30005         PUSH      EDI\r
30006         CALL      Windows.FillRect\r
30007         ADD       ESP, 16\r
30008 @@exit: POP       EDI\r
30009         POP       EBX\r
30010 @@ret_false:\r
30011         XOR       EAX, EAX\r
30012 end;\r
30013 {$ELSE ASM_VERSION PAS_VERSION}\r
30014 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
30015 var DC: HDC;\r
30016     R: TRect;\r
30017 begin\r
30018   Result := FALSE;\r
30019   if Msg.message = WM_ERASEBKGND then\r
30020   begin\r
30021     Self_.CreateChildWindows;\r
30022     if Self_.Transparent then Exit;\r
30023     DC := Msg.wParam;\r
30024     SetBkMode( DC, OPAQUE );\r
30025     SetBkColor( DC, Color2RGB( Self_.fColor ) );\r
30026     SetBrushOrgEx( DC, 0, 0, nil );\r
30027     GetClientRect( Self_.fHandle, R );\r
30028     Windows.FillRect( DC, R, Global_GetCtlBrushHandle( Self_ ) );\r
30029     Rslt := 1;\r
30030   end;\r
30031 end;\r
30032 {$ENDIF ASM_VERSION}\r
30033 //[END WndProcDoEraseBkgnd]\r
30035 //[function WndProcImageShow]\r
30036 function WndProcImageShow( Sender: PControl; var Msg: TMsg;\r
30037          var Rslt: Integer ): Boolean;\r
30038 var PaintStruct: TPaintStruct;\r
30039     IL: PImageList;\r
30040     OldPaintDC: HDC;\r
30041 begin\r
30042   Result := FALSE;\r
30043   if (Msg.message = WM_PAINT) or (Msg.message = WM_PRINT) then\r
30044   begin\r
30045     OldPaintDC := Sender.fPaintDC;\r
30046     Sender.fPaintDC := Msg.wParam;\r
30047     if Sender.fPaintDC = 0 then\r
30048       Sender.fPaintDC := BeginPaint( Sender.fHandle, PaintStruct );\r
30049     //fOnPaint( Self_, fPaintDC );\r
30050     IL := Sender.ImageListNormal;\r
30051     if IL <> nil then\r
30052     begin\r
30053       IL.Draw( Sender.fCurIndex, Sender.fPaintDC, 0, 0 );\r
30054       Result := TRUE;\r
30055     end;\r
30056     if Msg.wParam = 0 then\r
30057       EndPaint( Sender.fHandle, PaintStruct );\r
30058     Sender.fPaintDC := OldPaintDC;\r
30059     Rslt := 0;\r
30060     //Result := True;\r
30061     Exit;\r
30062   end;\r
30063 end;\r
30065 //[function NewImageShow]\r
30066 function NewImageShow( AParent: PControl; AImgList: PImageList;\r
30067          ImgIdx: Integer ): PControl;\r
30068 var W, H: Integer;\r
30069 begin\r
30070   Result := NewLabel( AParent, '' );\r
30071   Result.ImageListNormal := AImgList;\r
30072   Result.AttachProc( WndProcImageShow );\r
30073   Result.AttachProc( WndProcDoEraseBkgnd );\r
30074   W := 32; H := 32;\r
30075   if AImgList <> nil then\r
30076   begin\r
30077     W := AImgList.ImgWidth;\r
30078     H := AImgList.ImgHeight;\r
30079   end;\r
30080   with Result.fBoundsRect do\r
30081   begin\r
30082     Right := Left + W;\r
30083     Bottom := Top + H;\r
30084   end;\r
30085 end;\r
30086 //[END NewImageShow]\r
30088 //===================== Scrollbar ========================//\r
30089 const\r
30090   KSB_INITIALIZE = WM_USER + 10000;\r
30091   KSB_KEY = $3232;\r
30093 //[function WndProcScrollBar]\r
30094 function WndProcScrollBar( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
30095 begin\r
30096   Result := False;\r
30097   case Msg.message of\r
30098     WM_CREATE:\r
30099       PostMessage(Sender.Handle, KSB_INITIALIZE, KSB_KEY, KSB_KEY);\r
30101     KSB_INITIALIZE:\r
30102       if (Msg.wParam = Msg.lParam) and (Msg.wParam = KSB_KEY) then\r
30103       begin\r
30104         Sender.SBPageSize := Sender.fSBPageSize;\r
30105         Sender.SBMinMax := Sender.fSBMinMax;\r
30106         Sender.SBPosition := Sender.fSBPosition;\r
30107       end;\r
30108   end;\r
30109 end;\r
30110 //[END WndProcScrollBar]\r
30112 //[function WndProcScrollBarParent]\r
30113 function WndProcScrollBarParent( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
30114 var\r
30115   Bar: PControl;\r
30116   SI: TScrollInfo;\r
30117   NewPos: Integer;\r
30118   AllowChange: Boolean;\r
30119   Cmd: Word;\r
30121 begin\r
30122   Result := False;\r
30123   case Msg.message of\r
30124     WM_HSCROLL, WM_VSCROLL:\r
30125     if (Msg.lParam <> 0) then begin\r
30126       Bar := Pointer(GetProp(Msg.lParam, ID_SELF));\r
30127       if (Bar <> nil) then begin\r
30128         FillChar(SI, SizeOf(SI), 0);\r
30129         SI.cbSize := SizeOf(SI);\r
30130         SI.fMask := SIF_RANGE or SIF_POS or SIF_TRACKPOS or SIF_PAGE;\r
30131         Bar.SBGetScrollInfo(SI);\r
30133         Cmd := Msg.wParam and $0000FFFF;\r
30134         case Cmd of\r
30135           SB_BOTTOM: NewPos := SI.nMax;\r
30136           SB_TOP: NewPos := SI.nMin;\r
30137           SB_LINEDOWN: NewPos := SI.nPos + 1;\r
30138           SB_LINEUP: NewPos := SI.nPos - 1;\r
30139           SB_PAGEDOWN: NewPos := SI.nPos + Integer(SI.nPage);\r
30140           SB_PAGEUP: NewPos := SI.nPos - Integer(SI.nPage);\r
30141           SB_THUMBTRACK: NewPos := SI.nTrackPos;\r
30142           else\r
30143             Exit;\r
30144         end;\r
30146         if (NewPos > SI.nMax - Integer(SI.nPage) + 1) then\r
30147           NewPos := SI.nMax - Integer(SI.nPage) + 1;\r
30148         if (NewPos < SI.nMin) then\r
30149           NewPos := SI.nMin;\r
30151         AllowChange := True;\r
30152         if Assigned(Bar.OnSBBeforeScroll) then\r
30153           Bar.OnSBBeforeScroll(Bar, SI.nPos, NewPos, Cmd, AllowChange);\r
30154         if AllowChange then\r
30155           SI.nPos := NewPos\r
30156         else\r
30157           SI.nTrackPos := SI.nPos;\r
30158         Bar.fSBPosition := SI.nPos;\r
30159         Bar.fSBPosition := Bar.SBSetScrollInfo(SI);\r
30160         if AllowChange and Assigned(Bar.OnSBScroll) then\r
30161             Bar.OnSBScroll(Bar, Cmd);\r
30162       end;\r
30163     end;\r
30164   end;\r
30165 end;\r
30166 //[END WndProcScrollBarParent]\r
30168 //[function NewScrollBar]\r
30169 function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;\r
30170 const SBS_Directions: array[ TScrollerBar ] of DWORD = ( SBS_HORZ or SBS_BOTTOMALIGN,\r
30171       SBS_VERT or SBS_RIGHTALIGN );\r
30172 begin\r
30173   Result := _NewCommonControl(\r
30174     AParent,\r
30175     'SCROLLBAR',\r
30176     WS_VISIBLE or WS_CHILD or SBS_Directions[ BarSide ],\r
30177     False,\r
30178     nil\r
30179   );\r
30180   Result.DetachProc(WndProcCtrl);\r
30181   Result.fLookTabKeys := [tkTab];\r
30182   Result.AttachProc(WndProcScrollBar);\r
30183   AParent.AttachProc(WndProcScrollBarParent);\r
30184 end;\r
30185 //[END NewScrollBar]\r
30187 //===================== Scrollbox ========================//\r
30188 //[function WndProcScrollBox]\r
30189 function WndProcScrollBox( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
30190 var Bar: DWORD;\r
30191     SI: TScrollInfo;\r
30192     OldNotifyProc: pointer;\r
30193 begin\r
30195   case Msg.message of\r
30196   WM_HSCROLL: Bar := SB_HORZ;\r
30197   WM_VSCROLL: Bar := SB_VERT;\r
30198   WM_SIZE: begin\r
30199               if Assigned( Sender.fNotifyChild ) then\r
30200                 Sender.fNotifyChild( Sender, nil );\r
30201               Result := FALSE;\r
30202               Exit;\r
30203            end;\r
30204   else begin\r
30205          Result := FALSE;\r
30206          Exit;\r
30207        end;\r
30208   end;\r
30210   SI.cbSize := Sizeof( SI );\r
30211   SI.fMask := SIF_RANGE or SIF_POS or SIF_PAGE or\r
30212               {$IFDEF F_P}$10{$ELSE}SIF_TRACKPOS{$ENDIF};\r
30213   {$IFDEF _D2}\r
30214   GetScrollInfo( Sender.fHandle, Bar, SI );\r
30215   {$ELSE}\r
30216   GetScrollInfo( Sender.fHandle, Bar, SI );\r
30217   {$ENDIF}\r
30218   SI.fMask := SIF_POS;\r
30219   case LoWord( Msg.wParam ) of\r
30220   SB_BOTTOM:    SI.nPos := SI.nMax;\r
30221   SB_TOP:       SI.nPos := SI.nMin;\r
30222   SB_LINEDOWN:  Inc( SI.nPos, Sender.FScrollLineDist[ Bar ] );\r
30223   SB_LINEUP:    Dec( SI.nPos, Sender.FScrollLineDist[ Bar ] );\r
30224   SB_PAGEDOWN:  Inc( SI.nPos, Max( SI.nPage, 1 ) );\r
30225   SB_PAGEUP:    Dec( SI.nPos, Max( SI.nPage, 1 ) );\r
30226   SB_THUMBTRACK:SI.nPos := SI.nTrackPos;\r
30227   end;\r
30228   if SI.nPos > SI.nMax { - Integer( SI.nPage ) } then\r
30229     SI.nPos := SI.nMax { - Integer( SI.nPage ) };\r
30230   if SI.nPos < SI.nMin then\r
30231     SI.nPos := SI.nMin;\r
30232   SetScrollInfo( Sender.fHandle, Bar, SI, TRUE );\r
30234   if Assigned( Sender.fScrollChildren ) then\r
30235   begin\r
30236     OldNotifyProc := @ Sender.fNotifyChild;\r
30237     Sender.fNotifyChild := nil;\r
30238     Sender.fScrollChildren( Sender );\r
30239     Sender.fNotifyChild := OldNotifyProc;\r
30240   end;\r
30242   SetScrollInfo( Sender.fHandle, Bar, SI, TRUE );\r
30243   Result := FALSE;\r
30244 end;\r
30245 //[END WndProcScrollBox]\r
30247 //[function NewScrollBox]\r
30248 function NewScrollBox( AParent: PControl; EdgeStyle: TEdgeStyle;\r
30249          Bars: TScrollerBars ): PControl;\r
30250 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 );\r
30251 var SBFlag: Integer;\r
30252 begin\r
30253   SBFlag := EdgeStyles[ EdgeStyle ];\r
30254   if sbHorizontal in Bars then\r
30255     SBFlag := SBFlag or WS_HSCROLL;\r
30256   if sbVertical in Bars then\r
30257     SBFlag := SBFlag or WS_VSCROLL;\r
30259   Result := _NewControl( AParent, 'ScrollBox', WS_VISIBLE or WS_CHILD or\r
30260          SBFlag, EdgeStyle = esLowered, nil );\r
30261   Result.AttachProc( WndProcForm ); //!!!\r
30262   Result.AttachProc( WndProcScrollBox );\r
30263   Result.AttachProc( WndProcDoEraseBkgnd );\r
30264   Result.fIsControl := TRUE;\r
30265 end;\r
30266 //[END NewScrollBox]\r
30268 //[function WndProcNotifyParentAboutResize]\r
30269 function WndProcNotifyParentAboutResize( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
30270 var P: PControl;\r
30271 begin\r
30272   if (Msg.message = WM_SIZE) or (Msg.message = WM_MOVE) or (Msg.message = CM_SHOW) then\r
30273   begin\r
30274     P := Sender.Parent;\r
30275     if P <> nil then\r
30276       if Assigned( P.fNotifyChild ) then\r
30277         P.fNotifyChild( P, nil );\r
30278   end\r
30279     else\r
30280   if Msg.message = WM_SHOWWINDOW then\r
30281     PostMessage( Sender.fHandle, CM_SHOW, 0, 0 );\r
30282   Result := FALSE;\r
30283 end;\r
30285 //[procedure CalcMinMaxChildren]\r
30286 procedure CalcMinMaxChildren( Self_: PControl; var SzR: TRect );\r
30287 var I: Integer;\r
30288     C: PControl;\r
30289     R: TRect;\r
30290 begin\r
30291   Szr := MakeRect( 0, 0, 0, 0 );\r
30292   for I := 0 to Self_.fChildren.fCount - 1 do\r
30293   begin\r
30294     C := Self_.fChildren.fItems[ I ];\r
30295     if C.ToBeVisible then\r
30296     begin\r
30297       R := C.BoundsRect;\r
30298       if (SzR.Left = SzR.Right) or (R.Left < SzR.Left) or (R.Right > SzR.Right) then\r
30299       begin\r
30300         if SzR.Left = SzR.Right then\r
30301         begin\r
30302           SzR.Left := R.Left;\r
30303           SzR.Right := R.Right;\r
30304         end\r
30305           else\r
30306         begin\r
30307           if R.Left < SzR.Left then SzR.Left := R.Left;\r
30308           if R.Right > SzR.Right then SzR.Right := R.Right;\r
30309         end;\r
30310       end;\r
30311       if (SzR.Top = SzR.Bottom) or (R.Top < SzR.Top) or (R.Bottom > SzR.Bottom) then\r
30312       begin\r
30313         if SzR.Top = SzR.Bottom then\r
30314         begin\r
30315           SzR.Top := R.Top;\r
30316           SzR.Bottom := R.Bottom;\r
30317         end\r
30318           else\r
30319         begin\r
30320           if R.Top < SzR.Top then SzR.Top := R.Top;\r
30321           if R.Bottom > SzR.Bottom then SzR.Bottom := R.Bottom;\r
30322         end;\r
30323       end;\r
30324     end;\r
30325   end;\r
30326   Dec( SzR.Left, Self_.Border );\r
30327   Inc( SzR.Right, Self_.Border - 1 );\r
30328   Dec( SzR.Top, Self_.Border );\r
30329   Inc( SzR.Bottom, Self_.Border - 1 );\r
30330 end;\r
30332 //[procedure NotifyScrollBox]\r
30333 procedure NotifyScrollBox( Self_, Child: PControl );\r
30334 var SI: TScrollInfo;\r
30336     procedure GetSetScrollInfo( SBar: DWORD; WH, R_RightBottom, SzR_LeftTop, SzR_RightBottom: Integer );\r
30337     var OldPos: Double;\r
30338     begin\r
30339       OldPos := 0;\r
30340       if not GetScrollInfo( Self_.fHandle, SBar, SI ) then\r
30341       begin\r
30342         SI.nMin := 0;\r
30343         SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );\r
30344       end\r
30345         else\r
30346       begin\r
30347         if SI.nMax > SI.nMin then\r
30348         begin\r
30349           OldPos := (SI.nPos - SI.nMin) / (SI.nMax - SI.nMin);\r
30350           SI.nMin := 0;\r
30351           SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );\r
30352           if SzR_LeftTop < 0 then\r
30353             SI.nMax := Max( R_RightBottom - SzR_LeftTop - 1, WH - 1 );\r
30354         end\r
30355           else\r
30356         begin\r
30357           SI.nMin := 0;\r
30358           SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );\r
30359         end;\r
30360       end;\r
30361       SI.nPos := SI.nMin + Round( (SI.nMax - SI.nMin) * OldPos );\r
30362       SI.nPage := R_RightBottom;\r
30363       SetScrollInfo( Self_.fHandle, SBar, SI, TRUE );\r
30364     end;\r
30366 var W, H: Integer;\r
30367     SzR: TRect;\r
30368     R: TRect;\r
30369 begin\r
30370   if Assigned( Child ) then\r
30371   begin\r
30372     Child.AttachProc( WndProcNotifyParentAboutResize );\r
30373     Exit;\r
30374   end;\r
30375   CalcMinMaxChildren( Self_, SzR );\r
30376   W := SzR.Right - SzR.Left;\r
30377   H := SzR.Bottom - SzR.Top;\r
30379   R := Self_.ClientRect;\r
30380   if (R.Right = 0) or (R.Bottom = 0) then Exit; // for case when form is minimized\r
30381   SI.cbSize := sizeof( SI );\r
30382   SI.fMask := SIF_RANGE or SIF_PAGE or SIF_POS;\r
30384   GetSetScrollInfo( SB_HORZ, W, R.Right, SzR.Left, SzR.Right );\r
30385   GetSetScrollInfo( SB_VERT, H, R.Bottom, SzR.Top, SzR.Bottom );\r
30387 end;\r
30389 //[procedure ScrollChildren]\r
30390 procedure ScrollChildren( _Self_: PControl );\r
30391 var SzR, R: TRect;\r
30392     I, Xpos, Ypos: Integer;\r
30393     OldNotifyProc: Pointer;\r
30394     C: PControl;\r
30395     DeltaX, DeltaY: Integer;\r
30397 begin\r
30399   CalcMinMaxChildren( _Self_, SzR );\r
30400   Xpos := GetScrollPos( _Self_.fHandle, SB_HORZ );\r
30401   Ypos := GetScrollPos( _Self_.fHandle, SB_VERT );\r
30403   DeltaX := -Xpos - SzR.Left;\r
30404   DeltaY := -Ypos - SzR.Top;\r
30406   if (DeltaX <> 0) or (DeltaY <> 0) then\r
30407   begin\r
30409     OldNotifyProc := @ _Self_.fNotifyChild;\r
30410     _Self_.fNotifyChild := nil;\r
30412     for I := 0 to _Self_.fChildren.fCount - 1 do\r
30413     begin\r
30414       C := _Self_.fChildren.fItems[ I ];\r
30415       R := C.BoundsRect;\r
30416       OffsetRect( R, DeltaX, DeltaY  );\r
30417       C.BoundsRect := R;\r
30418     end;\r
30420     _Self_.fNotifyChild := OldNotifyProc;\r
30421     CalcMinMaxChildren( _Self_, R );\r
30422     if //(SzR.Left <> R.Left) or (SzR.Top <> R.Top) or\r
30423        //(Szr.Right <> R.Right) or (SzR.Bottom <> R.Bottom)\r
30424        ((SzR.Right - SzR.Left) <> (R.Right - R.Left)) or\r
30425        ((SzR.Bottom - SzR.Top) <> (R.Bottom - R.Top))\r
30426        then\r
30427     if Assigned( _Self_.fNotifyChild ) then\r
30428       _Self_.fNotifyChild( _Self_, nil );\r
30430   end;\r
30432 end;\r
30434 //[function NewScrollBoxEx]\r
30435 function NewScrollBoxEx( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;\r
30436 begin\r
30437   Result := NewScrollBox( AParent, EdgeStyle, [ ] );\r
30438   Result.fNotifyChild := NotifyScrollBox;\r
30439   Result.fScrollChildren := ScrollChildren;\r
30440   Result.FScrollLineDist[ 0 ] := 16;\r
30441   Result.FScrollLineDist[ 1 ] := 16;\r
30442 end;\r
30444 //[function WndProcOnScroll]\r
30445 function WndProcOnScroll( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
30446 var Bar: TScrollerBar;\r
30447 begin\r
30448   Bar := sbHorizontal; //0\r
30449   if Msg.message = WM_VSCROLL then\r
30450     Bar := sbVertical\r
30451   else\r
30452   if Msg.message <> WM_HSCROLL then\r
30453   begin\r
30454     Result := FALSE;\r
30455     Exit;\r
30456   end;\r
30458   if Assigned( Sender.OnScroll ) then\r
30459     Sender.OnScroll( Sender, Bar, LoWord( Msg.wParam ), HiWord( Msg.wParam ) );\r
30460   Result := FALSE;\r
30461 end;\r
30463 //[procedure TControl.SetOnScroll]\r
30464 procedure TControl.SetOnScroll(const Value: TOnScroll);\r
30465 begin\r
30466   FOnScroll := Value;\r
30467   AttachProc( @ WndProcOnScroll );\r
30468 end;\r
30470 //===================== Groupbox ========================//\r
30472 {$IFDEF USE_CONSTRUCTORS}\r
30473 //[function NewGroupbox]\r
30474 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;\r
30475 begin\r
30476   new( Result, CreateGroupbox( AParent, Caption ) );\r
30477 end;\r
30478 //[END NewGroupbox]\r
30479 {$ELSE not_USE_CONSTRUCTORS}\r
30481 //[FUNCTION NewGroupbox]\r
30482 {$IFDEF ASM_VERSION}\r
30483 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;\r
30484 asm\r
30485         PUSH     EDX\r
30486         PUSH     0\r
30487         PUSH     offset[ButtonActions]\r
30488         MOV      EDX, offset[ButtonClass]\r
30489         MOV      ECX, WS_VISIBLE or WS_CHILD or BS_GROUPBOX or WS_TABSTOP or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or WS_GROUP\r
30490         CALL     _NewControl\r
30491         OR       [EAX].TControl.fExStyle, WS_EX_CONTROLPARENT\r
30492         ADD      [EAX].TControl.fBoundsRect.Right, 100-64\r
30493         ADD      [EAX].TControl.fBoundsRect.Bottom, 100-22\r
30494         ADD      [EAX].TControl.fClientTop, 22\r
30495         XOR      EDX, EDX\r
30496         MOV      [EAX].TControl.fTabstop, DL\r
30497         MOV      DL, 2\r
30498         ADD      [EAX].TControl.fClientBottom, EDX\r
30499         ADD      [EAX].TControl.fClientLeft, EDX\r
30500         ADD      [EAX].TControl.fClientRight, EDX\r
30501         POP      EDX\r
30502         PUSH     EAX\r
30503         CALL     TControl.SetCaption\r
30504         POP      EAX\r
30505         PUSH     EAX\r
30506         MOV      EDX, offset[WndProcDoEraseBkgnd]\r
30507         CALL     TControl.AttachProc\r
30508         POP      EAX\r
30509 end;\r
30510 {$ELSE ASM_VERSION} //Pascal\r
30511 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;\r
30512 begin\r
30513   Result := _NewControl( AParent, 'BUTTON',\r
30514                    WS_CHILD or\r
30515                    WS_CLIPSIBLINGS or\r
30516                    WS_CLIPCHILDREN or\r
30517                    WS_TABSTOP or\r
30518                    WS_VISIBLE or\r
30519                    BS_NOTIFY or\r
30520                    BS_GROUPBOX\r
30521                    or WS_GROUP,\r
30522                    FALSE, @ ButtonActions );\r
30523   Result.fExStyle := Result.fExStyle or WS_EX_CONTROLPARENT;\r
30524   Result.Caption := Caption;\r
30525   with Result.fBoundsRect do\r
30526   begin\r
30527     Right := Left + 100;\r
30528     Bottom := Top + 100;\r
30529   end;\r
30530   Result.fClientTop := 22;\r
30531   Result.fClientBottom := 2;\r
30532   Result.fClientLeft := 2;\r
30533   Result.fClientRight := 2;\r
30534   Result.fTabstop := False;\r
30535   Result.AttachProc( WndProcDoEraseBkgnd );\r
30536 end;\r
30537 {$ENDIF ASM_VERSION}\r
30538 //[END NewGroupbox]\r
30540 {$ENDIF USE_CONSTRUCTORS}\r
30542 //===================== Panel ========================//\r
30544 {$IFDEF USE_CONSTRUCTORS}\r
30545 //[function NewPanel]\r
30546 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;\r
30547 begin\r
30548   new( Result, CreatePanel( AParent, EdgeStyle ) );\r
30549 end;\r
30550 //[END NewPanel]\r
30551 {$ELSE not_USE_CONSTRUCTORS}\r
30553 //[FUNCTION NewPanel]\r
30554 {$IFDEF ASM_VERSION}\r
30555 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;\r
30556 asm\r
30557         PUSH     EDX\r
30558         MOV      EDX, offset[StaticClass]\r
30559         MOV      ECX, WS_VISIBLE or WS_CHILD or SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY\r
30560         PUSH     0\r
30561         PUSH     offset[LabelActions]\r
30562         CALL     _NewControl\r
30563         ADD      [EAX].TControl.fBoundsRect.Right, 100-64\r
30564         ADD      [EAX].TControl.fBoundsRect.Bottom, 100-64\r
30565         OR       byte ptr [EAX].TControl.fExStyle+2, 1\r
30566         POP      ECX\r
30567         CMP      CL, 1\r
30568         JG       @@exit\r
30569         JE       @@sunken\r
30570         OR       byte ptr [EAX].TControl.fStyle+2, $40\r
30571         RET\r
30572 @@sunken:\r
30573         OR       byte ptr [EAX].TControl.fStyle+1, $10\r
30574 @@exit:\r
30575 end;\r
30576 {$ELSE ASM_VERSION} //Pascal\r
30577 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;\r
30578 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 );\r
30579 begin\r
30580   Result := _NewControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or SS_NOTIFY or\r
30581                          SS_LEFTNOWORDWRAP or SS_NOPREFIX, False, @LabelActions );\r
30582   with Result.fBoundsRect do\r
30583   begin\r
30584     Right := Left + 100;\r
30585     Bottom := Top + 100;\r
30586   end;\r
30587   Result.Style := Result.Style or Edgestyles[ EdgeStyle ];\r
30588   Result.ExStyle := Result.fExStyle or WS_EX_CONTROLPARENT;\r
30589   Result.fVerticalAlign := vaTop;\r
30590 end;\r
30591 {$ENDIF ASM_VERSION}\r
30592 //[END NewPanel]\r
30594 {$ENDIF USE_CONSTRUCTORS}\r
30596 //===================== Splitter ==============================//\r
30598 //{$DEFINE USE_ASM_DODRAG}\r
30600        {$IFNDEF USE_ASM_DODRAG}\r
30601          {$DEFINE USE_PAS_DODRAG}\r
30602        {$ENDIF}\r
30603        {$IFNDEF ASM_VERSION}\r
30604          {$DEFINE USE_PAS_DODRAG}\r
30605        {$ENDIF}\r
30606 {$IFDEF USE_PAS_DODRAG}\r
30607 //[procedure DoDrag]\r
30608 procedure DoDrag( Self_: PControl; Cancel: Boolean );\r
30609 var NewSize1, NewSize2: Integer;\r
30610     MousePos: TPoint;\r
30611     R: TRect;\r
30612     Prev: PControl;\r
30613     I, M : Integer;\r
30614 begin\r
30615   if Self_.fDragging then\r
30616   begin\r
30617     I := Self_.fParent.fChildren.IndexOf( Self_ );\r
30618     Prev := Self_;\r
30619     if I > 0 then\r
30620       Prev := Self_.FParent.fChildren.fItems[ I - 1 ];\r
30621     GetCursorPos( MousePos );\r
30622     if Cancel then\r
30623       MousePos := Self_.fSplitStartPos;\r
30624     M := 1;\r
30625     if Self_.FAlign in [ caRight, caBottom ] then\r
30626       M := -1;\r
30627     if Self_.FAlign in [ caTop, caBottom ] then\r
30628     begin\r
30629       NewSize1 := (MousePos.y - Self_.fSplitStartPos.y)* M\r
30630                 + Self_.fSplitStartSize;\r
30631       NewSize2 := Self_.fParent.ClientHeight - NewSize1\r
30632                 - Self_.fBoundsRect.Bottom + Self_.fBoundsRect.Top\r
30633                 - Self_.fParent.fMargin * 4;\r
30634       if Self_.fSecondControl <> nil then\r
30635       begin\r
30636         NewSize2 := Self_.fSecondControl.fBoundsRect.Bottom\r
30637                   - Self_.fSecondControl.fBoundsRect.Top;\r
30638         if Self_.fSecondControl.FAlign = caClient then\r
30639           NewSize2 := Self_.fSplitStartPos2.y\r
30640                     - (MousePos.y - Self_.fSplitStartPos.y)* M\r
30641                     - Self_.fParent.fMargin * 4;\r
30642       end;\r
30643     end\r
30644        else\r
30645     begin\r
30646       NewSize1 := (MousePos.x - Self_.fSplitStartPos.x)* M\r
30647                 + Self_.fSplitStartSize;\r
30648       NewSize2 := Self_.fParent.ClientWidth - NewSize1\r
30649                 - Self_.fBoundsRect.Right + Self_.fBoundsRect.Left\r
30650                 - Self_.fParent.fMargin * 4;\r
30651       if Self_.fSecondControl <> nil then\r
30652       begin\r
30653         NewSize2 := Self_.fSecondControl.fBoundsRect.Right\r
30654                   - Self_.fSecondControl.fBoundsRect.Left;\r
30655         if Self_.fSecondControl.FAlign = caClient then\r
30656           NewSize2 := Self_.fSplitStartPos2.x\r
30657                     - (MousePos.x - Self_.fSplitStartPos.x)* M\r
30658                     - Self_.fParent.Margin * 4;\r
30659       end;\r
30660     end;\r
30661     if {(Self_.fSplitMinSize1 <> 0) and} (NewSize1 < Self_.fSplitMinSize1) then\r
30662     begin\r
30663       Dec( NewSize2, Self_.fSplitMinSize1 - NewSize1 );\r
30664       NewSize1 := Self_.fSplitMinSize1;\r
30665     end;\r
30666     if {(Self_.fSplitMinSize2 <> 0) and} (NewSize2 < Self_.fSplitMinSize2) then\r
30667     begin\r
30668       Dec( NewSize1, Self_.fSplitMinSize2 - NewSize2 );\r
30669       NewSize2 := Self_.fSplitMinSize2;\r
30670     end;\r
30671     //if Self_.fSplitMinSize1 <> 0 then\r
30672       if NewSize1 < Self_.fSplitMinSize1 then Exit;\r
30673     //if Self_.fSplitMinSize2 <> 0 then\r
30674       if NewSize2 < Self_.fSplitMinSize2 then Exit;\r
30675     if assigned( Self_.fOnSplit ) then\r
30676       if not Self_.fOnSplit( Self_, NewSize1, NewSize2 ) then Exit;\r
30677     R := Prev.BoundsRect;\r
30678     case Self_.FAlign of\r
30679     caTop: R.Bottom := R.Top + NewSize1;\r
30680     caBottom: R.Top := R.Bottom - NewSize1;\r
30681     caRight: R.Left := R.Right - NewSize1;\r
30682     else R.Right := R.Left + NewSize1;\r
30683     end;\r
30684     Prev.BoundsRect := R;\r
30685     Global_Align( Self_.fParent );\r
30686   end;\r
30687 end;\r
30688 {$ENDIF}\r
30690 const\r
30691   chkLeft=2;\r
30692   chkTop=4;\r
30693   chkRight=8;\r
30694   chkBott=16;\r
30696 {$DEFINE USE!_ASM_DODRAG}\r
30698 //[FUNCTION WndProcSplitter]\r
30699 {$IFDEF ASM_VERSION}\r
30700 function WndProcSplitter( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
30701 asm\r
30702         CMP      word ptr [EDX].TMsg.message, WM_NCHITTEST\r
30703         JNE      @@noWM_NCHITTEST\r
30704         PUSH     ECX\r
30705         PUSH     [EDX].TMsg.lParam\r
30706         PUSH     [EDX].TMsg.wParam\r
30707         PUSH     [EDX].TMsg.message\r
30708         PUSH     [EAX].TControl.fHandle\r
30709         CALL     DefWindowProc\r
30710         TEST     EAX, EAX\r
30711         JLE      @@htReady\r
30712         XOR      EAX, EAX\r
30713         INC      EAX\r
30714 @@htReady:\r
30715         POP      ECX\r
30716         MOV      [ECX], EAX\r
30717         MOV      AL, 1\r
30718         RET\r
30720 @@noWM_NCHITTEST:\r
30721         PUSH     EBX\r
30722         XCHG     EBX, EAX\r
30723         CMP      word ptr [EDX].TMsg.message, WM_MOUSEMOVE\r
30724         JNE      @@noWM_MOUSEMOVE\r
30726         PUSH     [EBX].TControl.fCursor\r
30727         CALL     Windows.SetCursor\r
30729         XOR      EDX, EDX\r
30731         {$IFDEF USE_ASM_DODRAG}\r
30732         CALL     @@DoDrag\r
30733         {$ELSE}\r
30734         MOV      EAX, EBX\r
30735         CALL     DoDrag\r
30736         {$ENDIF}\r
30738         POP      EBX\r
30739         RET\r
30741 {$IFDEF USE_ASM_DODRAG}\r
30742 @@DoDrag:\r
30743         PUSHAD\r
30744         MOVZX    EDI, DL // EDI = 1 if Cancel, 0 otherwise\r
30745         CMP      [EBX].TControl.fDragging, 0\r
30746         JZ       @@e_DoDrag\r
30747         MOV      EAX, [EBX].TControl.fParent\r
30748         MOV      EAX, [EAX].TControl.fChildren\r
30749         PUSH     EAX\r
30750         MOV      EDX, EBX\r
30751         CALL     TList.IndexOf\r
30752         POP      EDX // EDX = Self_.fParent.fChildren:PList\r
30753         MOV      EBP, EBX  // Prev := Self_;\r
30754         TEST     EAX, EAX\r
30755         JLE      @@noPrev\r
30756         MOV      EDX, [EDX].TList.fItems\r
30757         MOV      EBP, [EDX+EAX*4-4] // Prev = Self_.fParent.fChildren.fItems[I-1]\r
30758         PUSH     EBP  // push Prev\r
30759 @@noPrev:\r
30760         PUSH     EDX\r
30761         PUSH     EDX\r
30762         PUSH     ESP\r
30763         CALL     GetCursorPos\r
30764         DEC      EDI\r
30765         JNZ      @@noCancel\r
30766         POP      EDX\r
30767         POP      EDX\r
30768         PUSH     [EBX].TControl.fSplitStartPos.y\r
30769         PUSH     [EBX].TControl.fSplitStartPos.x\r
30770 @@noCancel:\r
30771         OR       EDI, -1\r
30772         MOV      CL, [EBX].TControl.fAlign\r
30773         MOV      AL, 1\r
30774         SHL      EAX, CL\r
30775         {$IFDEF PARANOIA}\r
30776         DB $A8, chkRight or chkBott\r
30777         {$ELSE}\r
30778         TEST AL, chkRight or chkBott //fAlign in [ caRight, caBottom ] ?\r
30779         {$ENDIF}\r
30780         JNZ      @@mReady\r
30781         INC      EDI\r
30782         INC      EDI\r
30783 @@mReady:\r
30784         MOV      EDX, [EBX].TControl.fParent\r
30785         MOV      EBP, [EDX].TControl.fMargin\r
30786         NEG      EBP\r
30787         {$IFDEF PARANOIA}\r
30788         DB $A8, chkTop or chkBott\r
30789         {$ELSE}\r
30790         TEST AL, chkTop or chkBott // fAlign in [ caTop, caBottom ] ?\r
30791         {$ENDIF}\r
30792         XCHG     EAX, EDX\r
30793         JZ       @@noTopBottom\r
30795         CALL     TControl.GetClientHeight\r
30796         XCHG     EDX, EAX\r
30798         POP      EAX\r
30799         POP      ESI // MousePos.y\r
30800         MOV      EAX, ESI\r
30801         PUSH     EDX // Self_.fParent.ClientHeight\r
30802         SUB      EAX, [EBX].TControl.fSplitStartPos.y\r
30803         IMUL     EAX, EDI\r
30804         ADD      EAX, [EBX].TControl.fSplitStartSize // EAX = NewSize1\r
30806         POP      EDX\r
30807         SUB      EDX, EAX\r
30808         SUB      EDX, [EBX].TControl.fBoundsRect.Bottom\r
30809         ADD      EDX, [EBX].TControl.fBoundsRect.Top\r
30810         LEA      EDX, [EDX+EBP*4]\r
30812         MOV      ECX, [EBX].TControl.fSecondControl\r
30813         JECXZ    @@noSecondControl\r
30814         MOV      EDX, [ECX].TControl.fBoundsRect.Bottom\r
30815         SUB      EDX, [ECX].TControl.fBoundsRect.Top\r
30816         CMP      [ECX].TControl.fAlign, caClient\r
30817         JNZ      @@noSecondControl\r
30819         PUSH     EAX\r
30820         MOV      EAX, [EBX].TControl.fSplitStartPos.y\r
30821         SUB      EAX, ESI\r
30822         IMUL     EAX, EDI\r
30823         ADD      EAX, [EBX].TControl.fSplitStartPos2.y\r
30824         LEA      EDX, [EAX+EBP*4]\r
30825         POP      EAX\r
30827 @@noSecondControl:\r
30828         JMP      @@newSizesReady\r
30830 @@noTopBottom:\r
30831         CALL     TControl.GetClientWidth\r
30832         XCHG     EDX, EAX\r
30834         POP      ESI // MousePos.x\r
30835         POP      ECX\r
30836         MOV      EAX, ESI\r
30837         PUSH     EDX // Self_.fParent.ClientWidth\r
30838         SUB      EAX, [EBX].TControl.fSplitStartPos.x\r
30839         IMUL     EAX, EDI\r
30840         ADD      EAX, [EBX].TControl.fSplitStartSize // EAX = NewSize1\r
30842         POP      EDX\r
30843         SUB      EDX, EAX\r
30844         SUB      EDX, [EBX].TControl.fBoundsRect.Right\r
30845         ADD      EDX, [EBX].TControl.fBoundsRect.Left\r
30846         LEA      EDX, [EDX+EBP*4]\r
30848         MOV      ECX, [EBX].TControl.fSecondControl\r
30849         JECXZ    @@newSizesReady\r
30850         MOV      EDX, [ECX].TControl.fBoundsRect.Right\r
30851         SUB      EDX, [ECX].TControl.fBoundsRect.Left\r
30852         CMP      [ECX].TControl.fAlign, caClient\r
30853         JNZ      @@noSecondControl\r
30855         PUSH     EAX\r
30856         MOV      EAX, [EBX].TControl.fSplitStartPos.x\r
30857         SUB      EAX, ESI\r
30858         IMUL     EAX, EDI\r
30859         ADD      EAX, [EBX].TControl.fSplitStartPos2.x\r
30860         LEA      EDX, [EAX+EBP*4]\r
30861         POP      EAX\r
30863 @@newSizesReady:\r
30864         MOV      ECX, [EBX].TControl.fSplitMinSize1\r
30865         //JECXZ    @@noCheckMinSize1\r
30866         SUB      ECX, EAX\r
30867         JLE      @@noCheckMinSize1\r
30868         SUB      EDX, ECX\r
30869         ADD      EAX, ECX\r
30871 @@noCheckMinSize1:\r
30872         MOV      ECX, [EBX].TControl.fSplitMinSize2\r
30873         //JECXZ    @@noCheckMinSize2\r
30874         SUB      ECX, EDX\r
30875         JLE      @@noCheckMinSize2\r
30876         SUB      EAX, ECX\r
30877         ADD      EDX, ECX\r
30879 @@noCheckMinSize2:\r
30880         MOV      ECX, [EBX].TControl.fOnSplit.TMethod.Code\r
30881         JECXZ    @@noOnSplit\r
30882         PUSHAD\r
30883         PUSH     EDX\r
30884         MOV      ESI, ECX\r
30885         XCHG     ECX, EAX\r
30886         MOV      EDX, EBX\r
30887         MOV      EAX, [EBX].TControl.fOnSplit.TMethod.Data\r
30888         CALL     ESI\r
30889         TEST     AL, AL\r
30890         POPAD\r
30891         JZ       @@e_DoDrag\r
30893 @@noOnSplit:\r
30894         XCHG     ESI, EAX // NewSize1 -> ESI\r
30895         //MOV      EDI, EDX // NewSize2 -> EDI\r
30896         POP      EBP\r
30897         ADD      ESP, -16\r
30898         MOV      EAX, EBP\r
30899         MOV      EDX, ESP\r
30900         CALL     TControl.GetBoundsRect\r
30901         MOVZX    ECX, [EBX].TControl.fAlign\r
30902         LOOP     @@noPrev_caLeft\r
30903         ADD      ESI, [ESP].TRect.Left\r
30904         MOV      [ESP].TRect.Right, ESI\r
30905 @@noPrev_caLeft:\r
30906         LOOP     @@noPrev_caTop\r
30907         ADD      ESI, [ESP].TRect.Top\r
30908         MOV      [ESP].TRect.Bottom, ESI\r
30909 @@noPrev_caTop:\r
30910         LOOP     @@noPrev_caRight\r
30911         MOV      EAX, [ESP].TRect.Right\r
30912         SUB      EAX, ESI\r
30913         MOV      [ESP].TRect.Left, EAX\r
30914 @@noPrev_caRight:\r
30915         LOOP     @@noPrev_caBottom\r
30916         MOV      EAX, [ESP].TRect.Bottom\r
30917         SUB      EAX, ESI\r
30918         MOV      [ESP].TRect.Top, EAX\r
30919 @@noPrev_caBottom:\r
30920         MOV       EAX, EBP\r
30921         MOV       EDX, ESP\r
30922         CALL      TControl.SetBoundsRect\r
30923         ADD       ESP, 16\r
30924         MOV       EAX, [EBX].TControl.fParent\r
30925         //PUSH      EAX\r
30926         CALL      dword ptr[Global_Align]\r
30927         //POP       EAX\r
30928         //CALL      TControl.Update\r
30930 @@e_DoDrag:\r
30931         POPAD\r
30932         RET\r
30933 {$ENDIF USE_ASM_DODRAG}\r
30935 @@noWM_MOUSEMOVE:\r
30936         CMP      word ptr [EDX].TMsg.message, WM_LBUTTONDOWN\r
30937         JNE      @@noWM_LBUTTONDOWN\r
30938         MOV      ECX, [EBX].TControl.fParent\r
30939         TEST     ECX, ECX\r
30940         JZ       @@noWM_LBUTTONDOWN\r
30941         //JECXZ    @@noWM_LBUTTONDOWN\r
30943         MOV      EAX, [ECX].TControl.fChildren\r
30944         PUSH     EAX\r
30945         MOV      EDX, EBX\r
30946         CALL     TList.IndexOf\r
30947         POP      ECX\r
30948         MOV      EDX, EBX\r
30949         TEST     EAX, EAX\r
30950         JLE      @@noParent1\r
30951         MOV      ECX, [ECX].TList.fItems\r
30952         MOV      EDX, [ECX+EAX*4-4]\r
30953 @@noParent1:\r
30955         MOV      CL, [EBX].TControl.fAlign\r
30956         MOV      AL, 1\r
30957         SHL      EAX, CL\r
30958         {$IFDEF PARANOIA}\r
30959         DB $A8, chkTop or chkBott\r
30960         {$ELSE}\r
30961         TEST AL, chkTop or chkBott // fAlign in [caTop,caBottom] ?\r
30962         {$ENDIF}\r
30963         XCHG     EAX, EDX\r
30964         JZ       @@no_caTop_caBottom\r
30965         CALL     TControl.GetHeight\r
30966         JMP      @@caTop_caBottom\r
30967 @@no_caTop_caBottom:\r
30968         CALL     TControl.GetWidth\r
30969 @@caTop_caBottom:\r
30970         MOV      [EBX].TControl.fSplitStartSize, EAX\r
30971         MOV      ECX, [EBX].TControl.fSecondControl\r
30972         JECXZ    @@noSecondControl1\r
30973         XCHG     EAX, ECX\r
30974         PUSH     EAX\r
30975         CALL     TControl.GetWidth\r
30976         MOV      [EBX].TControl.fSplitStartPos2.x, EAX\r
30977         POP      EAX\r
30978         CALL     TControl.GetHeight\r
30979         MOV      [EBX].TControl.fSplitStartPos2.y, EAX\r
30980 @@noSecondControl1:\r
30981         PUSH     [EBX].TControl.fHandle\r
30982         CALL     SetCapture\r
30983         OR       [EBX].TControl.fDragging, 1\r
30984         PUSH     0\r
30985         PUSH     100\r
30986         PUSH     $7B\r
30987         PUSH     [EBX].TControl.fHandle\r
30988         CALL     SetTimer\r
30989         LEA      EAX, [EBX].TControl.fSplitStartPos\r
30990         PUSH     EAX\r
30991         CALL     GetCursorPos\r
30992         JMP      @@exit\r
30994 @@noWM_LBUTTONDOWN:\r
30995         CMP      word ptr [EDX].TMsg.message, WM_LBUTTONUP\r
30996         JNE      @@noWM_LBUTTONUP\r
30997         XOR      EDX, EDX\r
30999         {$IFDEF USE_ASM_DODRAG}\r
31000         CALL     @@DoDrag\r
31001         {$ELSE}\r
31002         MOV      EAX, EBX\r
31003         CALL     DoDrag\r
31004         {$ENDIF}\r
31006         JMP      @@killtimer\r
31008 @@noWM_LBUTTONUP:\r
31009         CMP      word ptr[EDX].TMsg.message, WM_TIMER\r
31010         JNE      @@exit\r
31011         CMP      [EBX].TControl.fDragging, 0\r
31012         JE       @@exit\r
31013         PUSH     VK_ESCAPE\r
31014         CALL     GetAsyncKeyState\r
31015         TEST     EAX, EAX\r
31016         JGE      @@exit\r
31018         MOV      DL, 1\r
31020         {$IFDEF USE_ASM_DODRAG}\r
31021         CALL     @@DoDrag\r
31022         {$ELSE}\r
31023         MOV      EAX, EBX\r
31024         CALL     DoDrag\r
31025         {$ENDIF}\r
31027 @@killtimer:\r
31028         MOV      [EBX].TControl.fDragging, 0\r
31029         PUSH     $7B\r
31030         PUSH     [EBX].TControl.fHandle\r
31031         CALL     KillTimer\r
31032         CALL     ReleaseCapture\r
31034 @@exit:\r
31035         POP      EBX\r
31036         XOR      EAX, EAX\r
31037 end;\r
31038 {$ELSE ASM_VERSION} //Pascal\r
31039 function WndProcSplitter( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
31040 var I: Integer;\r
31041     Prev: PControl;\r
31043     procedure FinDrag;\r
31044     begin\r
31045       KillTimer( Self_.fHandle, $7B );\r
31046       Self_.fDragging := False;\r
31047       ReleaseCapture;\r
31048     end;\r
31049 begin\r
31050   case Msg.message of\r
31051   WM_NCHITTEST:\r
31052     begin\r
31053         Rslt := DefWindowProc( Self_.fHandle, Msg.message, Msg.wParam, Msg.lParam );\r
31054         if Rslt > 0 then\r
31055           Rslt := HTCLIENT;\r
31056         Result := True;\r
31057         Exit;\r
31058     end;\r
31059   WM_MOUSEMOVE:\r
31060     begin\r
31061       Windows.SetCursor( Self_.fCursor );\r
31062       DoDrag( Self_, False );\r
31063     end;\r
31064   WM_LBUTTONDOWN:\r
31065     begin\r
31066       if Self_.fParent <> nil then\r
31067       begin\r
31068         I := Self_.fParent.fChildren.IndexOf( Self_ );\r
31069         Prev := Self_;\r
31070         if I > 0 then\r
31071           Prev := Self_.FParent.fChildren.fItems[ I - 1 ];\r
31072         if Self_.fAlign in [ caTop, caBottom ] then\r
31073           Self_.fSplitStartSize := Prev.Height\r
31074         else\r
31075           Self_.fSplitStartSize := Prev.Width;\r
31076         if Self_.fSecondControl <> nil then\r
31077           Self_.fSplitStartPos2 :=\r
31078             MakePoint( Self_.fSecondControl.Width, Self_.fSecondControl.Height );\r
31079         SetCapture( Self_.fHandle );\r
31080         Self_.fDragging := True;\r
31081         SetTimer( Self_.fHandle, $7B, 100, nil );\r
31082         GetCursorPos( Self_.fSplitStartPos );\r
31083       end;\r
31084     end;\r
31085   WM_LBUTTONUP:\r
31086     begin\r
31087       DoDrag( Self_, False );\r
31088       FinDrag;\r
31089     end;\r
31090   WM_TIMER:\r
31091     if Self_.fDragging and (GetAsyncKeyState( VK_ESCAPE ) < 0) then\r
31092     begin\r
31093       DoDrag( Self_, True );\r
31094       FinDrag;\r
31095     end;\r
31096   end;\r
31097   Result := False;\r
31098 end;\r
31099 {$ENDIF ASM_VERSION}\r
31100 //[END WndProcSplitter]\r
31102 //[function NewSplitter]\r
31103 function NewSplitter( AParent: PControl; MinSizePrev, MinSizeNext: Integer ): PControl;\r
31104 begin\r
31105   Result := NewSplitterEx( AParent, MinSizePrev, MinSizeNext, esLowered );\r
31106 end;\r
31107 //[END NewSplitter]\r
31109 {$IFDEF USE_CONSTRUCTORS}\r
31110 //[function NewSplitterEx]\r
31111 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;\r
31112          EdgeStyle: TEdgeStyle ): PControl;\r
31113 begin\r
31114   new( Result, CreateSplitter( AParent, MinSizePrev, MinSizeNext, EdgeStyle ) );\r
31115 end;\r
31116 //[END NewSplitterEx]\r
31117 {$ELSE not_USE_CONSTRUCTORS}\r
31119 //[FUNCTION NewSplitterEx]\r
31120 {$IFDEF ASM_VERSION}\r
31121 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;\r
31122          EdgeStyle: TEdgeStyle ): PControl;\r
31123 const int_IDC_SIZEWE = integer( IDC_SIZEWE );\r
31124 asm\r
31125         PUSH     EBX\r
31126         PUSH     EAX  // AParent\r
31127         PUSH     ECX  // MinSizePrev\r
31128         PUSH     EDX  // MinSizeNext\r
31129         MOV      DL, EdgeStyle\r
31130         CALL     NewPanel\r
31131         XCHG     EBX, EAX\r
31132         POP      [EBX].TControl.fSplitMinSize1\r
31133         POP      [EBX].TControl.fSplitMinSize2\r
31134         XOR      EDX, EDX\r
31135         MOV      DL, 4\r
31136         MOV      EAX, [EBX].TControl.fBoundsRect.Left\r
31137         ADD      EAX, EDX\r
31138         MOV      [EBX].TControl.fBoundsRect.Right, EAX\r
31139         ADD      EDX, [EBX].TControl.fBoundsRect.Top\r
31140         MOV      [EBX].TControl.fBoundsRect.Bottom, EDX\r
31142         POP      ECX  // ECX = AParent\r
31143         JECXZ    @@noParent2\r
31144         MOV      EAX, [ECX].TControl.fChildren\r
31145         MOV      ECX, [EAX].TList.fCount\r
31146         CMP      ECX, 1\r
31147         JLE      @@noParent2\r
31149         MOV      EAX, [EAX].TList.fItems\r
31150         MOV      EAX, [EAX+ECX*4-8]\r
31151         MOV      CL, [EAX].TControl.fAlign\r
31152         PUSH     ECX\r
31153         MOV      AL, 1\r
31154         SHL      EAX, CL\r
31155         {$IFDEF PARANOIA}\r
31156         DB $A8, chkTop or chkBott\r
31157         {$ELSE}\r
31158         TEST     AL, chkTop or chkBott\r
31159         {$ENDIF}\r
31160         MOV      EAX, int_IDC_SIZEWE\r
31161         JZ       @@TopBottom\r
31162         INC      EAX\r
31163 @@TopBottom:\r
31164         PUSH     EAX\r
31165         PUSH     0\r
31166         CALL     LoadCursor\r
31167         MOV      [EBX].TControl.fCursor, EAX\r
31168         POP      EDX\r
31169         MOV      EAX, EBX\r
31170         CALL     TControl.SetAlign\r
31172 @@noParent2:\r
31173         MOV      EAX, EBX\r
31174         MOV      EDX, offset[WndProcSplitter]\r
31175         CALL     TControl.AttachProc\r
31176         XCHG     EAX, EBX\r
31177         POP      EBX\r
31178 end;\r
31179 {$ELSE ASM_VERSION} //Pascal\r
31180 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;\r
31181          EdgeStyle: TEdgeStyle ): PControl;\r
31182 var PrevCtrl: PControl;\r
31183     Sz0: Integer;\r
31184 begin\r
31185   Result := NewPanel( AParent, EdgeStyle );\r
31186   Result.fSplitMinSize1 := MinSizePrev;\r
31187   Result.fSplitMinSize2 := MinSizeNext;\r
31188   Sz0 := 4;\r
31189   with Result.fBoundsRect do\r
31190   begin\r
31191     Right := Left + Sz0;\r
31192     Bottom := Top + Sz0;\r
31193   end;\r
31194   if AParent <> nil then\r
31195   begin\r
31196     if AParent.fChildren.fCount > 1 then\r
31197     begin\r
31198       PrevCtrl := AParent.fChildren.fItems[ AParent.fChildren.fCount - 2 ];\r
31199       case PrevCtrl.FAlign of\r
31200       caLeft, caRight:\r
31201         begin\r
31202           Result.fCursor := LoadCursor( 0, IDC_SIZEWE );\r
31203         end;\r
31204       caTop, caBottom:\r
31205         begin\r
31206           Result.fCursor := LoadCursor( 0, IDC_SIZENS );\r
31207         end;\r
31208       end;\r
31209       Result.Align := PrevCtrl.FAlign;\r
31210     end;\r
31211   end;\r
31212   Result.AttachProc( WndProcSplitter );\r
31213 end;\r
31214 {$ENDIF ASM_VERSION}\r
31215 //[END NewSplitterEx]\r
31217 {$ENDIF USE_CONSTRUCTORS}\r
31219 //===================== MDI client window control =============//\r
31221 //[procedure DestroyMDIChildren]\r
31222 procedure DestroyMDIChildren( Form: PControl );\r
31223 var MDIClient: PControl;\r
31224     I: Integer;\r
31225     Ch: PControl;\r
31226 begin\r
31227   //Form.fDefWndProc := nil;\r
31228   MDIClient := Form.fMDIClient;\r
31229   MDIClient.fMDIDestroying := TRUE;\r
31230   if MDIClient = nil then Exit;\r
31231   if MDIClient.fMDIChildren <> nil then\r
31232   for I := MDIClient.fMDIChildren.Count - 1 downto 0 do\r
31233   begin\r
31234     Ch := MDIClient.fMDIChildren.fItems[ I ];\r
31235     if Ch.fHandle <> 0 then\r
31236       MDIClient.Perform( WM_MDIDESTROY, Ch.fHandle, 0 );\r
31237   end;\r
31238   MDIClient.fMDIChildren.Free;\r
31239   MDIClient.fMDIChildren := nil;\r
31240   if Form.fMenu <> 0 then\r
31241   begin\r
31242     MDIClient.Perform( WM_MDISETMENU, 0, 0 );\r
31243     MDIClient.Perform( WM_MDIREFRESHMENU, 0, 0 );\r
31244     DrawMenuBar( Form.fHandle );\r
31245     Form.fMenuObj.Free;\r
31246     Form.fMenuObj := nil;\r
31247   end;\r
31248   Form.fMDIClient := nil;\r
31249   MDIClient.Free;\r
31250 end;\r
31252 //[function ProcMDIAccel]\r
31253 function ProcMDIAccel( Applet: PControl; var Msg: TMsg ): Boolean;\r
31254 var Form: PControl;\r
31255 begin\r
31256   Result := FALSE;\r
31257   if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then\r
31258   begin\r
31259     Form := Applet.ActiveControl;\r
31260     if Form <> nil then\r
31261     begin\r
31262       if Form.IsMDIChild then\r
31263         Form := Form.Parent;\r
31264       Form := Form.ParentForm;\r
31265       if (Form <> nil) and (Form.MDIClient <> nil) then\r
31266         Result := TranslateMDISysAccel( Form.MDIClient.fHandle, Msg );\r
31267     end;\r
31268   end;\r
31269 end;\r
31271 //[function CallDefFrameProc]\r
31272 function CallDefFrameProc( Wnd: HWnd; Msg: Integer; wParam, lParam: Integer ): Integer;\r
31273 stdcall;\r
31274 var Form: PControl;\r
31275 begin\r
31276   Form := Pointer( GetProp( Wnd, ID_SELF ) );\r
31277   if Form <> nil then\r
31278     Form := Form.ParentForm;\r
31279   if (Form <> nil) and (Form.fMDIClient <> nil) then\r
31280     Result := DefFrameProc( Wnd, Form.fMDIClient.fHandle, Msg, wParam, lParam )\r
31281   else\r
31282     Result := DefWindowProc( Wnd, Msg, wParam, lParam );\r
31283 end;\r
31285 //[function WndFuncMDIClient]\r
31286 function WndFuncMDIClient( Wnd: HWnd; Msg, wParam, lParam: Integer ): Integer;\r
31287 stdcall;\r
31288 var C: PControl;\r
31289     M: TMsg;\r
31290 begin\r
31291   C := Pointer( GetProp( Wnd, ID_SELF ) );\r
31292   if C <> nil then\r
31293   begin\r
31294     M.hwnd := Wnd;\r
31295     M.message := Msg;\r
31296     M.wParam := wParam;\r
31297     M.lParam := lParam;\r
31298     Result := C.WndProc( M );\r
31299   end\r
31300     else\r
31301     Result := DefWindowProc( Wnd, Msg, wParam, lParam );\r
31302 end;\r
31304 //[function ShowMDIClientEdge]\r
31305 function ShowMDIClientEdge( MDIClient: PControl ): Boolean;\r
31306 var ShowEdge: Boolean;\r
31307     I: Integer;\r
31308     Ch: PControl;\r
31309     ExStyle: Integer;\r
31310 begin\r
31311   Result := FALSE;\r
31312   ShowEdge := TRUE;\r
31313   if MDIClient.fMDIChildren.Count > 0 then\r
31314     for I := 0 to MDIClient.fMDIChildren.Count-1 do\r
31315     begin\r
31316       Ch := MDIClient.fMDIChildren.fItems[ I ];\r
31317       if IsZoomed( Ch.fHandle ) then\r
31318       begin\r
31319         ShowEdge := FALSE;\r
31320         break;\r
31321       end;\r
31322     end;\r
31323   ExStyle := MDIClient.ExStyle;\r
31324   if ShowEdge then\r
31325     if ExStyle and WS_EX_CLIENTEDGE = 0 then\r
31326       ExStyle := ExStyle or WS_EX_CLIENTEDGE\r
31327     else\r
31328       Exit\r
31329   else if ExStyle and WS_EX_CLIENTEDGE <> 0 then\r
31330     ExStyle := ExStyle and not WS_EX_CLIENTEDGE\r
31331   else\r
31332     Exit;\r
31333   MDIClient.ExStyle := ExStyle;\r
31334   Result := TRUE;\r
31335 end;\r
31337 //[function WndProcMDIClient]\r
31338 function WndProcMDIClient( MDIClient: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
31339 {var I: Integer;\r
31340     Ch: PControl;}\r
31341 begin\r
31342   if not MDIClient.fMDIDestroying then\r
31343   case Msg.message of\r
31344   $3f:\r
31345       begin\r
31346         PostMessage( MDIClient.fHandle, CM_MDIClientShowEdge, 0, 0 );\r
31347       end;\r
31348   CM_MDIClientShowEdge:\r
31349       begin\r
31350         ShowMDIClientEdge( MDIClient );\r
31351       end;\r
31352   WM_NCHITTEST: // not necessary though\r
31353       begin\r
31354         Rslt := DefWindowProc( MDIClient.fHandle, WM_NCHITTEST, Msg.wParam, Msg.lParam );\r
31355         if Rslt = HTCLIENT then Rslt := HTTRANSPARENT;\r
31356       end;\r
31357   WM_WINDOWPOSCHANGING:\r
31358       begin\r
31359         MDIClient.Perform( WM_SETREDRAW, 0, 0 );\r
31360       end;\r
31361   WM_WINDOWPOSCHANGED:\r
31362       begin\r
31363         Global_Align( MDIClient.Parent );\r
31364         MDIClient.Invalidate;\r
31365         MDIClient.Parent.Invalidate;\r
31366         MDIClient.Perform( WM_SETREDRAW, 1, 0 );\r
31367         PostMessage( MDIClient.fHandle, CM_INVALIDATE, 0, 0 );\r
31368       end;\r
31369   CM_INVALIDATE:\r
31370       begin\r
31371         MDIClient.InvalidateNC( TRUE );\r
31372         MDIClient.InvalidateEx;\r
31373         {for I := 0 to MDIClient.fMDIChildren.Count-1 do\r
31374         begin\r
31375           Ch := MDIClient.fMDIChildren.fItems[ I ];\r
31376           Ch.InvalidateEx;\r
31377           Ch.Perform( WM_NCPAINT, 1, 0 );\r
31378         end;}\r
31379       end;\r
31380   end;\r
31381   Result := FALSE;\r
31382 end;\r
31384 // function added by Thaddy de Koning to fix MDI behaviour\r
31385 //[function WndProcParentNotifyMouseLDown]\r
31386 function WndProcParentNotifyMouseLDown( Sender: PControl; var Msg: TMsg;\r
31387 var Rslt: Integer ): Boolean;\r
31388 begin\r
31389   Result := FALSE;\r
31390   if (Sender.IsMDIChild) and (Msg.message = WM_PARENTNOTIFY) and\r
31391      (LOWORD(msg.wparam)=WM_LBUTTONDOWN) then\r
31392      BringWindowToTop( Sender.Handle );\r
31393 end;\r
31395 //[function NewMDIClient]\r
31396 function NewMDIClient( AParent: PControl; WindowMenu: THandle ): PControl;\r
31397 var F: PControl;\r
31398     CCS: TClientCreateStruct;\r
31399     PrntWin: HWnd;\r
31400 begin\r
31401   F := nil;\r
31402   PrntWin := 0;\r
31403   if AParent <> nil then\r
31404   begin\r
31405     F := AParent.ParentForm;\r
31406     if F <> nil then\r
31407     begin\r
31408       F.Add2AutoFreeEx( TObjectMethod( MakeMethod( F, @ DestroyMDIChildren ) ) );\r
31409       F.GetWindowHandle; // must be created before MDI client creation\r
31410       F.fDefWndProc := @CallDefFrameProc;\r
31411     end;\r
31412     PrntWin := AParent.GetWindowHandle;\r
31413   end;\r
31414   Applet.fExMsgProc := ProcMDIAccel;\r
31415   Result := _NewControl( AParent, 'MDICLIENT',\r
31416          WS_CHILD or WS_CLIPCHILDREN or WS_VSCROLL or WS_HSCROLL or\r
31417          WS_VISIBLE or WS_TABSTOP or MDIS_ALLCHILDSTYLES, TRUE, nil );\r
31418   {Result.fBoundsRect.Right := Result.fBoundsRect.Left + 300;\r
31419   Result.fBoundsRect.Bottom := Result.fBoundsRect.Top + 200;}\r
31420   Result.fMDIChildren := NewList;\r
31421   Result.fExStyle := WS_EX_CLIENTEDGE;\r
31423   CCS.hWindowMenu := WindowMenu;\r
31424   CCS.idFirstChild := $FF00;\r
31425   Result.fHandle := CreateWindowEx( WS_EX_CLIENTEDGE, 'MDICLIENT', nil,\r
31426                  WS_CHILD or WS_CLIPCHILDREN or WS_VSCROLL or WS_HSCROLL or\r
31427                  WS_VISIBLE or WS_TABSTOP,\r
31428                  //or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX,\r
31429                  0, 0, 0, 0, PrntWin, 0, hInstance, @ CCS );\r
31430   Result.fDefWndProc := Pointer( GetWindowLong( Result.fHandle, GWL_WNDPROC ) );\r
31431   SetWindowLong( Result.fHandle, GWL_WNDPROC, Integer( @WndFuncMDIClient ) );\r
31432   SetProp( Result.fHandle, ID_SELF, Integer( Result ) );\r
31433   if F <> nil then\r
31434     F.fMDIClient := Result;\r
31435   Result.AttachProc( WndProcMDIClient );\r
31436   Result.GetWindowHandle;\r
31438   Applet.AttachProc( WndProcParentNotifyMouseLDown );\r
31439 end;\r
31441 //===================== MDI child window object ==============//\r
31442 //[function MDIChildFunc]\r
31443 function MDIChildFunc( Wnd: HWnd; Msg: DWord; wParam, lParam: Integer ): Integer;\r
31444 stdcall;\r
31445 var C: PControl;\r
31446     M: TMsg;\r
31447 begin\r
31448   C := Pointer( GetProp( Wnd, ID_SELF ) );\r
31449   if C <> nil then\r
31450   begin\r
31451     M.hwnd := Wnd;\r
31452     M.message := Msg;\r
31453     M.wParam := wParam;\r
31454     M.lParam := lParam;\r
31455     Result := C.WndProc( M );\r
31456   end\r
31457     else\r
31458     Result := DefMDIChildProc( Wnd, Msg, wParam, lParam );\r
31459 end;\r
31461 //[function Pass2DefMDIChildProc]\r
31462 function Pass2DefMDIChildProc( Sender_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
31463 begin\r
31464   Result := FALSE;\r
31465   if Sender_ = nil then Exit;\r
31466   if Sender_.Parent = nil then Exit;\r
31467   if Sender_.Parent.fDestroying then Exit;\r
31468   if (Msg.message = WM_SYSCOMMAND) or (Msg.message = WM_CHILDACTIVATE) or\r
31469      (Msg.message = WM_SETFOCUS) or (Msg.message = WM_SIZE) or\r
31470      (Msg.message = WM_MOVE) or (Msg.message = WM_MENUCHAR) or\r
31471      (Msg.message = WM_GETMINMAXINFO) {and IsZoomed( Sender_.fHandle ) {and (Msg.hwnd = Sender_.fHandle) { -- doesn't work -- } then\r
31472   begin\r
31473     {if Msg.message = WM_GETMINMAXINFO then\r
31474       Rslt := DefWindowProc( Msg.hwnd, Msg.message, Msg.lParam, Msg.wParam )\r
31475     else}\r
31476     Rslt := DefMDIChildProc( Msg.hwnd, Msg.message, Msg.lParam, Msg.wParam );\r
31477     Result := TRUE;\r
31478   end;\r
31479 end;\r
31481 //[function WndProcMDIChild]\r
31482 function WndProcMDIChild( MDIChild: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
31483 var ClientWnd: HWnd;\r
31484     MDIClient: PControl;\r
31485     MDIForm: PControl;\r
31486 begin\r
31487   Result := FALSE;\r
31488   MDIClient := MDIChild.Parent;\r
31489   if MDIClient = nil then Exit;\r
31490   ClientWnd := MDIClient.fHandle;\r
31491   if ClientWnd = 0 then Exit;\r
31492   case Msg.message of\r
31493   WM_DESTROY:\r
31494     begin\r
31495       MDIClient.fMDIChildren.Remove( MDIChild );\r
31496       MDIForm := MDIClient.ParentForm;\r
31497       if MDIForm <> nil then\r
31498       if MDIForm.fHandle <> 0 then\r
31499         DrawMenuBar( MDIForm.fHandle );\r
31500       MDIChild.Free;\r
31501       Result := TRUE;\r
31502       Exit;\r
31503     end;\r
31504   end;\r
31505   if MDIChild.fNotAvailable then\r
31506   begin\r
31507     MDIChild.fNotAvailable := FALSE;\r
31508     MDIChild.Invalidate;\r
31509   end;\r
31510 end;\r
31512 //[procedure CreateMDIChildExt]\r
31513 procedure CreateMDIChildExt( Sender: PControl );\r
31514 var F: PControl;\r
31515 begin\r
31516   F := Sender.Parent;\r
31517   if F <> nil then\r
31518     F := F.ParentForm;\r
31519   if F <> nil then\r
31520     DrawMenuBar( F.fHandle );\r
31521 end;\r
31523 //[function NewMDIChild]\r
31524 function NewMDIChild( AParent: PControl; const ACaption: String ): PControl;\r
31525 var MDIClient: PControl;\r
31526 begin\r
31527   Assert( (AParent <> nil) and (AParent.ParentForm <> nil) and\r
31528           (AParent.ParentForm.fMDIClient <> nil), 'Error creating MDI child' );\r
31529   MDIClient := AParent.ParentForm.fMDIClient;\r
31530   Result := NewForm( MDIClient, ACaption );\r
31531   Result.fIsMDIChild := TRUE;\r
31532   Result.fMenu := CtlIdCount;\r
31533   Inc( CtlIdCount );\r
31534   MDIClient.fMDIChildren.Add( Result );\r
31535   Result.fExStyle := Result.fExStyle or WS_EX_MDICHILD;\r
31536   Result.fWndFunc := @ MDIChildFunc;\r
31537   Result.fDefWndProc := @DefMDIChildProc;\r
31538   Result.fPass2DefProc := Pass2DefMDIChildProc;\r
31539   Result.AttachProc( WndProcMDIChild );\r
31541   Result.SubClassName := 'MDI_chld';\r
31542   Result.fNotAvailable := TRUE;\r
31543   Result.fCreateWndExt := CreateMDIChildExt;\r
31545 end;\r
31547 //===================== Gradient panel ========================//\r
31549 {$IFDEF USE_CONSTRUCTORS}\r
31550 //[function NewGradientPanel]\r
31551 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;\r
31552 begin\r
31553   new( Result, CreateGradientPanel( AParent, Color1, Color2 ) );\r
31554 end;\r
31555 //[END NewGradientPanel]\r
31556 {$ELSE not_USE_CONSTRUCTORS}\r
31558 //[FUNCTION NewGradientPanel]\r
31559 {$IFDEF ASM_VERSION}\r
31560 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;\r
31561 asm\r
31562         PUSH     ECX\r
31563         PUSH     EDX\r
31564         XOR      EDX, EDX\r
31565         CALL     NewLabel\r
31566         PUSH     EAX\r
31567         MOV      EDX, offset[WndProcGradient]\r
31568         CALL     TControl.AttachProc\r
31569         POP      EAX\r
31570         POP      [EAX].TControl.fColor1\r
31571         POP      [EAX].TControl.fColor2\r
31572         ADD      [EAX].TControl.fBoundsRect.Right, 40-64\r
31573         ADD      [EAX].TControl.fBoundsRect.Bottom, 40 - 22\r
31574 end;\r
31575 {$ELSE ASM_VERSION} //Pascal\r
31576 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;\r
31577 begin\r
31578   Result := NewLabel( AParent, '' );\r
31579   Result.AttachProc( WndProcGradient );\r
31580   Result.fColor2 := Color2;\r
31581   Result.fColor1 := Color1;\r
31582   with Result.fBoundsRect do\r
31583   begin\r
31584     Right := Left + 40;\r
31585     Bottom := Top + 40;\r
31586   end;\r
31587 end;\r
31588 {$ENDIF ASM_VERSION}\r
31589 //[END NewGradientPanel]\r
31591 {$ENDIF USE_CONSTRUCTORS}\r
31593 {$IFDEF USE_CONSTRUCTORS}\r
31594 //[function NewGradientPanelEx]\r
31595 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;\r
31596                              Style: TGradientStyle; Layout: TGradientLayout ): PControl;\r
31597 begin\r
31598   new( Result, CreateGradientPanelEx( AParent, Color1, Color2,\r
31599                              Style, Layout ) );\r
31600 end;\r
31601 //[END NewGradientPanelEx]\r
31602 {$ELSE not_USE_CONSTRUCTORS}\r
31604 //[FUNCTION NewGradientPanelEx]\r
31605 {$IFDEF ASM_VERSION}\r
31606 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;\r
31607                              Style: TGradientStyle; Layout: TGradientLayout ): PControl;\r
31608 asm\r
31609         PUSH     ECX\r
31610         PUSH     EDX\r
31611         XOR      EDX, EDX\r
31612         CALL     NewLabel\r
31613         PUSH     EAX\r
31614         MOV      EDX, offset[WndProcGradientEx]\r
31615         CALL     TControl.AttachProc\r
31616         POP      EAX\r
31617         POP      [EAX].TControl.fColor1\r
31618         POP      [EAX].TControl.fColor2\r
31619         ADD      [EAX].TControl.fBoundsRect.Right, 40-100\r
31620         ADD      [EAX].TControl.fBoundsRect.Bottom, 40 - 22\r
31621         MOV      DL, Style\r
31622         MOV      [EAX].TControl.fGradientStyle, DL\r
31623         MOV      DL, Layout\r
31624         MOV      [EAX].TControl.fGradientLayout, DL\r
31625 end;\r
31626 {$ELSE ASM_VERSION} //Pascal\r
31627 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;\r
31628                              Style: TGradientStyle; Layout: TGradientLayout ): PControl;\r
31629 begin\r
31630   Result := NewLabel( AParent, '' );\r
31631   Result.AttachProc( WndProcGradientEx );\r
31632   Result.fColor2 := Color2;\r
31633   Result.fColor1 := Color1;\r
31634   Result.fGradientStyle := Style;\r
31635   Result.fGradientLayout := Layout;\r
31636   with Result.fBoundsRect do\r
31637   begin\r
31638     Right := Left + 40;\r
31639     Bottom := Top + 40;\r
31640   end;\r
31641 end;\r
31642 {$ENDIF ASM_VERSION}\r
31643 //[END NewGradientPanelEx]\r
31645 {$ENDIF USE_CONSTRUCTORS}\r
31647 //===================== Edit box ========================//\r
31649 const Editflags: array [ TEditOption ] of Integer = (\r
31650                   not (ES_AUTOHSCROLL or WS_HSCROLL),\r
31651                   not (es_AutoVScroll or WS_VSCROLL),\r
31652                   es_Lowercase, es_Multiline,\r
31653                   es_NoHideSel, es_OemConvert, es_Password, es_Readonly,\r
31654                   es_UpperCase, es_WantReturn, 0, es_Number );\r
31656 {$IFDEF USE_CONSTRUCTORS}\r
31657 //[function NewEditbox]\r
31658 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;\r
31659 begin\r
31660   new( Result, CreateEditbox( AParent, Options ) );\r
31661 end;\r
31662 //[END NewEditbox]\r
31663 {$ELSE not_USE_CONSTRUCTORS}\r
31665 //[FUNCTION NewEditBox]\r
31666 {$IFDEF ASM_VERSION}\r
31667 const EditClass: array[0..4] of Char = ( 'E','D','I','T',#0 );\r
31668 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;\r
31669 const int_IDC_IBEAM = integer( IDC_IBEAM );\r
31670 const WS_flags = integer( WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER );\r
31671 const WS_clear = integer( not(WS_VSCROLL or WS_HSCROLL) );\r
31672 asm\r
31673         PUSH     EBX\r
31674         XCHG     EBX, EAX // EBX=AParent\r
31675         PUSH     EDX\r
31676         MOV      EAX, ESP\r
31677         XOR      ECX, ECX\r
31678         MOV      CL, 11\r
31679         MOV      EDX, offset [EditFlags]\r
31680         CALL     MakeFlags\r
31681         XCHG     ECX, EAX // ECX = Flags\r
31682         POP      EAX  // Options\r
31683         PUSH     EAX\r
31684         {$IFDEF PARANOIA}\r
31685         DB $A8, 8\r
31686         {$ELSE}\r
31687         TEST     AL, 8\r
31688         {$ENDIF}\r
31689         JNZ      @@1\r
31690         AND      ECX, WS_clear\r
31691 @@1:    OR       ECX, WS_flags\r
31692         PUSH     1\r
31693         PUSH     offset [EditActions]\r
31694         MOV      EDX, offset [EditClass]\r
31695         XCHG     EAX, EBX\r
31696         CALL     _NewControl\r
31697         XCHG     EBX, EAX\r
31698 { //YS\r
31699         PUSH     int_IDC_IBEAM\r
31700         PUSH     0\r
31701         CALL     LoadCursor\r
31702         MOV      [EBX].TControl.fCursor, EAX\r
31704         LEA      ECX, [EBX].TControl.fBoundsRect\r
31705         MOV      EDX, [ECX].TRect.Left\r
31706         ADD      EDX, 100\r
31707         MOV      [ECX].TRect.Right, EDX\r
31708         MOV      EDX, [ECX].TRect.Top\r
31709         ADD      EDX, 22\r
31710         MOV      [ECX].TRect.Bottom, EDX\r
31711         POP      EAX // Options\r
31712         {$IFDEF PARANOIA}\r
31713         DB $A8, 8\r
31714         {$ELSE}\r
31715         TEST     AL, 8\r
31716         {$ENDIF}\r
31717         MOV      DL, $0D\r
31718         JZ       @@2\r
31719         ADD      [ECX].TRect.Right, 100\r
31720         ADD      [ECX].TRect.Bottom, 200 - 22\r
31721         MOV      DL, 1\r
31722         INC      [EBX].TControl.fIgnoreDefault\r
31723 @@2:    //MOV      [EBX].TControl.fColor, clWindow\r
31724         TEST     AH, 4\r
31725         JZ       @@3\r
31726         AND      DL, $FE\r
31727 @@3:    MOV      [EBX].TControl.fLookTabKeys, DL\r
31728         XCHG     EAX, EBX\r
31729         POP      EBX\r
31730 end;\r
31731 {$ELSE ASM_VERSION} //Pascal\r
31732 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;\r
31733 var Flags: Integer;\r
31734 begin\r
31735   Flags := MakeFlags( @Options, EditFlags );\r
31736   if not(eoMultiline in Options) then\r
31737      Flags := Flags and not(WS_HSCROLL or WS_VSCROLL);\r
31738   Result := _NewControl( AParent, 'EDIT', WS_VISIBLE or WS_CHILD or WS_TABSTOP\r
31739                          or WS_BORDER or Flags, True, @EditActions );\r
31740 //  Result.fCursor := LoadCursor( 0, IDC_IBEAM ); {YS}\r
31741   with Result.fBoundsRect do\r
31742   begin\r
31743     Right := Left + 100;\r
31744     Bottom := Top + 22;\r
31745     if eoMultiline in Options then\r
31746     begin\r
31747        Right := Right + 100;\r
31748        Bottom := Top + 200;\r
31749        Result.fIgnoreDefault := TRUE;\r
31750     end;\r
31751   end;\r
31752   Result.fLookTabKeys := [ tkTab, tkUpDown, tkPageUpPageDn ];\r
31753   if eoMultiline in Options then\r
31754      Result.fLookTabKeys := [ tkTab ];\r
31755   if eoWantTab in Options then\r
31756      Result.fLookTabKeys := Result.fLookTabKeys - [ tkTab ];\r
31757 end;\r
31758 {$ENDIF ASM_VERSION}\r
31759 //[END NewEditBox]\r
31761 {$ENDIF USE_CONSTRUCTORS}\r
31763 //===================== List box ========================//\r
31765 const ListFlags: array[TListOption] of Integer = (\r
31766                   LBS_DISABLENOScroll, not LBS_ExtendedSel,\r
31767                   LBS_MultiColumn or WS_HSCROLL,\r
31768                   LBS_MultiPLESel,\r
31769                   LBS_NoIntegralHeight, LBS_NoSel, LBS_Sort, LBS_USETabstops,\r
31770                   not LBS_HASSTRINGS, LBS_NODATA, LBS_OWNERDRAWFIXED, LBS_OWNERDRAWVARIABLE );\r
31772 {$IFDEF USE_CONSTRUCTORS}\r
31773 //[function NewListbox]\r
31774 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;\r
31775 begin\r
31776   new( Result, CreateListbox( AParent, Options ) );\r
31777 end;\r
31778 //[END NewListbox]\r
31779 {$ELSE not_USE_CONSTRUCTORS}\r
31781 //[FUNCTION NewListbox]\r
31782 {$IFDEF ASM_VERSION}\r
31783 const ListBoxClass : array[ 0..7 ] of Char = ( 'L','I','S','T','B','O','X',#0 );\r
31784 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;\r
31785 asm\r
31786         PUSH     EAX\r
31787         PUSH     EDX\r
31788         MOV      EAX, ESP\r
31789         MOV      EDX, offset[ListFlags]\r
31790         XOR      ECX, ECX\r
31791         MOV      CL, 11\r
31792         CALL     MakeFlags\r
31793         POP      EDX\r
31794         OR       EAX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER or WS_VSCROLL or LBS_NOTIFY\r
31795         XCHG     ECX, EAX\r
31796         POP      EAX\r
31797         PUSH     1\r
31798         PUSH     offset[ListActions]\r
31799         MOV      EDX, offset[ListBoxClass]\r
31800         CALL     _NewControl\r
31801         ADD      [EAX].TControl.fBoundsRect.Right, 100\r
31802         ADD      [EAX].TControl.fBoundsRect.Bottom, 200-64\r
31803         MOV      [EAX].TControl.fColor, clWindow\r
31804         MOV      [EAX].TControl.fLookTabKeys, 3\r
31805 end;\r
31806 {$ELSE ASM_VERSION} //Pascal\r
31807 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;\r
31808 var Flags: Integer;\r
31809 begin\r
31810   Flags := MakeFlags( @Options, ListFlags );\r
31811   Result := _NewControl( AParent, 'LISTBOX', WS_VISIBLE or WS_CHILD or WS_TABSTOP\r
31812                          or WS_BORDER or WS_VSCROLL\r
31813                          or LBS_NOTIFY or Flags, True, @ListActions );\r
31814   with Result.fBoundsRect do\r
31815   begin\r
31816     Right := Right + 100;\r
31817     Bottom := Top + 200;\r
31818   end;\r
31819   Result.fColor := clWindow;\r
31820   Result.fLookTabKeys := [ tkTab, tkLeftRight ];\r
31821 end;\r
31822 {$ENDIF ASM_VERSION}\r
31823 //[END NewListbox]\r
31825 {$ENDIF USE_CONSTRUCTORS}\r
31827 //===================== Combo box ========================//\r
31829 //[FUNCTION ComboboxDropDown]\r
31830 {$IFNDEF USE_DROPDOWNCOUNT}\r
31831 {$IFDEF ASM_VERSION}\r
31832 procedure ComboboxDropDown( Sender: PObj );\r
31833 asm\r
31834         PUSH     EBX\r
31835         PUSH     ESI\r
31836         MOV      EBX, EAX\r
31837         CALL     TControl.GetItemsCount\r
31838         CMP      EAX, 1\r
31839         JGE      @@1\r
31840         XOR      EAX, EAX\r
31841         INC      EAX\r
31842 @@1:    CMP      EAX, 8\r
31843         JLE      @@2\r
31844         XOR      EAX, EAX\r
31845         MOV      AL, 8\r
31846 @@2:    XOR      ESI, ESI\r
31847         PUSH     SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_SHOWWINDOW\r
31848         PUSH     ESI\r
31849         PUSH     ESI\r
31850         PUSH     SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_HIDEWINDOW\r
31851         PUSH     EAX\r
31852         MOV      EAX, EBX\r
31853         CALL     TControl.GetHeight\r
31854         POP      ECX\r
31855         INC      ECX\r
31856         IMUL     ECX\r
31857         INC      EAX\r
31858         INC      EAX\r
31859         PUSH     EAX\r
31860         MOV      EAX, EBX\r
31861         CALL     TControl.GetWidth\r
31862         PUSH     EAX\r
31863         INC      ESI\r
31864 @@3:    XOR      EDX, EDX\r
31865         PUSH     EDX\r
31866         PUSH     EDX\r
31867         PUSH     EDX\r
31868         PUSH     [EBX].TControl.fHandle\r
31869         CALL     SetWindowPos\r
31870         DEC      ESI\r
31871         JZ       @@3\r
31872         MOV      ECX, [EBX].TControl.fOnDropDown.TMethod.Code\r
31873         JECXZ    @@exit\r
31874         MOV      EAX, [EBX].TControl.fOnDropDown.TMethod.Data\r
31875         MOV      EDX, EBX\r
31876         CALL     ECX\r
31877 @@exit: POP      ESI\r
31878         POP      EBX\r
31879 end;\r
31880 {$ELSE ASM_VERSION} //Pascal\r
31881 procedure ComboboxDropDown( Sender: PObj );\r
31882 var\r
31883   CB: PControl;\r
31884   IC: Integer;\r
31885 begin\r
31886   CB := PControl( Sender );\r
31887   IC := CB.Count;\r
31888   if IC > 8 then IC := 8;\r
31889   if IC < 1 then IC := 1;\r
31891   SetWindowPos( CB.Handle, 0, 0, 0, CB.Width, CB.Height * (IC + 1) + 2,\r
31892                 SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_NOREDRAW +\r
31893                 SWP_HIDEWINDOW);\r
31895   SetWindowPos( CB.Handle, 0, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE\r
31896                 + SWP_NOZORDER + SWP_NOACTIVATE\r
31897                 + SWP_NOREDRAW + SWP_SHOWWINDOW);\r
31899   if assigned( CB.fOnDropDown ) then\r
31900     CB.fOnDropDown( CB );\r
31902 end;\r
31903 {$ELSE newcode}\r
31904 procedure ComboboxDropDown( Sender: PObj );\r
31905 var\r
31906   CB: PControl;\r
31907   Count: Integer;\r
31908   DropDownCount: Integer;\r
31909   ItemHeight: Integer;\r
31910 begin\r
31911   CB := PControl(Sender);\r
31913   Count := CB.Count;\r
31914   DropDownCount := CB.DropDownCount;\r
31915   DropDownCount := 8;\r
31916   if (Count > DropDownCount) then\r
31917     Count := DropDownCount;\r
31918   if (Count < 1) then\r
31919     Count := 1;\r
31920   ItemHeight := CB.Perform(CB_GETITEMHEIGHT, 0, 0);\r
31921   SetWindowPos(\r
31922     CB.Handle, 0, 0, 0, CB.Width, ItemHeight * Count + CB.Height + 2,\r
31923     SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_HIDEWINDOW);\r
31924   SetWindowPos(\r
31925     CB.Handle, 0, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or\r
31926     SWP_NOACTIVATE or SWP_NOREDRAW or SWP_SHOWWINDOW);\r
31928   if Assigned(CB.fOnDropDown) then\r
31929     CB.fOnDropDown(CB);\r
31930 end;\r
31931 {$ENDIF USE_DROPDOWNCOUNT}\r
31932 {$ENDIF ASM_VERSION}\r
31933 //[END ComboboxDropDown]\r
31935 //[function WndFuncCombo]\r
31936 function WndFuncCombo( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )\r
31937                                    : Integer; stdcall;\r
31938 var Combo, Form: PControl;\r
31939     ParentWnd : HWnd;\r
31940     MsgStruct: TMsg;\r
31941 //********************************************************** Added By M.Gerasimov\r
31942 //*\r
31943     PrevProc:Pointer;\r
31944 //*\r
31945 //********************************************************** Added By M.Gerasimov\r
31946 begin\r
31947    Combo := nil;\r
31949    ParentWnd := GetParent( W );\r
31950    if ParentWnd <> 0 then\r
31951      Combo := Pointer( GetProp( ParentWnd, ID_SELF ) );\r
31953    if Combo <> nil then\r
31954    begin\r
31955       MsgStruct.hwnd := Combo.fHandle;\r
31956       MsgStruct.message := Msg;\r
31957       MsgStruct.wParam := wParam;\r
31958       MsgStruct.lParam := lParam;\r
31959       Form := Combo.ParentForm;\r
31960       if fGlobalProcKeybd( Combo, MsgStruct, Result ) then Exit;\r
31961       if W <> Combo.FHandle then\r
31962       begin\r
31963         if Assigned( Applet ) and Assigned( Applet.OnMessage ) then\r
31964           if Applet.OnMessage( MsgStruct, Result ) then Exit;\r
31965         if (Applet <> Form) and (Form <> nil) then\r
31966         if Assigned( Form.OnMessage ) then\r
31967           if Form.OnMessage( MsgStruct, Result ) then Exit;\r
31968       end;\r
31969       if //(GetFocus = W) and\r
31970          (Msg = WM_KEYDOWN) or (Msg = WM_KEYUP) or (Msg = WM_CHAR) then\r
31971       begin\r
31972         Result := 0;\r
31973         if (wParam = VK_TAB) then\r
31974         begin\r
31975           case Msg of\r
31976           WM_KEYDOWN:\r
31977             if Assigned( Combo.fGotoControl ) and\r
31978                Combo.fGotoControl( Combo, wParam, FALSE ) then Exit;\r
31979           else Exit;\r
31980           end;\r
31981         end\r
31982           else\r
31983         if (Msg = WM_CHAR) and ((wParam = VK_ESCAPE) or (wParam = VK_RETURN)) then\r
31984         begin\r
31985           if Combo.Perform( CB_GETDROPPEDSTATE, 0, 0 ) <> 0 then\r
31986           begin\r
31987             Combo.Perform( CB_SHOWDROPDOWN, 0, 0 );\r
31988             if wParam = VK_ESCAPE then\r
31989               Combo.Perform( CB_SETCURSEL, Combo.fCurIdxAtDrop, 0 );\r
31990             Combo.fWndProcKeybd( Combo, MsgStruct, Result );\r
31991             Exit;\r
31992           end\r
31993           {$IFDEF ESC_CLOSE_DIALOGS}\r
31994               //---------------------------------Babenko Alexey--------------------------\r
31995               else\r
31996               if (wparam = VK_ESCAPE)  then\r
31997                 if (combo.ParentForm.ExStyle and WS_EX_DLGMODALFRAME) <> 0 then begin\r
31998                 SendMessage(combo.ParentForm.Handle, WM_CLOSE, 0, 0);\r
31999                 exit;\r
32000               end;\r
32001               //---------------------------------Babenko Alexey--------------------------\r
32002           {$ENDIF}\r
32003         end;\r
32004         Combo.fWndProcKeybd( Combo, MsgStruct, Result );\r
32005       end\r
32006         else\r
32007       if Msg = WM_SETFOCUS then\r
32008       begin\r
32009         if Form <> nil then Form.fCurrentControl := Combo;\r
32010       end;\r
32011       MsgStruct.hwnd := W;\r
32012 //********************************************************** Added By M.Gerasimov\r
32013 //*\r
32014       PrevProc:=Pointer(GetProp( W, ID_PREVPROC ));\r
32015       if PrevProc <> Nil then\r
32016        Result := CallWindowProc( PrevProc , W, Msg, wParam, lParam )\r
32017       else\r
32018        Result:=0;\r
32019 //*\r
32020 //********************************************************** Added By M.Gerasimov\r
32021 //     Result := CallWindowProc( //Combo.fPrevWndProc\r
32022 //           Pointer( GetProp( W, 'PREV_PROC' ) )\r
32023 //           , W, Msg, wParam, lParam );\r
32024 //**********************************************************\r
32025    end\r
32026       else\r
32027       Result := DefWindowProc( W, Msg, wParam, lParam );\r
32028 end;\r
32030 //[PROCEDURE CreateComboboxWnd]\r
32031 {$IFDEF ASM_VERSION}\r
32032 procedure CreateComboboxWnd( Combo: PControl );\r
32033 //********************************************************** Remarked By M.Gerasimov\r
32034 //const PrevProcStr: PChar = 'PREV_PROC';\r
32035 //********************************************************** Remarked By M.Gerasimov\r
32036 asm\r
32037         PUSH     EDI\r
32038         PUSH     EBX\r
32039         XCHG     EBX, EAX\r
32040         PUSH     GW_CHILD\r
32041         PUSH     [EBX].TControl.fHandle\r
32042         //XOR      EDI, EDI\r
32043 @@getwindow:\r
32044         CALL     GetWindow\r
32045         TEST     EAX, EAX\r
32046         JZ       @@fin\r
32047         {TEST     EDI, EDI\r
32048         XCHG     EDI, EAX\r
32049         JZ       @@2getnext}\r
32050         PUSH     offset[WndFuncCombo]\r
32051         PUSH     GWL_WNDPROC\r
32052         PUSH     EAX\r
32053         XCHG     EDI, EAX\r
32054         CALL     SetWindowLong\r
32055         PUSH     EAX\r
32056 //********************************************* By M.Gerasimov\r
32057 //      PUSH     [PrevProcStr]\r
32058 //************************************************************\r
32059         PUSH     offset [ID_PREVPROC]                       //\r
32060 //************************************************************\r
32061         PUSH     EDI\r
32062         CALL     SetProp\r
32063 @@2getnext:\r
32064         PUSH     GW_HWNDNEXT\r
32065         PUSH     EDI\r
32066         JMP      @@getwindow\r
32067 @@fin:  POP      EBX\r
32068         POP      EDI\r
32069 end;\r
32070 {$ELSE ASM_VERSION} //Pascal\r
32071 procedure CreateComboboxWnd( Combo: PControl );\r
32072 var W : HWND;\r
32073     PrevProc: DWORD;\r
32074 begin\r
32075    W := GetWindow( Combo.fHandle, GW_CHILD );\r
32076    {if W <> 0 then\r
32077      W := GetWindow( W, GW_HWNDNEXT );}\r
32078    while W <> 0 do\r
32079    begin\r
32080      PrevProc :=\r
32081        SetWindowLong( W, GWL_WNDPROC, Longint( @WndFuncCombo ) );\r
32082 //********************************************* By M.Gerasimov\r
32083 //   SetProp( W, 'PREV_PROC', PrevProc );\r
32084 //************************************************************\r
32085      SetProp( W, ID_PREVPROC, PrevProc );                   //\r
32086 //************************************************************\r
32087      W := GetWindow( W, GW_HWNDNEXT );\r
32088    end;\r
32089 end;\r
32090 {$ENDIF ASM_VERSION}\r
32091 //[END CreateComboboxWnd]\r
32093 //[procedure RemoveChldPrevProc]\r
32094 procedure RemoveChldPrevProc( fHandle: HWnd );\r
32095 var Chld: HWnd;\r
32096 begin\r
32097   Chld := GetWindow( fHandle, GW_CHILD );\r
32098   while Chld <> 0 do\r
32099   begin\r
32100     if GetProp( Chld, ID_PREVPROC ) <> 0 then\r
32101       RemoveProp(Chld, ID_PREVPROC);\r
32102     Chld := GetWindow( Chld, GW_HWNDNEXT );\r
32103   end;\r
32104 end;\r
32106 //[function WndProcCombo]\r
32107 function WndProcCombo( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32108 begin\r
32109   Result := FALSE;\r
32110   if (Msg.message >= WM_CTLCOLORMSGBOX) and (Msg.message <= WM_CTLCOLORSTATIC) then\r
32111   begin\r
32112     Rslt := Sender.Perform( Msg.message + CN_BASE, Msg.wParam, Msg.lParam );\r
32113     Result := TRUE;\r
32114   end\r
32115     else\r
32116   if //(Msg.message = CN_CTLCOLOREDIT)\r
32117      (Msg.message >= CN_CTLCOLORMSGBOX) and (Msg.message <= CN_CTLCOLORSTATIC)\r
32118      {and not AppletTerminated} then\r
32119   begin\r
32120     if Sender.fTransparent then\r
32121     case Msg.message of\r
32122     CN_CTLCOLORLISTBOX:\r
32123       begin\r
32124         SetBkMode( Msg.wParam, Windows.OPAQUE );\r
32125         SetBkColor(Msg.WParam, Color2RGB( Sender.fColor ) );\r
32126         Rslt := Global_GetCtlBrushHandle( Sender );\r
32127         Result := TRUE;\r
32128       end;\r
32129 //********************************************************** Added By M.Gerasimov\r
32130 //*\r
32131      WM_DESTROY:\r
32132        RemoveChldPrevProc( Sender.Handle );\r
32133 //*\r
32134 //********************************************************** Added By M.Gerasimov\r
32135     else\r
32136     if not Sender.DblBufTopParent.fDblBufPainting then\r
32137       Sender.Invalidate;\r
32138     end;\r
32139     //Result := FALSE;\r
32140   end\r
32141     else\r
32142   if Msg.message = CM_COMMAND then\r
32143   begin\r
32144     case HiWord( Msg.wParam ) of\r
32145     CBN_DROPDOWN:\r
32146          begin\r
32147            Sender.fDropped := True;\r
32148            Sender.fCurIdxAtDrop := Sender.CurIndex;\r
32149            Sender.fDropDownProc( Sender );\r
32150          end;\r
32151     CBN_CLOSEUP:\r
32152          begin\r
32153            Sender.fDropped := False;\r
32154            if Assigned( Sender.fOnCloseUp ) then Sender.fOnCloseUp( Sender );\r
32155          end;\r
32156     CBN_SELCHANGE:\r
32157          begin\r
32158            PostMessage( Sender.fHandle, CM_COMMAND, CM_CBN_SELCHANGE shl 16, 0 );\r
32159          end;\r
32160     end;\r
32161   end;\r
32162 end;\r
32164 const ComboFlags: array[ TComboOption ] of Integer = (\r
32165       CBS_DROPDOWNLIST, not CBS_AUTOHScroll,\r
32166       CBS_DISABLENOSCROLL, CBS_LowerCase, CBS_NoIntegralHeight,\r
32167       CBS_OemConvert, CBS_Sort, CBS_UpperCase,\r
32168       CBS_OWNERDRAWFIXED, CBS_OWNERDRAWVARIABLE, CBS_SIMPLE );\r
32170 {$IFDEF USE_CONSTRUCTORS}\r
32171 //[function NewCombobox]\r
32172 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;\r
32173 begin\r
32174   new( Result, CreateCombobox( AParent, Options ) );\r
32175 end;\r
32176 {$ELSE not_USE_CONSTRUCTORS}\r
32178 //[FUNCTION NewCombobox]\r
32179 {$IFDEF ASM_VERSION}\r
32180 const ComboboxClass: array[0..8] of Char = ('C','O','M','B','O','B','O','X',#0 );\r
32181 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;\r
32182 asm\r
32183         PUSH     EDX\r
32184         PUSH     EAX\r
32185         PUSH     EDX\r
32186         MOV      EAX, ESP\r
32187         MOV      EDX, offset[ComboFlags]\r
32188         XOR      ECX, ECX\r
32189         MOV      CL, 10\r
32190         CALL     MakeFlags\r
32191         POP      EDX\r
32192         XCHG     ECX, EAX\r
32193         POP      EAX\r
32194         PUSH     1\r
32195         PUSH     offset[ComboActions]\r
32196         MOV      EDX, offset[ComboboxClass]\r
32197         OR       ECX, WS_VISIBLE or WS_CHILD or WS_VSCROLL or CBS_HASSTRINGS or WS_TABSTOP\r
32198         TEST     ECX, CBS_SIMPLE\r
32199         JNZ      @@O\r
32200         OR       ECX, CBS_DROPDOWN\r
32201 @@O:\r
32202         CALL     _NewControl\r
32203         MOV      [EAX].TControl.fCreateWndExt, offset[CreateComboboxWnd]\r
32204         MOV      [EAX].TControl.fDropDownProc, offset[ComboboxDropDown]\r
32205         OR       byte ptr [EAX].TControl.fClsStyle, CS_DBLCLKS\r
32206         ADD      [EAX].TControl.fBoundsRect.Right, 100-64\r
32207         ADD      [EAX].TControl.fBoundsRect.Bottom, 22-64\r
32208         //MOV      [EAX].TControl.fColor, clWindow\r
32209         MOV      CL, 1\r
32210         POP      EDX\r
32211         TEST     DL, 1\r
32212         JZ       @@exit\r
32213         MOV      CL, 3\r
32214 @@exit:\r
32215         MOV      [EAX].TControl.fLookTabKeys, CL\r
32216         PUSH     EAX\r
32217         MOV      EDX, offset[ WndProcCombo ]\r
32218         CALL     TControl.AttachProc\r
32219         POP      EAX\r
32220 end;\r
32221 {$ELSE ASM_VERSION} //Pascal\r
32222 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;\r
32223 var Flags: Integer;\r
32224 begin\r
32225   Flags := MakeFlags( @Options, ComboFlags );\r
32226   if not LongBool( Flags and CBS_SIMPLE ) then\r
32227     Flags := Flags or CBS_DROPDOWN;\r
32228   Result := _NewControl( AParent, 'COMBOBOX',\r
32229                          WS_VISIBLE\r
32230                          or WS_CHILD\r
32231                          or WS_VSCROLL\r
32232                          or CBS_HASSTRINGS or WS_TABSTOP\r
32233                          or Flags\r
32234                          , True, @ComboActions );\r
32235   //Result.fCannotDoubleBuf := TRUE;\r
32236   Result.fCreateWndExt := CreateComboboxWnd;\r
32237   Result.fDropDownProc := ComboboxDropDown;\r
32238   Result.fClsStyle := Result.fClsStyle or CS_DBLCLKS;\r
32239   with Result.fBoundsRect do\r
32240   begin\r
32241     Right := Left + 100;\r
32242     Bottom := Top + 22;\r
32243   end;\r
32244   Result.fLookTabKeys := [ tkTab ];\r
32245   if coReadOnly in Options then\r
32246     Result.fLookTabKeys := [ tkTab, tkLeftRight ];\r
32247   Result.AttachProc( @ WndProcCombo );\r
32248   {$IFDEF USE_DROPDOWNCOUNT}\r
32249   Result.DropDownCount := 8;\r
32250   {$ENDIF}\r
32251 end;\r
32252 {$ENDIF ASM_VERSION}\r
32253 //[END NewCombobox]\r
32255 {$ENDIF USE_CONSTRUCTORS}\r
32257 //[FUNCTION WndProcResiz]\r
32258 {$IFDEF ASM_VERSION}\r
32259 function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32260 asm\r
32261         PUSH     ESI\r
32262         CMP      word ptr [EDX].TMsg.message, WM_SIZE\r
32263         JNZ      @@exit\r
32265         MOV      ESI, [EAX].TControl.fChildren\r
32266         MOV      ECX, [ESI].TList.fCount\r
32267         JECXZ    @@exit\r
32268         MOV      ESI, [ESI].TList.fItems\r
32269 @@loo:  PUSH     ECX\r
32270         LODSD\r
32271         PUSH     EAX\r
32272         PUSH     EAX\r
32273         PUSH     CM_SIZE\r
32274         PUSH     EAX\r
32275         CALL     TControl.Perform\r
32276         POP      ECX\r
32277         LOOP     @@loo\r
32279 @@exit: XOR      EAX, EAX\r
32280         POP      ESI\r
32281 end;\r
32282 {$ELSE ASM_VERSION} //Pascal\r
32283 function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32284 var I: Integer;\r
32285     C: PControl;\r
32286 begin\r
32287   if Msg.message = WM_SIZE then\r
32288   begin\r
32289     for I:= 0 to Self_.fChildren.fCount - 1 do\r
32290     begin\r
32291       C := Self_.fChildren.fItems[ I ];\r
32292       C.Perform( CM_SIZE, 0, 0 );\r
32293     end;\r
32294   end;\r
32295   Result := False; // don't stop further processing\r
32296 end;\r
32297 {$ENDIF ASM_VERSION}\r
32298 //[END WndProcResiz]\r
32300 //[FUNCTION WndProcParentResize]\r
32301 {$IFDEF ASM_VERSION}\r
32302 function WndProcParentResize( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32303 asm\r
32304         CMP      word ptr [EDX].TMsg.message, CM_SIZE\r
32305         JNZ      @@exit\r
32306         PUSH     0\r
32307         PUSH     0\r
32308         PUSH     WM_SIZE\r
32309         PUSH     EAX\r
32310         CALL     TControl.Perform\r
32311 @@exit: XOR      EAX, EAX\r
32312 end;\r
32313 {$ELSE ASM_VERSION} //Pascal\r
32314 function WndProcParentResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32315 begin\r
32316   Result := False;\r
32317   case Msg.message of\r
32318   CM_SIZE:\r
32319     begin\r
32320       Self_.Perform( WM_SIZE, 0, 0 );\r
32321     end;\r
32322   end;\r
32323 end;\r
32324 {$ENDIF ASM_VERSION}\r
32325 //[END WndProcParentResize]\r
32327 //[procedure InitCommonControlCommonNotify]\r
32328 procedure InitCommonControlCommonNotify( Ctrl: PControl );\r
32329 var AParent: PControl;\r
32330 begin\r
32331   Ctrl.fIsCommonControl := True;\r
32332   AParent := Ctrl.Parent;\r
32333   if AParent <> nil then\r
32334   begin\r
32335     Ctrl.AttachProc( WndProcCommonNotify );\r
32336     AParent.AttachProc( WndProcNotify );\r
32337   end;\r
32338 end;\r
32340 //[procedure InitCommonControlSizeNotify]\r
32341 procedure InitCommonControlSizeNotify( Ctrl: PControl );\r
32342 var AParent: PControl;\r
32343 begin\r
32344   AParent := Ctrl.Parent;\r
32345   if AParent <> nil then\r
32346   begin\r
32347     Ctrl.AttachProc( WndProcParentResize );\r
32348     AParent.AttachProc( WndProcResize );\r
32349   end;\r
32350 end;\r
32352 //[function _NewCommonControl]\r
32353 function _NewCommonControl( AParent: PControl; ClassName: PChar; Style: DWORD;\r
32354                             Ctl3D: Boolean; Actions: PCommandActions ): PControl;\r
32355 begin\r
32356   {*************} DoInitCommonControls( ICC_WIN95_CLASSES );\r
32357   Result := _NewControl( AParent, ClassName, Style, Ctl3D, Actions );\r
32358   //InitCommonControlSizeNotify( Result );\r
32359   InitCommonControlCommonNotify( Result );\r
32360 end;\r
32362 //==================== Progress bar ======================//\r
32364 {$IFDEF USE_CONSTRUCTORS}\r
32365 //[function NewProgressbar]\r
32366 function NewProgressbar( AParent: PControl ): PControl;\r
32367 begin\r
32368   new( Result, CreateProgressbar( AParent ) );\r
32369 end;\r
32370 //[END NewProgressbar]\r
32371 {$ELSE not_USE_CONSTRUCTORS}\r
32373 //[FUNCTION NewProgressbar]\r
32374 {$IFDEF ASM_VERSION}\r
32375 function NewProgressbar( AParent: PControl ): PControl;\r
32376 asm\r
32377         PUSH     1\r
32378         PUSH     0\r
32379         MOV      EDX, offset[Progress_class]\r
32380         MOV      ECX, WS_CHILD or WS_VISIBLE\r
32381         CALL     _NewCommonControl\r
32382         LEA      EDX, [EAX].TControl.fBoundsRect\r
32383         MOV      ECX, [EDX].TRect.Left\r
32384         ADD      ECX, 300\r
32385         MOV      [EDX].TRect.Right, ECX\r
32386         MOV      ECX, [EDX].TRect.Top\r
32387         ADD      ECX, 20\r
32388         MOV      [EDX].TRect.Bottom, ECX\r
32389         XOR      EDX, EDX\r
32390         MOV      [EAX].TControl.fMenu, EDX\r
32391         MOV      [EAX].TControl.fTextColor, clHighlight\r
32392         MOV      [EAX].TControl.fCommandActions.aSetBkColor, PBM_SETBKCOLOR\r
32393 end;\r
32394 {$ELSE ASM_VERSION} //Pascal\r
32395 function NewProgressbar( AParent: PControl ): PControl;\r
32396 begin\r
32397   Result := _NewCommonControl( AParent, PROGRESS_CLASS,\r
32398             WS_CHILD or WS_VISIBLE, True, nil );\r
32399   with Result.fBoundsRect do\r
32400   begin\r
32401     Right := Left + 300;\r
32402     Bottom := Top + 20;\r
32403   end;\r
32404   Result.fMenu := 0;\r
32405   Result.fTextColor := clHighlight;\r
32406   Result.fCommandActions.aSetBkColor := PBM_SETBKCOLOR;\r
32407 end;\r
32408 {$ENDIF ASM_VERSION}\r
32409 //[END NewProgressbar]\r
32411 {$ENDIF USE_CONSTRUCTORS}\r
32413 {$IFDEF USE_CONSTRUCTORS}\r
32414 //[function NewProgressbarEx]\r
32415 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;\r
32416 begin\r
32417   new( Result, CreateProgressbarEx( AParent, Options ) );\r
32418 end;\r
32419 //[END NewProgressbarEx]\r
32420 {$ELSE not_USE_CONSTRUCTORS}\r
32422 //[FUNCTION NewProgressbarEx]\r
32423 {$IFDEF ASM_VERSION}\r
32424 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;\r
32425 asm\r
32426         PUSH     EDX\r
32427         CALL     NewProgressbar\r
32428         POP      ECX\r
32429         XOR      EDX, EDX\r
32430         SHR      ECX, 1\r
32431         JNC      @@notVert\r
32432         MOV      DL, 4\r
32433 @@notVert:\r
32434         SHR      ECX, 1\r
32435         JNC      @@notSmooth\r
32436         INC      EDX\r
32437 @@notSmooth:\r
32438         OR       [EAX].TControl.fStyle, EDX\r
32439 end;\r
32440 {$ELSE ASM_VERSION} //Pascal\r
32441 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;\r
32442 const ProgressBarFlags: array[ TProgressbarOption ] of Integer =\r
32443       (PBS_VERTICAL, PBS_SMOOTH );\r
32444 begin\r
32445   Result := NewProgressbar( AParent );\r
32446   Result.fStyle := Result.fStyle or DWORD( MakeFlags( @Options, ProgressBarFlags ) );\r
32447 end;\r
32448 {$ENDIF ASM_VERSION}\r
32449 //[END NewProgressbarEx]\r
32451 {$ENDIF USE_CONSTRUCTORS}\r
32453 //===================== List view ========================//\r
32455 //[FUNCTION WndProcNotify]\r
32456 {$IFDEF ASM_VERSION}\r
32457 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32458 asm\r
32459         CMP      word ptr [EDX].TMsg.message, WM_NOTIFY\r
32460         JNE      @@ret_false\r
32461         PUSH     ECX\r
32462         PUSH     EDX\r
32463         PUSH     offset[ID_SELF]\r
32464         MOV      ECX, [EDX].TMsg.lParam\r
32465         PUSH     [ECX].TNMHdr.hwndFrom\r
32466         CALL     GetProp\r
32467         POP      EDX\r
32468         TEST     EAX, EAX\r
32469         JZ       @@ret_false_ECX\r
32470         MOV      ECX, [EAX].TControl.fHandle\r
32471         MOV      [EDX].TMsg.hwnd, ECX\r
32472         POP      ECX\r
32473         JMP      TControl.EnumDynHandlers\r
32474 @@ret_false_ECX:\r
32475         POP      ECX\r
32476 @@ret_false:\r
32477         XOR      EAX, EAX\r
32478 end;\r
32479 {$ELSE ASM_VERSION} //Pascal\r
32480 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32481 var NMhdr: PNMHdr;\r
32482     Child: PControl;\r
32483 begin\r
32484   Result := False;\r
32485   if Msg.message = WM_NOTIFY then\r
32486   begin\r
32487     NMhdr := Pointer( Msg.lParam );\r
32488     Child := Pointer( GetProp( NMhdr.hwndFrom, ID_SELF ) );\r
32489     if Child <> nil then\r
32490     begin\r
32491       {if Child = Self_ then\r
32492       begin\r
32493         Rslt := Self_.CallDefWndProc( Msg );\r
32494         Result := TRUE;\r
32495       end\r
32496         else}\r
32497       begin\r
32498         Msg.hwnd := Child.fHandle;\r
32499         Result := EnumDynHandlers( Child, Msg, Rslt );\r
32500       end;\r
32501     end;\r
32502   end;\r
32503 end;\r
32504 {$ENDIF ASM_VERSION}\r
32505 //[END WndProcNotify]\r
32507 //[FUNCTION WndProcCommonNotify]\r
32508 {$IFDEF ASM_VERSION}\r
32509 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32510 asm\r
32511         CMP      word ptr [EDX].TMsg.message, WM_NOTIFY\r
32512         JNE      @@ret_false\r
32513         PUSH     EBX\r
32514         MOV      EBX, [EDX].TMsg.lParam\r
32515         MOV      EDX, [EBX].TNMHdr.code\r
32517 @@chk_nm_click:\r
32518         XOR      ECX, ECX\r
32519         CMP      EDX, NM_CLICK\r
32520         JZ       @@click\r
32521         CMP      EDX, NM_RCLICK\r
32522         JNE      @@chk_killfocus\r
32523         INC      ECX\r
32524 @@click:\r
32525         MOV      [EAX].TControl.fRightClick, CL\r
32527         MOV      ECX, [EAX].TControl.fOnClick.TMethod.Code\r
32528         JECXZ    @@fin_false\r
32529         MOV      EDX, [EAX].TControl.fOnClick.TMethod.Data\r
32530         JMP      @@fin_event\r
32532 @@fin_false:\r
32533         POP      EBX\r
32534 @@ret_false:\r
32535         XOR      EAX, EAX\r
32536         RET\r
32538 @@chk_killfocus:\r
32539         CMP      EDX, NM_KILLFOCUS\r
32540         JNE      @@chk_setfocus\r
32541         MOV      ECX, [EAX].TControl.fOnLeave.TMethod.Code\r
32542         JECXZ    @@fin_false\r
32543         MOV      EDX, [EAX].TControl.fOnLeave.TMethod.Data\r
32544         JMP      @@fin_event\r
32545 @@chk_setfocus:\r
32546         CMP      EDX, NM_RETURN\r
32547         JE       @@set_focus\r
32548         CMP      EDX, NM_SETFOCUS\r
32549         JNE      @@fin_false\r
32551 @@set_focus:\r
32552         MOV      ECX, [EAX].TControl.fOnEnter.TMethod.Code\r
32553         JECXZ    @@fin_false\r
32554         MOV      EDX, [EAX].TControl.fOnEnter.TMethod.Data\r
32556 @@fin_event:\r
32557         XCHG     EAX, EDX\r
32558         CALL     ECX\r
32559         POP      EBX\r
32560         MOV      AL, 1\r
32561 end;\r
32562 {$ELSE ASM_VERSION} //Pascal\r
32563 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32564 var NMhdr: PNMHdr;\r
32565 begin\r
32566   Result := False;\r
32567   if Msg.message = WM_NOTIFY then\r
32568   begin\r
32569     NMHdr := Pointer( Msg.lParam );\r
32570     case NMHdr.code of\r
32571       NM_RCLICK,\r
32572       NM_CLICK:  if assigned( Self_.fOnClick ) then\r
32573                  begin\r
32574                     Self_.fRightClick := NMHdr.code=NM_RCLICK;\r
32575                     Self_.fOnClick( Self_ );\r
32576                     Result := TRUE;\r
32577                  end;\r
32578       NM_KILLFOCUS: if assigned( Self_.fOnLeave ) then\r
32579                     Self_.fOnLeave( Self_ );\r
32580       NM_RETURN,\r
32581       NM_SETFOCUS: if assigned( Self_.fOnEnter ) then\r
32582                     Self_.fOnEnter( Self_ );\r
32583     end;\r
32584   end;\r
32585 end;\r
32586 {$ENDIF ASM_VERSION}\r
32587 //[END WndProcCommonNotify]\r
32589 const ListViewStyles: array[ TListViewStyle ] of DWORD = ( LVS_ICON, LVS_SMALLICON,\r
32590                       LVS_LIST, LVS_REPORT, LVS_REPORT or LVS_NOCOLUMNHEADER );\r
32591       ListViewFlags: array[ TListViewOption ] of Integer = ( LVS_ALIGNLEFT, LVS_AUTOARRANGE,\r
32592                       $400 {LVS_BUTTON}, LVS_EDITLABELS, LVS_NOLABELWRAP,\r
32593                       LVS_NOSCROLL, LVS_NOSORTHEADER,\r
32594                       not LVS_SHOWSELALWAYS, not LVS_SINGLESEL, LVS_SORTASCENDING,\r
32595                       LVS_SORTDESCENDING, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
32596                       LVS_OWNERDATA, LVS_OWNERDRAWFIXED );\r
32598       ListViewExFlags: array[ TListViewOption ] of Integer = ( 0, 0,\r
32599                       0, 0, 0, 0, 0, 0, 0, 0, 0, LVS_EX_GRIDLINES,\r
32600                       LVS_EX_SUBITEMIMAGES, LVS_EX_CHECKBOXES, LVS_EX_TRACKSELECT,\r
32601                       LVS_EX_HEADERDRAGDROP, LVS_EX_FULLROWSELECT, LVS_EX_ONECLICKACTIVATE,\r
32602                       LVS_EX_TWOCLICKACTIVATE, LVS_EX_FLATSB, LVS_EX_REGIONAL,\r
32603                       LVS_EX_INFOTIP, LVS_EX_UNDERLINEHOT, LVS_EX_MULTIWORKAREAS, 0, 0 );\r
32606 //[FUNCTION ApplyImageLists2Control]\r
32607 {$IFDEF ASM_VERSION}\r
32608 procedure ApplyImageLists2Control( Sender: PControl );\r
32609 asm\r
32610         PUSHAD\r
32611         XCHG     ESI, EAX\r
32612         MOVZX    ECX, [ESI].TControl.fCommandActions.aSetImgList\r
32613         JECXZ    @@fin\r
32614         MOV      EBP, ECX\r
32615         XOR      EBX, EBX\r
32616         MOV      BL, 32\r
32617         XOR      EDI, EDI\r
32618 @@loo:\r
32619         MOV      EAX, ESI\r
32620         MOV      EDX, EBX\r
32621         CALL     TControl.GetImgListIdx\r
32622         TEST     EAX, EAX\r
32623         JZ       @@nx\r
32624         CALL     TImageList.GetHandle\r
32625         PUSH     EAX\r
32626         PUSH     EDI\r
32627         PUSH     EBP\r
32628         PUSH     ESI\r
32629         CALL     TControl.Perform\r
32630 @@nx:\r
32631         INC      EDI\r
32632         SHR      EBX, 1\r
32633         JZ       @@fin\r
32634         CMP      BL, 16\r
32635         JGE      @@loo\r
32636         XOR      EBX, EBX\r
32637         JMP      @@loo\r
32638 @@fin:\r
32639         POPAD\r
32640 end;\r
32641 {$ELSE ASM_VERSION} //Pascal\r
32642 procedure ApplyImageLists2Control( Sender: PControl );\r
32643 var IL: PImageList;\r
32644 begin\r
32645   if Sender.fCommandActions.aSetImgList = 0 then Exit;\r
32646   IL := Sender.ImageListNormal;\r
32647   if IL <> nil then\r
32648     Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_NORMAL, IL.Handle );\r
32649   IL := Sender.ImageListSmall;\r
32650   if IL <> nil then\r
32651     Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_SMALL, IL.Handle );\r
32652   IL := Sender.ImageListState;\r
32653   if IL <> nil then\r
32654     Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_STATE, IL.Handle );\r
32655 end;\r
32656 {$ENDIF ASM_VERSION}\r
32657 //[END ApplyImageLists2Control]\r
32659 //[FUNCTION ApplyImageLists2ListView]\r
32660 {$IFDEF ASM_VERSION}\r
32661 procedure ApplyImageLists2ListView( Sender: PControl );\r
32662 asm\r
32663         PUSHAD\r
32665         XCHG     ESI, EAX\r
32666         PUSH     dword ptr [ESI].TControl.fLVOptions\r
32667         MOV      EAX, ESP\r
32668         MOV      EDX, offset[ListViewFlags]\r
32669         XOR      ECX, ECX\r
32670         MOV      CL, 25\r
32671         CALL     MakeFlags\r
32672         POP      ECX\r
32673         PUSH     ECX\r
32675         MOV      EDX, [ESI].TControl.fStyle\r
32676         //AND      DH, 3\r
32677         AND      DX, not $403F\r
32678         OR       EDX, EAX\r
32680         MOVZX    EAX, [ESI].TControl.fLVStyle\r
32681         OR       EDX, [EAX*4 + offset ListViewStyles]\r
32683         MOV      EAX, ESI\r
32684         CALL     TControl.SetStyle\r
32686         MOV      EAX, ESP\r
32687         MOV      EDX, offset[ListViewExFlags]\r
32688         XOR      ECX, ECX\r
32689         MOV      CL, 23\r
32690         CALL     MakeFlags\r
32691         POP      EDX\r
32692         PUSH     EAX\r
32693         PUSH     $3FFF\r
32694         PUSH     LVM_SETEXTENDEDLISTVIEWSTYLE\r
32695         PUSH     ESI\r
32696         CALL     TControl.Perform\r
32698         POPAD\r
32699         CALL     ApplyImageLists2Control\r
32700 end;\r
32701 {$ELSE ASM_VERSION} //Pascal\r
32702 procedure ApplyImageLists2ListView( Sender: PControl );\r
32703 var Flags: DWORD;\r
32704 begin\r
32705   Flags := MakeFlags( @Sender.fLVOptions, ListViewFlags );\r
32706   Sender.Style := Sender.Style and not $403F\r
32707                   or Flags or ListViewStyles[ Sender.fLVStyle ];\r
32708   Flags := MakeFlags( @Sender.fLVOptions, ListViewExFlags );\r
32709   Sender.Perform( LVM_SETEXTENDEDLISTVIEWSTYLE, $3FFF, Flags );\r
32710   ApplyImageLists2Control( Sender );\r
32711 end;\r
32712 {$ENDIF ASM_VERSION}\r
32713 //[END ApplyImageLists2ListView]\r
32715 {$IFDEF USE_CONSTRUCTORS}\r
32716 //[function NewListView]\r
32717 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;\r
32718                       ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;\r
32719 begin\r
32720   new( Result, CreateListView( AParent, Style, Options, ImageListSmall,\r
32721                ImageListNormal, ImageListState ) );\r
32722 end;\r
32723 //[END NewListView]\r
32724 {$ELSE not_USE_CONSTRUCTORS}\r
32726 //[FUNCTION NewListView]\r
32727 {$IFDEF ASM_VERSION}\r
32728 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;\r
32729                       ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;\r
32730 asm\r
32731         PUSH     EDX\r
32732         PUSH     ECX\r
32733         MOVZX    EDX, DL\r
32734         MOV      ECX, [EDX*4 + offset ListViewStyles]\r
32735         OR       ECX, LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP\r
32736         MOV      EDX, offset[WC_LISTVIEW]\r
32737         PUSH     1\r
32738         PUSH     offset[ListViewActions]\r
32739         CALL     _NewCommonControl\r
32741         MOV      EDX, ESP\r
32742         PUSH     EAX\r
32743         XCHG     EAX, EDX\r
32744         MOV      EDX, offset ListViewFlags\r
32745         XOR      ECX, ECX\r
32746         MOV      CL, 25\r
32747         CALL     MakeFlags\r
32748         XCHG     EDX, EAX\r
32749         POP      EAX\r
32750         MOV      ECX, [EAX].TControl.fStyle\r
32751         AND      ECX, not LVS_TYPESTYLEMASK\r
32752         OR       EDX, ECX\r
32753         MOV      [EAX].TControl.fStyle, EDX\r
32755         POP      [EAX].TControl.fLVOptions\r
32756         POP      EDX\r
32757         MOV      [EAX].TControl.fLVStyle, DL\r
32758         MOV      [EAX].TControl.fCreateWndExt, offset[ApplyImageLists2ListView]\r
32759         ADD      [EAX].TControl.fBoundsRect.Right, 200-64\r
32760         ADD      [EAX].TControl.fBoundsRect.Bottom, 150-64\r
32761         MOV      ECX, [ImageListState]\r
32762         XOR      EDX, EDX\r
32763         PUSHAD\r
32764         CALL     TControl.SetImgListIdx\r
32765         POPAD\r
32766         MOV      ECX, [ImageListSmall]\r
32767         MOV      DL, 16\r
32768         PUSHAD\r
32769         CALL     TControl.SetImgListIdx\r
32770         POPAD\r
32771         MOV      ECX, [ImageListNormal]\r
32772         ADD      EDX, EDX\r
32773         PUSH     EAX\r
32774         CALL     TControl.SetImgListIdx\r
32775         POP      EAX\r
32776         MOV      [EAX].TControl.fLVTextBkColor, clWindow\r
32777         XOR      EDX, EDX\r
32778         //MOV      [EAX].TControl.fMargin, EDX\r
32779         INC      EDX\r
32780         MOV      [EAX].TControl.fLookTabKeys, DL\r
32781 end;\r
32782 {$ELSE ASM_VERSION} //Pascal\r
32783 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;\r
32784                       ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;\r
32785 begin\r
32786   Result := _NewCommonControl( AParent, WC_LISTVIEW, ListViewStyles[ Style ] or\r
32787                                LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_CLIPCHILDREN,\r
32788                                True, @ListViewActions );\r
32790   Result.fLVOptions := Options;\r
32791   Result.fLVStyle := Style;\r
32792   Result.fStyle := Result.fStyle and not LVS_TYPESTYLEMASK\r
32793                   or DWORD( MakeFlags( @Options, ListViewFlags ) );\r
32794   Result.fCreateWndExt := ApplyImageLists2ListView;\r
32795   with Result.fBoundsRect do\r
32796   begin\r
32797     Right := Left + 200;\r
32798     Bottom := Top + 150;\r
32799   end;\r
32800   Result.ImageListSmall := ImageListSmall;\r
32801   Result.ImageListNormal := ImageListNormal;\r
32802   Result.ImageListState := ImageListState;\r
32803   Result.fLVTextBkColor := clWindow;\r
32804   Result.fLookTabKeys := [ tkTab ];\r
32805   //Result.fMargin := 0;\r
32806 end;\r
32807 {$ENDIF ASM_VERSION}\r
32808 //[END NewListView]\r
32810 {$ENDIF USE_CONSTRUCTORS}\r
32812 //=====================  Tree view  ========================//\r
32814 //[FUNCTION WndProcTreeView]\r
32815 {$IFDEF ASM_VERSION}\r
32816 function WndProcTreeView( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
32817 asm     //cmd    //opd\r
32818         CMP      word ptr [EDX].TMsg.message, WM_NOTIFY\r
32819         JNZ      @@ret_false\r
32820         PUSH     EBX\r
32821         XCHG     EBX, EAX\r
32822         MOV      EDX, [EDX].TMsg.lParam\r
32823         LEA      EAX, [EBX].TControl.fOnTVBeginDrag\r
32824         CMP      word ptr [EDX].TNMTreeView.hdr.code, NM_RCLICK\r
32825         JNE      @@chk_TVN_BEGINDRAG\r
32826         PUSH     ECX\r
32827         PUSH     ECX\r
32828         PUSH     ESP\r
32829         CALL     GetCursorPos\r
32830         MOV      EAX, EBX\r
32831         MOV      EDX, ESP\r
32832         MOV      ECX, EDX\r
32833         CALL     TControl.Screen2Client\r
32834         POP      EAX\r
32835         AND      EAX, $FFFF\r
32836         POP      EDX\r
32837         SHL      EDX, 16\r
32838         OR       EAX, EDX\r
32839         PUSH     EAX\r
32840         CALL     GetShiftState\r
32841         PUSH     EAX\r
32842         PUSH     WM_RBUTTONUP\r
32843         PUSH     [EBX].TControl.fHandle\r
32844         CALL     PostMessage\r
32845         JMP      @@2fin_false1\r
32847 @@chk_TVN_BEGINDRAG:\r
32848         {$IFDEF UNICODE_CTRLS}\r
32849         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINDRAGW\r
32850         JZ       @@event_drag\r
32851         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINRDRAGW\r
32852         JZ       @@event_drag\r
32853         {$ENDIF UNICODE_CTRLS}\r
32854         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINDRAG\r
32855         JZ       @@event_drag\r
32856         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINRDRAG\r
32857         JNZ      @@chk_BEGINLABELEDIT\r
32858 @@event_drag:\r
32859         MOV      EDX, [EDX].TNMTreeView.itemNew.hItem\r
32860 @@event_call:\r
32861         MOV      ECX, [EAX].TMethod.Code\r
32862         JECXZ    @@2fin_false1\r
32863         MOV      EAX, [EAX].TMethod.Data\r
32864         XCHG     EBX, ECX\r
32865         XCHG     EDX, ECX\r
32866         CALL     EBX\r
32867 @@2fin_false1:   JMP      @@fin_false\r
32868 @@chk_BEGINLABELEDIT:\r
32869         LEA      EAX, [EBX].TControl.fOnTVBeginEdit\r
32870         {$IFDEF UNICODE_CTRLS}\r
32871         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINLABELEDITW\r
32872         JZ       @@beginlabeledit\r
32873         {$ENDIF UNICODE_CTRLS}\r
32874         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINLABELEDIT\r
32875         JNZ      @@chk_ITEMEXPANDED //@@chk_DELETEITEM\r
32876 @@beginlabeledit:\r
32878         CMP      [EBX].TControl.fDragging, 0\r
32879         JZ       @@allow_LABELEDIT\r
32880         XOR      EAX, EAX\r
32881         INC      EAX\r
32882         MOV      [ECX], EAX\r
32883         JMP      @@ret_true\r
32885 @@allow_LABELEDIT:\r
32886         PUSH     ECX // @Rslt\r
32888         MOV      ECX, [EAX].TMethod.Code\r
32889         JECXZ    @@2fin_false1\r
32890         PUSH     EBX\r
32891         XCHG     EBX, ECX\r
32892         MOV      EDX, [EDX].TTVDispInfo.item.hItem\r
32893         XCHG     EDX, ECX\r
32894         MOV      EAX, [EAX].TMethod.Data\r
32895         CALL     EBX\r
32896         TEST     AL, AL\r
32897         SETZ     AL        // Rslt := not event result;\r
32898         POP      EBX\r
32899         JZ       @@ret_EAX\r
32900         INC      [EBX].TControl.fEditing\r
32901         JMP      @@ret_EAX\r
32903 @@call_EBX:\r
32904         CALL     EBX\r
32905 @@2fin_false:\r
32906         JMP      @@fin_false\r
32907 @@chk_ITEMEXPANDED:\r
32908         LEA      EAX, [EBX].TControl.fOnTVExpanded\r
32909         {$IFDEF UNICODE_CTRLS}\r
32910         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDEDW\r
32911         JZ       @@itemexpanded\r
32912         {$ENDIF UNICODE_CTRLS}\r
32913         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDED\r
32914         JNZ      @@chk_SELCHANGING\r
32915 @@itemexpanded:\r
32916         MOV      ECX, [EAX].TMethod.Code\r
32917         JECXZ    @@2fin_false\r
32918         CMP      [EDX].TNMTreeView.action, TVE_EXPAND\r
32919         PUSH     ECX\r
32920         SETZ     CL\r
32921         XCHG     ECX, [ESP]\r
32922         JMP      @@event_drag\r
32923 @@chk_SELCHANGING:\r
32924         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGING\r
32925         JNE      @@chk_ITEMEXPANDING\r
32926         XCHG     EAX, ECX\r
32927         MOV      ECX, [EBX].TControl.fOnTVSelChanging.TMethod.Code\r
32928 @@2fin_false2:\r
32929         JECXZ    @@2fin_false\r
32930         PUSH     EAX  //@Rslt\r
32931         PUSH     [EDX].TNMTreeView.itemNew.hItem\r
32932         XCHG     ECX, EBX //EBX=OnTVSelChanging.Code ECX=Sender\r
32933         XCHG     ECX, EDX //EDX=Sender ECX=Msg\r
32934         MOV      ECX, [ECX].TNMTreeView.itemOld.hItem\r
32935         MOV      EAX, [EDX].TControl.fOnTVSelChanging.TMethod.Data\r
32936         JMP      @@111\r
32938 @@chk_ITEMEXPANDING:\r
32939         {$IFDEF UNICODE_CTRLS}\r
32940         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDINGW\r
32941         JZ       @@itemexpanding\r
32942         {$ENDIF UNICODE_CTRLS}\r
32943         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDING\r
32944         JNE      @@chk_ENDLABELEDIT\r
32945 @@itemexpanding:\r
32946         XCHG     EAX, ECX\r
32947         MOV      ECX, [EBX].TControl.fOnTVExpanding.TMethod.Code\r
32948         JECXZ    @@2fin_false2\r
32949         PUSH     EAX // @Rslt\r
32950         CMP      [EDX].TNMTreeView.action, TVE_EXPAND\r
32951         PUSH     ECX\r
32952         SETZ     CL\r
32953         XCHG     ECX, [ESP]\r
32954         XCHG     ECX, EBX  //EBX=OnTVExpanding.Code ECX=Seneder\r
32955         XCHG     EDX, ECX  //ECX=Msg EDX=Sender\r
32956         MOV      ECX, [ECX].TNMTreeView.itemNew.hItem //ECX=Item\r
32957         MOV      EAX, [EDX].TControl.fOnTVExpanding.TMethod.Data //EAX=object\r
32958 @@111:\r
32959         CALL     EBX\r
32960         TEST     EAX, EAX\r
32961         SETZ     AL        // Rslt := not event result;\r
32962 @@ret_EAX:\r
32963         POP      EDX //EDX=@Rslt\r
32964         MOVZX    EAX, AL\r
32965         NEG      EAX\r
32966         MOV      [EDX], EAX\r
32967 @@ret_true:\r
32968         MOV      AL, 1\r
32969         POP      EBX\r
32970         RET\r
32971 @@chk_ENDLABELEDIT:\r
32972         {$IFDEF UNICODE_CTRLS}\r
32973         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_ENDLABELEDITW\r
32974         JZ       @@endlabeledit\r
32975         {$ENDIF UNICODE_CTRLS}\r
32976         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_ENDLABELEDIT\r
32977         JNZ      @@chk_SELCHANGED\r
32978 @@endlabeledit:\r
32979         MOV      [EBX].TControl.fEditing, 0\r
32980         XCHG     EAX, ECX\r
32981         MOV      ECX, [EBX].TControl.fOnTVEndEdit.TMethod.Code\r
32982         JECXZ    @@ret_1\r
32983         PUSH     EAX\r
32984         PUSH     EBX\r
32985         PUSH     0\r
32987         XCHG     EDX, EBX\r
32988         MOV      EAX, [EBX].TTVDispInfo.item.pszText\r
32989         PUSH     EDX\r
32990         PUSH     ECX\r
32991         XCHG     EAX, EDX\r
32992         {$IFDEF UNICODE_CTRLS}\r
32993         CMP      [EBX].TNMTreeView.hdr.code, TVN_ENDLABELEDITW\r
32994         JNZ      @@endlabeleditA\r
32995         CALL     TControl.TVGetItemTextW\r
32996         JMP      @@NewTxt_ready\r
32997 @@endlabeleditA:\r
32998         {$ENDIF UNICODE_CTRLS}\r
32999         TEST     EDX, EDX\r
33000         JNZ      @@prepare_NewTxt\r
33001         // NewTxt := [EDX].TControl.TVItemText[ hItem ]\r
33002         LEA      ECX, [ESP + 8]\r
33003         MOV      EDX, [EBX].TTVDispInfo.item.hItem\r
33004         CALL     TControl.TVGetItemText\r
33005         JMP      @@NewTxt_ready\r
33006 @@prepare_NewTxt:\r
33007         LEA      EAX, [ESP+8]\r
33008         CALL     System.@LStrFromPChar\r
33009 @@NewTxt_ready:\r
33010         POP      ECX\r
33011         POP      EDX\r
33012         POP      EAX\r
33013         PUSH     EAX\r
33014         PUSH     EAX\r
33015         MOV      EAX, [EDX].TControl.fOnTVEndEdit.TMethod.Data\r
33016         MOV      EBX, [EBX].TTVDispInfo.item.hItem\r
33017         XCHG     ECX, EBX\r
33018         CALL     EBX\r
33019         XCHG     EBX, EAX\r
33020         CALL     RemoveStr\r
33021         XCHG     EAX, EBX\r
33022         POP      EBX\r
33023         JMP      @@ret_EAX\r
33024 @@ret_1:\r
33025         INC      ECX\r
33026         MOV      [EAX], ECX\r
33027         JMP      @@ret_true\r
33029 @@chk_SELCHANGED:\r
33030         {$IFDEF UNICODE_CTRLS}\r
33031         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGEDW\r
33032         JZ       @@selchanged\r
33033         {$ENDIF UNICODE_CTRLS}\r
33034         CMP      word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGED\r
33035         JNZ      @@fin_false\r
33036 @@selchanged:\r
33037         XCHG     EAX, EBX\r
33038         CALL     TControl.DoSelChange\r
33040 @@fin_false:\r
33041         POP      EBX\r
33042 @@ret_false:\r
33043         XOR      EAX, EAX\r
33044 end;\r
33045 {$ELSE ASM_VERSION} //Pascal\r
33046 function WndProcTreeView( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
33047 var NM: PNMTreeView;\r
33048     DI: PTVDispInfo;\r
33049     P: TPoint;\r
33050     S: String;\r
33051 begin\r
33052   if Msg.message = WM_NOTIFY then\r
33053   begin\r
33054     NM := Pointer( Msg.lParam );\r
33055     case NM.hdr.code of\r
33056       NM_RCLICK:\r
33057         begin\r
33058           GetCursorPos( P );\r
33059           P := Self_.Screen2Client( P );\r
33060           PostMessage( Self_.fHandle, WM_RBUTTONUP, MK_RBUTTON or GetShiftState,\r
33061                        (P.x and $FFFF) or (P.y shl 16) );\r
33062         end;\r
33064       {$IFDEF UNICODE_CTRLS}\r
33065                TVN_BEGINDRAGW, TVN_BEGINRDRAGW,\r
33066       {$ENDIF} TVN_BEGINDRAG, TVN_BEGINRDRAG:\r
33067         if Assigned( Self_.fOnTVBeginDrag ) then\r
33068           Self_.fOnTVBeginDrag( Self_, NM.itemNew.hItem );\r
33069       TVN_BEGINLABELEDIT {$IFDEF UNICODE_CTRLS}, TVN_BEGINLABELEDITW{$ENDIF}:\r
33070       begin\r
33071         if Self_.fDragging then\r
33072         begin\r
33073           Rslt := 1; // do not allow edit while dragging\r
33074           Result := TRUE;\r
33075           Exit;\r
33076         end;\r
33077         DI := Pointer( NM );\r
33078         if Assigned( Self_.fOnTVBeginEdit ) then\r
33079         begin\r
33080           Rslt := Integer( not Self_.fOnTVBeginEdit( Self_, DI.item.hItem ) );\r
33081           if Rslt = 0 then\r
33082             Self_.fEditing := TRUE;\r
33083           Result := TRUE;\r
33084           Exit;\r
33085         end;\r
33086       end;\r
33087       TVN_ENDLABELEDIT {$IFDEF UNICODE_CTRLS}, TVN_ENDLABELEDITW {$ENDIF}:\r
33088       begin\r
33089         DI := Pointer( NM );\r
33090         if Assigned( Self_.fOnTVEndEdit ) then\r
33091         begin\r
33092           S := DI.item.pszText;\r
33093           if DI.item.pszText = nil then\r
33094           begin\r
33095             {$IFDEF UNICODE_CTRLS}\r
33096             if NM.hdr.code = TVN_ENDLABELEDITW then\r
33097               S := Self_.TVItemTextW[ DI.item.hItem ]\r
33098             else\r
33099             {$ENDIF UNICODE_CTRLS}\r
33100               S := Self_.TVItemText[ DI.item.hItem ];\r
33101           end;\r
33102           if Self_.fOnTVEndEdit( Self_, DI.item.hItem, S )\r
33103             then Rslt := 1\r
33104             else Rslt := 0;\r
33105         end\r
33106         else\r
33107           Rslt := 1;\r
33108         Self_.fEditing := FALSE;\r
33109         Result := True;\r
33110         Exit;\r
33111       end;\r
33112       TVN_ITEMEXPANDING {$IFDEF UNICODE_CTRLS}, TVN_ITEMEXPANDINGW {$ENDIF}:\r
33113       begin\r
33114         if Assigned( Self_.fOnTVExpanding ) then\r
33115         begin\r
33116           Rslt := Integer( not Self_.fOnTVExpanding( Self_, NM.itemNew.hItem,\r
33117                                NM.action = TVE_EXPAND ) );\r
33118           Result := TRUE;\r
33119           Exit;\r
33120         end;\r
33121       end;\r
33122       TVN_ITEMEXPANDED {$IFDEF UNICODE_CTRLS}, TVN_ITEMEXPANDEDW {$ENDIF}:\r
33123         if Assigned( Self_.fOnTVExpanded ) then\r
33124           Self_.fOnTVExpanded( Self_, NM.itemNew.hItem, NM.action=TVE_EXPAND );\r
33125       {TVN_DELETEITEM:\r
33126         if Assigned( Self_.fOnTVDelete ) then\r
33127           Self_.fOnTVDelete( Self_, NM.itemOld.hItem );}\r
33128       //------------------ by Sergey Shisminzev:\r
33129       TVN_SELCHANGING {$IFDEF UNICODE_CTRLS}, TVN_SELCHANGINGW {$ENDIF}:\r
33130         begin\r
33131           if Assigned( Self_.fOnTVSelChanging ) then\r
33132           begin\r
33133             Rslt := Integer( not Self_.fOnTVSelChanging( Self_, NM.itemOld.hItem, NM.itemNew.hItem ) );\r
33134             Result := TRUE;\r
33135             Exit;\r
33136           end;\r
33137         end;\r
33138       //----------------------------------------\r
33139       TVN_SELCHANGED {$IFDEF UNICODE_CTRLS}, TVN_SELCHANGEDW {$ENDIF}:\r
33140         Self_.DoSelChange;\r
33141     end;\r
33142   end;\r
33143   Result := False;\r
33144 end;\r
33145 {$ENDIF ASM_VERSION}\r
33146 //[END WndProcTreeView]\r
33148 //[function ProcTVDeleteItem]\r
33149 function ProcTVDeleteItem( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
33150 var NM: PNMTreeView;\r
33151 begin\r
33152   if Msg.message = WM_NOTIFY then\r
33153   begin\r
33154     NM := Pointer( Msg.lParam );\r
33155     case NM.hdr.code of\r
33156     TVN_DELETEITEM:\r
33157         if Assigned( Self_.fOnTVDelete ) then\r
33158           Self_.fOnTVDelete( Self_, NM.itemOld.hItem );\r
33159     end;\r
33160   end;\r
33161   Result := FALSE;\r
33162 end;\r
33164 //[procedure ClearTreeView]\r
33165 procedure ClearTreeView( TV: PControl );\r
33166 begin\r
33167   TV.TVDelete( TVI_ROOT );\r
33168 end;\r
33170 const\r
33171   TreeViewFlags: array[ TTreeViewOption ] of Integer = ( not TVS_HASLINES, TVS_LINESATROOT,\r
33172                  not TVS_HASBUTTONS, TVS_EDITLABELS, not TVS_SHOWSELALWAYS,\r
33173                   not TVS_DISABLEDRAGDROP, TVS_NOTOOLTIPS, TVS_CHECKBOXES,\r
33174                   TVS_TRACKSELECT, TVS_SINGLEEXPAND, TVS_INFOTIP,\r
33175                   TVS_FULLROWSELECT, TVS_NOSCROLL, TVS_NONEVENHEIGHT );\r
33177 {$IFDEF USE_CONSTRUCTORS}\r
33178 //[function NewTreeView]\r
33179 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;\r
33180                       ImgListNormal, ImgListState: PImageList ): PControl;\r
33181 begin\r
33182   new( Result, CreateTreeView( AParent, Options, ImgListNormal, ImgListState ) );\r
33183 end;\r
33184 {$ELSE not_USE_CONSTRUCTORS}\r
33186 //[FUNCTION NewTreeView]\r
33187 {$IFDEF ASM_VERSION}\r
33188 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;\r
33189                       ImgListNormal, ImgListState: PImageList ): PControl;\r
33190 asm     //cmd    //opd\r
33191         PUSH     EBX\r
33192         PUSH     ECX\r
33193         PUSH     EAX\r
33194         PUSH     EDX\r
33195         MOV      EAX, ESP\r
33196         MOV      EDX, offset[TreeViewFlags]\r
33197         XOR      ECX, ECX\r
33198         MOV      CL, 13\r
33199         CALL     MakeFlags\r
33200         POP      EDX\r
33201         OR       EAX, WS_VISIBLE or WS_CHILD or WS_TABSTOP\r
33202         XCHG     ECX, EAX\r
33203         POP      EAX\r
33204         MOV      EDX, offset[WC_TREEVIEW]\r
33205         PUSH     1\r
33206         PUSH     offset[TreeViewActions]\r
33207         CALL     _NewCommonControl\r
33208         MOV      EBX, EAX\r
33209         MOV      [EBX].TControl.fCreateWndExt, offset[ApplyImageLists2Control]\r
33210         MOV      [EBX].TControl.fColor, clWindow\r
33211         MOV      EDX, offset[WndProcTreeView]\r
33212         CALL     TControl.AttachProc\r
33213         ADD      [EBX].TControl.fBoundsRect.Right, 150-64\r
33214         ADD      [EBX].TControl.fBoundsRect.Bottom, 200-64\r
33215         MOV      EAX, EBX\r
33216         XOR      EDX, EDX\r
33217         MOV      DL, 32\r
33218         POP      ECX // ImageListNormal\r
33219         CALL     TControl.SetImgListIdx\r
33220         MOV      EAX, EBX\r
33221         XOR      EDX, EDX\r
33222         MOV      ECX, [ImgListState]\r
33223         CALL     TControl.SetImgListIdx\r
33224         MOV      byte ptr [EBX].TControl.fLookTabKeys, 1\r
33225         XCHG     EAX, EBX\r
33226         POP      EBX\r
33227 end;\r
33228 {$ELSE ASM_VERSION} //Pascal\r
33229 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;\r
33230                       ImgListNormal, ImgListState: PImageList ): PControl;\r
33231 var Flags: Integer;\r
33232 begin\r
33233   Flags := MakeFlags( @Options, TreeViewFlags );\r
33234   Result := _NewCommonControl( AParent, WC_TREEVIEW, Flags or WS_VISIBLE or\r
33235             WS_CHILD or WS_TABSTOP, True, @TreeViewActions );\r
33236   Result.fCreateWndExt := ApplyImageLists2Control;\r
33237   Result.fColor := clWindow;\r
33238   Result.AttachProc( WndProcTreeView );\r
33239   with Result.fBoundsRect do\r
33240   begin\r
33241     Right := Left + 150;\r
33242     Bottom := Top + 200;\r
33243   end;\r
33244   Result.ImageListNormal := ImgListNormal;\r
33245   Result.ImageListState := ImgListState;\r
33246   //Result.fLVTextBkColor := clWindow;\r
33247   Result.fLookTabKeys := [ tkTab ];\r
33248 end;\r
33249 {$ENDIF ASM_VERSION}\r
33250 //[END NewTreeView]\r
33252 {$ENDIF USE_CONSTRUCTORS}\r
33254 //===================== Tab Control ========================//\r
33256 //[FUNCTION WndProcTabControl]\r
33257 {$IFDEF ASM_VERSION}\r
33258 function WndProcTabControl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
33259 asm     //cmd    //opd\r
33260         PUSH     EBP\r
33261         PUSH     EBX\r
33262         PUSH     ESI\r
33263         PUSH     EDI\r
33264         MOV      EBX, EAX\r
33265         CMP      word ptr [EDX].TMsg.message, WM_NOTIFY\r
33266         JNZ      @@chk_WM_SIZE\r
33267         MOV      EDX, [EDX].TMsg.lParam\r
33268         CMP      word ptr [EDX].TNMHdr.code, TCN_SELCHANGE\r
33269         JNZ      @@ret_false\r
33271         CALL     TControl.GetCurIndex\r
33272         XCHG     EDI, EAX\r
33273         CMP      EDI, [EBX].TControl.fCurIndex\r
33274         PUSHFD   // WasActive = ZF\r
33276         MOV      [EBX].TControl.FCurIndex, EDI\r
33278         MOV      EAX, EBX\r
33279         CALL     TControl.GetItemsCount\r
33280         XCHG     ESI, EAX // ESI := Self_.Count\r
33282 @@loo:  DEC      ESI\r
33283         JS       @@e_loo\r
33284         MOV      EDX, ESI\r
33285         MOV      EAX, EBX\r
33286         CALL     TControl.GetPages\r
33288         CMP      ESI, EDI\r
33289         PUSH     EAX\r
33290         SETZ     DL\r
33291         CALL     TControl.SetVisible\r
33292         POP      EAX\r
33293         CMP      ESI, EDI\r
33294         JNE      @@nx_loo\r
33295         CALL     TControl.BringToFront\r
33296 @@nx_loo:\r
33297         JMP      @@loo\r
33298 @@e_loo:\r
33299         MOV      EAX, EBX\r
33300         CALL     TControl.ParentForm\r
33301         TEST     EAX, EAX\r
33302         JZ       @@1\r
33303         MOV      ECX, [EAX].TControl.fCurrentControl\r
33304         JECXZ    @@1\r
33305         MOV      EAX, EBX\r
33306         MOV      DL, 1\r
33307         CALL     TControl.SetFocused\r
33308         MOV      EAX, EBX\r
33309         CALL     TControl.Invalidate\r
33310         TEST     byte ptr [EBX].TControl.fStyle+1, $10\r
33311         JNZ      @@1\r
33312         MOV      EAX, EBX\r
33313         XOR      EDX, EDX\r
33314         MOV      DL, VK_TAB\r
33315         CALL     TControl.GotoControl\r
33316 @@1:\r
33317         POPFD\r
33318         JZ       @@ret_false\r
33320         MOV      ECX, [EBX].TControl.fOnSelChange.TMethod.Code\r
33321         JECXZ    @@ret_false\r
33322         MOV      EDX, EBX\r
33323         MOV      EAX, [EBX].TControl.fOnSelChange.TMethod.Data\r
33324         CALL     ECX\r
33325         JMP      @@ret_false\r
33326 @@chk_WM_SIZE:\r
33327         CMP      word ptr [EDX].TMsg.message, WM_SIZE\r
33328         JNE      @@ret_false\r
33329         ADD      ESP, -16\r
33330         PUSH     ESP\r
33331         PUSH     [EBX].TControl.fHandle\r
33332         CALL     Windows.GetClientRect\r
33333         PUSH     ESP\r
33334         PUSH     0\r
33335         PUSH     TCM_ADJUSTRECT\r
33336         PUSH     EBX\r
33337         CALL     TControl.Perform\r
33338         MOV      EAX, EBX\r
33339         CALL     TControl.GetItemsCount\r
33340         XCHG     ESI, EAX\r
33341 @@loo2:\r
33342         DEC      ESI\r
33343         JS       @@e_loo2\r
33344         MOV      EDX, ESI\r
33345         MOV      EAX, EBX\r
33346         CALL     TControl.GetPages\r
33347         MOV      EDX, ESP\r
33348         CALL     TControl.SetBoundsRect\r
33349         JMP      @@loo2\r
33350 @@e_loo2:\r
33351         ADD      ESP, 16\r
33352 @@ret_false:\r
33353         XOR      EAX, EAX\r
33354         POP      EDI\r
33355         POP      ESI\r
33356         POP      EBX\r
33357         POP      EBP\r
33358 end;\r
33359 {$ELSE ASM_VERSION} //Pascal\r
33360 function WndProcTabControl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
33361 var Hdr: PNMHdr;\r
33362     Page: PControl;\r
33363     I, A: Integer;\r
33364     R: TRect;\r
33365     Form: PControl;\r
33366     WasActive: Boolean;\r
33367 begin\r
33368   case Msg.message of\r
33369     WM_NOTIFY:\r
33370       begin\r
33371         Hdr := Pointer( Msg.lParam );\r
33372         case Hdr.code of\r
33373         TCN_SELCHANGE:\r
33374           begin\r
33375             A := Self_.Perform( TCM_GETCURSEL, 0, 0 );\r
33376             WasActive := Self_.fCurIndex = A;\r
33377             Self_.fCurIndex := A;\r
33378             for I := 0 to Self_.Count - 1 do\r
33379             begin\r
33380               Page := Self_.Pages[ I ];\r
33381               Page.Visible := A = I;\r
33382               if A = I then\r
33383                 Page.BringToFront;\r
33384             end;\r
33385             Form := Self_.ParentForm;\r
33386             if Form <> nil then\r
33387             begin\r
33388               if Form.fCurrentControl <> nil then\r
33389               begin\r
33390                 Self_.Focused := True;\r
33391                 Self_.Invalidate;\r
33392                 if not Longbool( Self_.fStyle and TCS_FOCUSONBUTTONDOWN ) then\r
33393                   Self_.GotoControl( VK_TAB );\r
33394               end;\r
33395             end;\r
33396             if not WasActive then\r
33397             if Assigned( Self_.fOnSelChange ) then\r
33398               Self_.fOnSelChange( Self_ );\r
33399             //Result := True;\r
33400           end;\r
33401         end;\r
33402       end;\r
33403     WM_SIZE:\r
33404       begin\r
33405         GetClientRect( Self_.fHandle, R );\r
33406         Self_.Perform( TCM_ADJUSTRECT, 0, Integer( @R ) );\r
33407         for I := 0 to Self_.Count - 1 do\r
33408         begin\r
33409           Page := Self_.Pages[ I ];\r
33410           Page.BoundsRect := R;\r
33411         end;\r
33412       end;\r
33413   end;\r
33414   Result := False;\r
33415 end;\r
33416 {$ENDIF ASM_VERSION}\r
33417 //[END WndProcTabControl]\r
33419 const TabControlFlags: array[ TTabControlOption ] of Integer = ( TCS_BUTTONS,\r
33420            TCS_FIXEDWIDTH, not TCS_FOCUSNEVER,\r
33421            TCS_FIXEDWIDTH or TCS_FORCEICONLEFT, TCS_FIXEDWIDTH or TCS_FORCELABELLEFT,\r
33422            TCS_MULTILINE, TCS_MULTISELECT, TCS_RIGHTJUSTIFY, TCS_SCROLLOPPOSITE,\r
33423            TCS_BOTTOM, TCS_VERTICAL, TCS_FLATBUTTONS, TCS_HOTTRACK, 0, TCS_OWNERDRAWFIXED );\r
33425 {$IFDEF USE_CONSTRUCTORS}\r
33426 //[function NewTabControl]\r
33427 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;\r
33428          ImgList: PImageList; ImgList1stIdx: Integer ): PControl;\r
33429 begin\r
33430   new( Result, CreateTabControl( AParent, Tabs, Options, ImgList, ImgList1stIdx ) );\r
33431 end;\r
33432 //[END NewTabControl]\r
33433 {$ELSE not_USE_CONSTRUCTORS}\r
33435 //[FUNCTION NewTabControl]\r
33436 {$IFDEF ASM_VERSION}\r
33437 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;\r
33438          ImgList: PImageList; ImgList1stIdx: Integer ): PControl;\r
33439 asm     //cmd    //opd\r
33440         PUSH     EBX\r
33441         PUSH     ESI\r
33442         PUSH     EDI\r
33443         XCHG     EBX, EAX\r
33444         PUSH     EDX\r
33445         PUSH     ECX\r
33446         LEA      EAX, [Options]\r
33447         MOV      EDX, offset[TabControlFlags]\r
33448         XOR      ECX, ECX\r
33449         MOV      CL, 13\r
33450         CALL     MakeFlags\r
33451         TEST     byte ptr [Options], 4\r
33452         JZ       @@0\r
33453         OR       EAX, WS_TABSTOP or TCS_FOCUSONBUTTONDOWN\r
33454 @@0:    OR       EAX, WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_VISIBLE\r
33455         XCHG     ECX, EAX\r
33456         XCHG     EAX, EBX\r
33457         MOV      EDX, offset[WC_TABCONTROL]\r
33458         PUSH     1\r
33459         PUSH     offset[TabControlActions]\r
33460         CALL     _NewCommonControl\r
33461         MOV      EBX, EAX\r
33462         TEST     [Options], 2 shl (tcoBorder - 1)\r
33463         JNZ      @@borderfixed\r
33464         AND      [EBX].TControl.fExStyle, not WS_EX_CLIENTEDGE\r
33465 @@borderfixed:\r
33466         MOV      EDX, offset[WndProcTabControl]\r
33467         CALL     TControl.AttachProc\r
33468         ADD      [EBX].TControl.fBoundsRect.Right, 100-64\r
33469         ADD      [EBX].TControl.fBoundsRect.Bottom, 100-64\r
33470         MOV      ECX, [ImgList]\r
33471         JECXZ    @@2\r
33472         XCHG     EAX, ECX\r
33473         CALL     TImageList.GetHandle\r
33474         PUSH     EAX\r
33475         PUSH     0\r
33476         PUSH     TCM_SETIMAGELIST\r
33477         PUSH     EBX\r
33478         CALL     TControl.Perform\r
33479 @@2:\r
33480         POP      EDI // EDI = High(Tabs)\r
33481         POP      ESI // ESI = Tabs\r
33482         XOR      EDX, EDX // EBP := 0 (=I)\r
33483         MOV      EAX, [ImgList1stIdx] //(=II)\r
33484 @@loop:\r
33485         CMP      EDX, EDI\r
33486         JG       @@e_loop\r
33487         PUSH     EAX\r
33488         PUSH     EDX\r
33489         PUSH     EAX\r
33490         LODSD\r
33491         XCHG     ECX, EAX\r
33492         MOV      EAX, EBX\r
33493         CALL     TControl.TC_Insert\r
33494         POP      EDX\r
33495         POP      EAX\r
33496         INC      EAX\r
33497         INC      EDX\r
33498         JMP      @@loop\r
33499 @@e_loop:\r
33500         MOV      byte ptr [EBX].TControl.fLookTabKeys, 1\r
33501         XCHG     EAX, EBX\r
33502         POP      EDI\r
33503         POP      ESI\r
33504         POP      EBX\r
33505 end;\r
33506 {$ELSE ASM_VERSION} //Pascal\r
33507 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;\r
33508          ImgList: PImageList; ImgList1stIdx: Integer ): PControl;\r
33509 var I, II : Integer;\r
33510     Flags: Integer;\r
33511 begin\r
33512   Flags := MakeFlags( @Options, TabControlFlags );\r
33513   if tcoFocusTabs in Options then\r
33514     Flags := Flags or (WS_TABSTOP or TCS_FOCUSONBUTTONDOWN);\r
33515   Result := _NewCommonControl( AParent, WC_TABCONTROL,\r
33516             Flags or (WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_VISIBLE), True,\r
33517             @TabControlActions );\r
33518   //***\r
33519   if not( tcoBorder in Options ) then\r
33520   begin\r
33521     Result.fExStyle := Result.fExStyle and not WS_EX_CLIENTEDGE;\r
33522   end;\r
33523   Result.AttachProc( WndProcTabControl );\r
33524   with Result.fBoundsRect do\r
33525   begin\r
33526     Right := Left + 100;\r
33527     Bottom := Top + 100;\r
33528   end;\r
33529   if ImgList <> nil then\r
33530     Result.Perform( TCM_SETIMAGELIST, 0, ImgList.Handle );\r
33531   II := ImgList1stIdx;\r
33532   for I := 0 to High( Tabs ) do\r
33533   begin\r
33534     Result.TC_Insert( I, Tabs[ I ], II );\r
33535     Inc( II );\r
33536   end;\r
33537   Result.fLookTabKeys := [ tkTab ];\r
33538 end;\r
33539 {$ENDIF ASM_VERSION}\r
33540 //[END NewTabControl]\r
33542 {$ENDIF USE_CONSTRUCTORS}\r
33544 //===================== Tool bar ========================//\r
33546 //[FUNCTION WndProcToolbarCtr]\r
33547 {$IFDEF ASM_noVERSION} //TTN_NEEDTEXTW\r
33548 function WndProcToolbarCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
33549 asm\r
33550         CMP      word ptr [EDX].TMsg.message, WM_WINDOWPOSCHANGED\r
33551         JNE      @@chk_CM_COMMAND\r
33552         MOV      dword ptr [ECX], 0 // Rslt := 0\r
33553         MOV      ECX, [EAX].TControl.fOnResize.TMethod.Code\r
33554         JECXZ    @@ret_true\r
33555         XCHG     EDX, EAX           // Sender := Self_\r
33556         MOV      EAX, [EDX].TControl.fOnResize.TMethod.Data\r
33557         CALL     ECX                // Self_.fOnResize\r
33558 @@ret_true:\r
33559         MOV      AL, 1              // Result := TRUE\r
33560         RET\r
33561 @@chk_CM_COMMAND:\r
33562         CMP      word ptr [EDX].TMsg.message, CM_COMMAND\r
33563         JNE      @@chk_WM_NOTIFY\r
33564         MOVZX    ECX, word ptr [EDX].TMsg.wParam\r
33565         MOV      [EAX].TControl.fCurItem, ECX\r
33566         PUSH     EAX\r
33567         PUSH     0\r
33568         PUSH     ECX\r
33569         PUSH     TB_COMMANDTOINDEX\r
33570         PUSH     EAX\r
33571         CALL     TControl.Perform\r
33572         PUSH     EAX\r
33574         PUSH     VK_RETURN\r
33575         CALL     GetKeyState\r
33576         TEST     EAX, EAX\r
33577         SETL     DL\r
33578         POP      ECX\r
33579         POP      EAX\r
33580         MOV      [EAX].TControl.fCurIndex, ECX\r
33581         MOV      [EAX].TControl.fRightClick, DL\r
33582 @@ret_false:\r
33583         XOR      EAX, EAX\r
33584         RET\r
33586 @@chk_WM_NOTIFY:\r
33587         CMP      word ptr [EDX].TMsg.message, WM_NOTIFY\r
33588         JNE      @@ret_false\r
33589         MOV      EDX, [EDX].TMsg.lParam\r
33590         MOV      ECX, [EDX].TTooltipText.hdr.code\r
33591         CMP      ECX, TTN_NEEDTEXT\r
33592         JNE      @@chk_NM_RCLICK\r
33593         PUSH     EAX\r
33594         PUSH     EDX\r
33595         MOV      EDX, [EDX].TTooltipText.hdr.idFrom\r
33596         MOV      ECX, [EAX].TControl.fTBttCmd\r
33597         OR       EAX, -1\r
33598         JECXZ    @@idxReady\r
33599         XCHG     EAX, ECX\r
33600         CALL     TList.IndexOf\r
33601 @@idxReady: // EAX = -1 or index of button tooltip\r
33602         TEST     EAX, EAX\r
33603         POP      EDX\r
33604         LEA      EDX, [EDX].TTooltipText.szText\r
33605         MOV      byte ptr [EDX], 0\r
33606         POP      ECX\r
33607         JL       @@ret_true\r
33608         MOV      ECX, [ECX].TControl.fTBttTxt\r
33609         MOV      ECX, [ECX].TStrList.fList\r
33610         MOV      ECX, [ECX].TList.fItems\r
33611         MOV      EAX, [ECX+EAX*4]\r
33612         XCHG     EAX, EDX\r
33613         XOR      ECX, ECX\r
33614         MOV      CL, 79\r
33615         CALL     StrLCopy\r
33616         JMP      @@ret_true\r
33617 @@chk_NM_RCLICK:\r
33618         CMP      ECX, NM_RCLICK\r
33619         JNE      @@chk_NM_CLICK\r
33620         OR       [EAX].TControl.fRightClick, 1\r
33621         MOV      ECX, [EDX].TNMMouse.dwItemSpec\r
33622         MOV      [EAX].TControl.fCurItem, -1\r
33623         PUSH     EAX\r
33624         PUSH     0\r
33625         PUSH     ECX\r
33626         PUSH     TB_COMMANDTOINDEX\r
33627         PUSH     EAX\r
33628         CALL     TControl.Perform\r
33629         POP      EDX\r
33630         MOV      [EDX].TControl.fCurIndex, EAX\r
33631         XOR      EAX, EAX\r
33632         RET\r
33633 @@chk_NM_CLICK:\r
33634         CMP      ECX, NM_CLICK\r
33635         JNE      @@chk_TBN_DROPDOWN\r
33636         MOV      [EAX].TControl.fRightClick, 0\r
33637         OR       [EAX].TControl.fCurItem, -1\r
33638         OR       [EAX].TControl.fCurIndex, -1\r
33639         CMP      [EDX].TTBNotify.iItem, -1\r
33640         SETNZ    AL\r
33641         RET\r
33642 @@chk_TBN_DROPDOWN:\r
33643         CMP      ECX, TBN_DROPDOWN\r
33644         JNE      @@ret_false\r
33645         MOV      EDX, [EDX].TTBNotify.iItem\r
33646         MOV      [EAX].TControl.fCurItem, EDX\r
33647         PUSH     EAX\r
33648         CALL     TControl.TBItem2Index\r
33649         POP      EDX\r
33650         MOV      [EDX].TControl.fCurIndex, EAX\r
33651         MOV      ECX, [EDX].TControl.fOnDropDown.TMethod.Code\r
33652         JECXZ    @@ret_z\r
33653         MOV      EAX, [EDX].TControl.fOnDropDown.TMethod.Data\r
33654         CALL     ECX\r
33655 @@ret_z:\r
33656         XOR      EAX, EAX\r
33657 end;\r
33658 {$ELSE ASM_VERSION} //Pascal\r
33659 function WndProcToolbarCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
33660 var lpttt: PTooltipText;\r
33661     idBtn, Idx: Integer;\r
33662 var Notify: PTBNotify;\r
33663     Mouse: PNMMouse;\r
33664 {$IFNDEF _FPC}\r
33665 {$IFNDEF _D2}\r
33666 var Wstr: WideString;\r
33667 {$ENDIF _D2}\r
33668 {$ENDIF _FPC}\r
33669 begin\r
33670   Result := False;\r
33671   if Msg.message = WM_WINDOWPOSCHANGED then\r
33672   begin\r
33673     if Assigned( Self_.fOnResize ) then\r
33674       Self_.fOnResize( Self_ );\r
33675     Result := TRUE;\r
33676     Rslt := 0;\r
33677   end\r
33678   else if Msg.message = CM_COMMAND then\r
33679   begin\r
33680     Self_.fCurItem := Loword( Msg.wParam );\r
33681     Self_.fCurIndex := Self_.Perform( TB_COMMANDTOINDEX, Loword( Msg.wParam ), 0 );\r
33682     Self_.fRightClick := GetKeyState( VK_RBUTTON ) < 0;\r
33683   end\r
33684   else if Msg.message = WM_NOTIFY then\r
33685   begin\r
33686     lpttt := Pointer( Msg.lParam );\r
33687     Notify := Pointer( Msg.lParam );\r
33688     case lpttt.hdr.code of\r
33689     TTN_NEEDTEXT:\r
33690         begin\r
33691           Result := True;\r
33692           idBtn := lpttt.hdr.idFrom;\r
33693           Idx := -1;\r
33694           if Self_.fTBttCmd <> nil then\r
33695             Idx := Self_.fTBttCmd.IndexOf( Pointer( idBtn ) );\r
33696           lpttt.szText[ 0 ] := #0;\r
33697           if Idx >= 0 then\r
33698             StrLCopy( lpttt.szText, Self_.fTBttTxt.fList.fItems[ Idx ], 79 );\r
33699           Exit;\r
33700         end;\r
33701       // for Windows XP\r
33702       {$IFNDEF _FPC}\r
33703       {$IFNDEF _D2}\r
33704       TTN_NEEDTEXTW:\r
33705           begin\r
33706             Result := True;\r
33707             idBtn := lpttt.hdr.idFrom;\r
33708             Idx := -1;\r
33709             if Self_.fTBttCmd <> nil then\r
33710               Idx := Self_.fTBttCmd.IndexOf( Pointer( idBtn ) );\r
33711             FillChar( lpttt.szText[ 0 ], 160, 0 );\r
33712             if Idx >= 0 then\r
33713             begin\r
33714               WStr := Self_.fTBttTxt.Items[ Idx ];\r
33715               if WStr <> '' then\r
33716                 Move( Wstr[ 1 ], lpttt.szText, Min( 158, (Length( WStr ) + 1) * 2 ) );\r
33717             end;\r
33718             Exit;\r
33719           end;\r
33720     {$ENDIF _D2}\r
33721     {$ENDIF _FPC}\r
33722     NM_RCLICK:\r
33723         begin\r
33724           Mouse := Pointer( Msg.lParam );\r
33725           Self_.fCurItem := Mouse.dwItemSpec;\r
33726           Self_.fCurIndex := Self_.Perform( TB_COMMANDTOINDEX, Mouse.dwItemSpec, 0 );\r
33727           Self_.fRightClick := GetKeyState( VK_RBUTTON ) < 0;\r
33728           Self_.fRightClick := True;\r
33729         end;\r
33730     NM_CLICK:\r
33731         begin\r
33732           Self_.fCurItem := -1; // return CurItem = -1\r
33733           Self_.fCurIndex := -1;\r
33734           Self_.fRightClick := False;\r
33735           Result := Notify.iItem <> -1;\r
33736                    // do not handle - if it will be handled in WM_COMMAND\r
33737           Exit;\r
33738         end;\r
33739     TBN_DROPDOWN:\r
33740         begin\r
33741           Self_.fCurItem := Notify.iItem;\r
33742           Self_.fCurIndex := Self_.TBItem2Index( Self_.fCurItem );\r
33743           if assigned( Self_.fOnDropDown ) then\r
33744             Self_.fOnDropDown( Self_ );\r
33745         end;\r
33746     end;\r
33747   end;\r
33748 end;\r
33749 {$ENDIF ASM_VERSION}\r
33750 //[END WndProcToolbarCtr]\r
33752 const ToolbarAligns: array[ TControlAlign ] of DWORD =\r
33753       ( CCS_NOPARENTALIGN {or CCS_NOMOVEY} {or CCS_NORESIZE} or CCS_NODIVIDER, CCS_TOP or CCS_VERT, CCS_TOP, CCS_BOTTOM or CCS_VERT, CCS_BOTTOM,\r
33754         CCS_TOP );\r
33755       ToolbarOptions: array[ TToolbarOption ] of Integer = ( TBSTYLE_LIST, not TBSTYLE_LIST,\r
33756                      TBSTYLE_FLAT, TBSTYLE_TRANSPARENT, TBSTYLE_WRAPABLE, CCS_NODIVIDER, 0 );\r
33758 {$IFDEF USE_CONSTRUCTORS}\r
33759 //[function NewToolbar]\r
33760 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;\r
33761                      Bitmap: HBitmap; Buttons: array of PChar;\r
33762                      BtnImgIdxArray: array of Integer ) : PControl;\r
33763 begin\r
33764   new( Result, CreateToolbar( AParent, Align, Options, Bitmap, Buttons, BtnImgIdxArray ) );\r
33765 end;\r
33766 //[END NewToolbar]\r
33767 {$ELSE not_USE_CONSTRUCTORS}\r
33769 //[FUNCTION NewToolbar]\r
33770 {$IFDEF ASM_!VERSION}\r
33771 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;\r
33772                      Bitmap: HBitmap; Buttons: array of PChar;\r
33773                      BtnImgIdxArray: array of Integer ) : PControl;\r
33774 const szTBButton = Sizeof( TTBButton );\r
33775       Option3DBorder = 1 shl Ord( tbo3DBorder );\r
33776 asm\r
33777         MOVZX    EDX, DL\r
33778         PUSH     EDX // Align\r
33779         PUSH     EAX // AParent\r
33781         XOR      EAX, EAX\r
33782         TEST     CL, Option3DBorder\r
33783         SETNZ    AL\r
33784         PUSH     EAX\r
33786         PUSH     ECX // Options\r
33788         MOV      AL, ICC_BAR_CLASSES\r
33789         CALL     DoInitCommonControls\r
33791         MOV      EAX, ESP\r
33792         MOV      EDX, offset[ToolbarOptions]\r
33793         XOR      ECX, ECX\r
33794         MOV      CL, 5\r
33795         CALL     MakeFlags\r
33796         POP      EDX\r
33798         PUSH     0\r
33799         XCHG     ECX, EAX // ECX = MakeFlags(...)\r
33800         MOV      EAX, [ESP+8] // EAX = AParent\r
33801         MOV      EDX, [ESP+12] // EDX = Align\r
33802         OR       ECX, [EDX*4+offset ToolbarAligns]\r
33803         OR       ECX, WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS\r
33804         MOV      EDX, offset[ TOOLBARCLASSNAME ]\r
33805         CALL     _NewCommonControl\r
33806         MOV      [EAX].TControl.fCommandActions.aClear, offset[ClearToolbar]\r
33807         MOV      [EAX].TControl.fCommandActions.aGetCount, TB_BUTTONCOUNT\r
33808         INC      [EAX].TControl.fIsButton\r
33809         POP      EDX // pop AParent\r
33810         POP      EDX // EDX = Align\r
33811         PUSH     EDX\r
33812         TEST     EDX, EDX\r
33813         JE       @@zero_bounds\r
33814         ADD      [EAX].TControl.fBoundsRect.Bottom, 26-64\r
33815         ADD      [EAX].TControl.fBoundsRect.Right, 1000-64\r
33816         JMP      @@bounds_ready\r
33817 @@zero_bounds:\r
33818         MOV      [EAX].TControl.fBoundsRect.Left, EDX\r
33819         MOV      [EAX].TControl.fBoundsRect.Top, EDX\r
33820         MOV      [EAX].TControl.fBoundsRect.Right, EDX\r
33821         MOV      [EAX].TControl.fBoundsRect.Bottom, EDX\r
33822 @@bounds_ready:\r
33823         PUSH     EBX\r
33824         PUSH     ESI\r
33825         XCHG     EBX, EAX\r
33826         MOV      ESI, offset[TControl.Perform]\r
33827         PUSH     0\r
33828         PUSH     0\r
33829         PUSH     TB_GETEXTENDEDSTYLE\r
33830         PUSH     EBX\r
33831         CALL     ESI\r
33832         OR       EAX, TBSTYLE_EX_DRAWDDARROWS\r
33833         PUSH     EAX\r
33834         PUSH     0\r
33835         PUSH     TB_SETEXTENDEDSTYLE\r
33836         PUSH     EBX\r
33837         CALL     ESI\r
33838         MOV      EDX, offset[WndProcToolbarCtrl]\r
33839         MOV      EAX, EBX\r
33840         CALL     TControl.AttachProc\r
33841         MOV      EDX, offset[WndProcDoEraseBkgnd]\r
33842         MOV      EAX, EBX\r
33843         CALL     TControl.AttachProc\r
33844         PUSH     0\r
33845         PUSH     szTBButton\r
33846         PUSH     TB_BUTTONSTRUCTSIZE\r
33847         PUSH     EBX\r
33848         CALL     ESI\r
33849         PUSH     0\r
33850         PUSH     [EBX].TControl.fMargin\r
33851         PUSH     TB_SETINDENT\r
33852         PUSH     EBX\r
33853         CALL     ESI\r
33854         MOV      EAX, [ESP+8] // Align\r
33855         {$IFDEF PARANOIA}\r
33856         DB $2C,  1\r
33857         {$ELSE}\r
33858         SUB AL, 1\r
33859         {$ENDIF}\r
33860         JL       @@bounds_correct\r
33861         JE       @@corr_right\r
33862         {$IFDEF PARANOIA}\r
33863         DB $2C,  2\r
33864         {$ELSE}\r
33865         SUB AL, 2\r
33866         {$ENDIF}\r
33867         JNE      @@corr_bottom\r
33868 @@corr_right:\r
33869         MOV      EDX, [EBX].TControl.fBoundsRect.Left\r
33870         ADD      EDX, 24\r
33871         MOV      [EBX].TControl.fBoundsRect.Right, EDX\r
33872         JMP      @@bounds_correct\r
33873 @@corr_bottom:\r
33874         MOV      EDX, [EBX].TControl.fBoundsRect.Top\r
33875         ADD      EDX, 22\r
33876         MOV      [EBX].TControl.fBoundsrect.Bottom, EDX\r
33877 @@bounds_correct:\r
33878         MOV      EDX, [Bitmap]\r
33879         TEST     EDX, EDX\r
33880         JZ       @@bitmap_added\r
33881         MOV      EAX, EBX\r
33882         CALL     TControl.TBAddBitmap\r
33883 @@bitmap_added:\r
33885         PUSH     dword ptr [BtnImgIdxArray]\r
33886         PUSH     dword ptr [BtnImgIdxArray-4]\r
33887         MOV      ECX, [Buttons-4]\r
33888         MOV      EDX, [Buttons]\r
33889         MOV      EAX, EBX\r
33890         CALL     TControl.TBAddButtons\r
33892         PUSH     0\r
33893         PUSH     0\r
33894         PUSH     WM_SIZE\r
33895         PUSH     EBX\r
33896         CALL     ESI\r
33898         XCHG     EAX, EBX\r
33899         POP      ESI\r
33900         POP      EBX\r
33901         ///POP      EDX  ///!!! next command is MOV ESP,EBP\r
33902 end;\r
33903 {$ELSE ASM_VERSION} //Pascal\r
33904 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;\r
33905                      Bitmap: HBitmap; Buttons: array of PChar;\r
33906                      BtnImgIdxArray: array of Integer ) : PControl;\r
33907 var Flags: DWORD;\r
33908 begin\r
33909   if not( tboTextBottom in Options ) then\r
33910     Options := Options + [ tboTextRight ];\r
33911   if tboTextRight in Options then\r
33912     Options := Options - [ tboTextBottom ];\r
33913   Flags := MakeFlags( @Options, ToolbarOptions );\r
33914   DoInitCommonControls( ICC_BAR_CLASSES );\r
33915   Result := _NewCommonControl( AParent, TOOLBARCLASSNAME,\r
33916          (ToolbarAligns[ Align ] or WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS or Flags),\r
33917          //(not (Align in [caNone])) and not (tboNoDivider in Options),  nil );\r
33918          tbo3DBorder in Options,  nil );\r
33919   Result.fCommandActions.aClear := ClearToolbar;\r
33920   Result.fCommandActions.aGetCount := TB_BUTTONCOUNT;\r
33921   Result.fIsButton := TRUE;\r
33922   with Result.fBoundsRect do\r
33923   begin\r
33924     if Align in [ caNone ] then\r
33925     begin\r
33926       Bottom := Top + 26;\r
33927       Right := Left + 1000;\r
33928     end\r
33929        else\r
33930     begin\r
33931       Left := 0; Right := 0;\r
33932       Top := 0; Bottom := 0;\r
33933     end;\r
33934   end;\r
33935   Result.AttachProc( WndProcToolbarCtrl );\r
33936   Result.AttachProc( WndProcDoEraseBkgnd );\r
33937   Result.Perform(TB_SETEXTENDEDSTYLE, 0, Result.Perform(TB_GETEXTENDEDSTYLE, 0, 0) or\r
33938       TBSTYLE_EX_DRAWDDARROWS);\r
33940   Result.Perform( TB_BUTTONSTRUCTSIZE, Sizeof( TTBButton ), 0 );\r
33941   Result.Perform( TB_SETINDENT, Result.fMargin, 0 );\r
33942   with Result.fBoundsRect do\r
33943   begin\r
33944     if Align in [ caLeft, caRight ] then\r
33945       Right := Left + 24\r
33946     else if not (Align in [caNone]) then\r
33947       Bottom := Top + 22;\r
33948   end;\r
33949   if Bitmap <> 0 then\r
33950     Result.TBAddBitmap( Bitmap );\r
33951   Result.TBAddButtons( Buttons, BtnImgIdxArray );\r
33952   Result.Perform( WM_SIZE, 0, 0 );\r
33953 end;\r
33954 {$ENDIF ASM_VERSION}\r
33955 //[END NewToolbar]\r
33957 {$ENDIF USE_CONSTRUCTORS}\r
33959 //================== DateTimePicker =====================//\r
33961 function WndProcDateTimePickerNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
33962 var NMhdr: PNMHdr;\r
33963     D: TDateTime;\r
33964     AllowChg: Boolean;\r
33965     NMDTString: PNMDateTimeString;\r
33966 begin\r
33967   Result := False;\r
33968   if Msg.message = WM_NOTIFY then\r
33969   begin\r
33970     NMHdr := Pointer( Msg.lParam );\r
33971     CASE NMHdr.code OF\r
33972     DTN_DROPDOWN: if Assigned( Self_.fOnDropDown ) then\r
33973                      Self_.fOnDropDown( Self_ );\r
33974     DTN_CLOSEUP: if Assigned( Self_.fOnCloseUp ) then\r
33975                    Self_.fOnCloseUp( Self_ );\r
33976     DTN_DATETIMECHANGE:\r
33977       if Assigned( Self_.fOnChange ) then\r
33978         Self_.fOnChange( Self_ );\r
33979     {DTN_FORMAT:\r
33980       Rslt := 0;}\r
33981     DTN_USERSTRING:\r
33982       if Assigned( Self_.fOnDTPUserString ) then\r
33983       begin\r
33984         NMDTString := Pointer( NMHdr );\r
33985         D := 0.0;\r
33986         AllowChg := TRUE;\r
33987         Self_.fOnDTPUserString( Self_, NMDTString.pszUserString, D, AllowChg );\r
33988         NMDTString.dwFlags := Integer( not AllowChg );\r
33989       end;\r
33990     END;\r
33991   end;\r
33992 end;\r
33994 const\r
33995   //( dtpoTime, dtpoDateLong, dtpoUpDown, dtpoRightAlign,\r
33996   //  dtpoShowNone, dtpoParseInput )\r
33998   DateTimePickerOptions: array[ TDateTimePickerOption ] of Integer = (\r
33999     DTS_TIMEFORMAT, DTS_LONGDATEFORMAT, DTS_UPDOWN, DTS_RIGHTALIGN,\r
34000     DTS_SHOWNONE, DTS_APPCANPARSE );\r
34002 function NewDateTimePicker( AParent: PControl; Options: TDateTimePickerOptions )\r
34003          : PControl;\r
34004 var Flags: DWORD;\r
34005 const\r
34006   CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS or\r
34007            CS_VREDRAW or CS_HREDRAW;\r
34008 begin\r
34009   DoInitCommonControls( ICC_DATE_CLASSES );\r
34010   Flags := MakeFlags( @Options, DateTimePickerOptions );\r
34011   Result := _NewCommonControl( AParent, DATETIMEPICK_CLASS,\r
34012          (WS_CHILD or WS_VISIBLE or WS_TABSTOP or Flags), TRUE,  nil );\r
34013   //Result.ClsStyle := Result.ClsStyle and not CS_OFF;\r
34014   Result.SetSize( 110, 24 );\r
34015   Result.AttachProc( WndProcDateTimePickerNotify );\r
34016 end;\r
34018 procedure TControl.SetDateTime(Value: TDateTime);\r
34019 var ST: TSystemTime;\r
34020 begin\r
34021   DateTime2SystemTime( Value, ST );\r
34022   Perform( DTM_SETSYSTEMTIME, Integer( IsNAN( Value ) ) , Integer( @ ST ) );\r
34023 end;\r
34025 function TControl.GetDateTime: TDateTime;\r
34026 var ST: TSystemTime;\r
34027 begin\r
34028   if Perform( DTM_GETSYSTEMTIME, 0, Integer( @ ST ) ) = GDT_VALID then\r
34029     SystemTime2DateTime( ST, Result )\r
34030   else\r
34031     Result := NAN;\r
34032 end;\r
34034 function TControl.GetDate: TDateTime;\r
34035 begin\r
34036   Result := DateTime;\r
34037   if not IsNAN( Result ) then\r
34038     Result := Trunc( DateTime );\r
34039 end;\r
34041 function TControl.GetTime: TDateTime;\r
34042 begin\r
34043   Result := DateTime;\r
34044   if not IsNAN( Result ) then\r
34045     Result := Frac( Result );\r
34046 end;\r
34048 procedure TControl.SetDate(const Value: TDateTime);\r
34049 begin\r
34050   if IsNAN( Value ) then\r
34051     DateTime := Value\r
34052   else\r
34053   if not IsNAN( DateTime ) then\r
34054     DateTime := Trunc( Value ) + Frac( DateTime )\r
34055   else\r
34056     DateTime := Trunc( Value );\r
34057 end;\r
34059 procedure TControl.SetTime(const Value: TDateTime);\r
34060 begin\r
34061   if IsNAN( Value ) then\r
34062     DateTime := Value\r
34063   else\r
34064   if not IsNAN( DateTime ) then\r
34065     DateTime := Trunc( DateTime ) + Frac( Value )\r
34066   else\r
34067     DateTime := 1.0 + Frac( Value );\r
34068 end;\r
34070 function TControl.GetDateTimeRange: TDateTimeRange;\r
34071 var ST_R: array[ 0..1 ] of TSystemTime;\r
34072 begin\r
34073   Perform( DTM_GETRANGE, 0, Integer( @ ST_R[ 0 ] ) );\r
34074   SystemTime2DateTime( ST_R[ 0 ], Result[ 0 ] );\r
34075   SystemTime2DateTime( ST_R[ 1 ], Result[ 1 ] );\r
34076 end;\r
34078 procedure TControl.SetDateTimeRange(Value: TDateTimeRange);\r
34079 var ST_R: array[ 0..1 ] of TSystemTime;\r
34080 begin\r
34081   DateTime2SystemTime( Value[ 0 ], ST_R[ 0 ] );\r
34082   DateTime2SystemTime( Value[ 1 ], ST_R[ 1 ] );\r
34083   Perform( DTM_SETRANGE,\r
34084            Integer( IsNAN( Value[ 0 ] ) ) or\r
34085            (Integer( IsNAN( Value[ 1 ] ) ) shl 1),\r
34086            Integer( @ ST_R[ 0 ] ) );\r
34087 end;\r
34089 function TControl.GetDateTimePickerColor( Index: TDateTimePickerColor): TColor;\r
34090 begin\r
34091   Result := Perform( DTM_GETMCCOLOR, Integer( Index ), 0 );\r
34092 end;\r
34094 procedure TControl.SetDateTimePickerColor(\r
34095   Index: TDateTimePickerColor; Value: TColor);\r
34096 begin\r
34097   Perform( DTM_SETMCCOLOR, Integer( Index ), Color2RGB( Value ) );\r
34098 end;\r
34100 procedure TControl.SetDateTimeFormat(const Value: String);\r
34101 begin\r
34102   Perform( DTM_SETFORMAT, 0, Integer( PChar( Value ) ) );\r
34103 end;\r
34105 function MakeDateTimeRange( D1, D2: TDateTime ): TDateTimeRange;\r
34106 begin\r
34107   Result[ 0 ] := D1;\r
34108   Result[ 1 ] := D2;\r
34109 end;\r
34112 //===================== RichEdit ========================//\r
34114 type PENLink = ^TENLink;\r
34115      TENLink = packed record\r
34116        hdr: TNMHDR;\r
34117        msg: DWORD;\r
34118        wParam: Integer;\r
34119        lParam: Integer;\r
34120        chrg: TCHARRANGE;\r
34121      end;\r
34122   TEXTRANGEA = packed record\r
34123     chrg: TCharRange;\r
34124     lpstrText: PAnsiChar;\r
34125   end;\r
34127 //[FUNCTION WndProc_RE_LinkNotify]\r
34128 {$IFDEF ASM_VERSION}\r
34129 function WndProc_RE_LinkNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
34130 asm\r
34131         CMP      word ptr [EDX].TMsg.message, WM_NOTIFY\r
34132         JNE      @@ret_false\r
34133         MOV      EDX, [EDX].TMsg.lParam\r
34134         CMP      [EDX].TNMHdr.code, EN_LINK\r
34135         JNE      @@ret_false\r
34136         PUSH     EBX\r
34137         PUSH     EDX\r
34138         XCHG     EBX, EAX\r
34139         XOR      EAX, EAX\r
34140         MOV      [ECX], EAX\r
34141         ADD      ESP, -1020\r
34142         PUSH     EAX\r
34143         PUSH     ESP\r
34144         PUSH     [EDX].TENLink.chrg.cpMax\r
34145         PUSH     [EDX].TENLink.chrg.cpMin\r
34146         PUSH     ESP\r
34147         PUSH     0\r
34148         PUSH     EM_GETTEXTRANGE\r
34149         PUSH     EBX\r
34150         CALL     TControl.Perform\r
34151         ADD      ESP, 12\r
34152         MOV      EDX, ESP\r
34153         LEA      EAX, [EBX].TControl.fREUrl\r
34154         CALL     System.@LStrFromPChar\r
34155         ADD      ESP, 1024\r
34156         POP      EDX\r
34157         MOV      ECX, [EDX].TENLink.msg\r
34158         LEA      EAX, [EBX].TControl.fOnREOverURL\r
34159         CMP      ECX, WM_MOUSEMOVE\r
34160         JE       @@Url_event\r
34161         LEA      EAX, [EBX].TControl.fOnREUrlClick\r
34162         CMP      ECX, WM_LBUTTONDOWN\r
34163         JE       @@Url_Event\r
34164         CMP      ECX, WM_RBUTTONDOWN\r
34165         JNE      @@after_Url_event\r
34166 @@Url_event:\r
34167         MOV      ECX, [EAX].TMethod.Code\r
34168         JECXZ    @@after_Url_event\r
34169         MOV      EDX, EBX\r
34170         MOV      EAX, [EAX].TMethod.Data\r
34171         CALL     ECX\r
34172 @@after_Url_event:\r
34173         POP      EBX\r
34174         MOV      AL, 1\r
34175         RET\r
34176 @@ret_false:\r
34177         XOR      EAX, EAX\r
34178 end;\r
34179 {$ELSE ASM_VERSION} //Pascal\r
34180 function WndProc_RE_LinkNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
34181 var Link: PENLink;\r
34182     Range: TextRangeA;\r
34183     Buffer: array[ 0..1023 ] of Char;\r
34184 begin\r
34185   Result := False;\r
34186   if (Msg.message = WM_NOTIFY) and (PNMHdr( Msg.lParam ).code = EN_LINK) then\r
34187   begin\r
34188     Link := Pointer( Msg.lParam );\r
34189     Range.chrg := Link.chrg;\r
34190     Range.lpstrText := @Buffer[ 0 ]; //Pchar( @Buffer[ 0 ] );\r
34191     Buffer[ 0 ] := #0;\r
34192     Self_.Perform( EM_GETTEXTRANGE, 0, Integer( @Range ) );\r
34193     Self_.fREUrl := Buffer;\r
34194     case Link.msg of\r
34195     WM_MOUSEMOVE:\r
34196       if assigned( Self_.fOnREOverURL ) then\r
34197         Self_.fOnREOverURL( Self_ );\r
34198     WM_LBUTTONDOWN, WM_RBUTTONDOWN:\r
34199       if assigned( Self_.fOnREUrlClick ) then\r
34200         Self_.fOnREUrlClick( Self_ );\r
34201     end;\r
34202     Rslt := 0;\r
34203     Result := TRUE;\r
34204   end;\r
34205 end;\r
34206 {$ENDIF ASM_VERSION}\r
34207 //[END WndProc_RE_LinkNotify]\r
34209 var Global_DisableParentCursor: Boolean;\r
34211 //[FUNCTION WndProcRichEditNotify]\r
34212 {$IFDEF ASM_noVERSION}\r
34213 function WndProcRichEditNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
34214 const int_IDC_ARROW = integer( IDC_ARROW );\r
34215 asm\r
34216         CMP      word ptr [EDX].TMsg.message, WM_NOTIFY\r
34217         JNE      @@ret_false                           {YS}\r
34218 //        JNE      @@chk_WM_SETCURSOR                  {YS}\r
34219         MOV      EDX, [EDX].TMsg.lParam\r
34220         CMP      [EDX].TNMHdr.code, EN_SELCHANGE\r
34221         JNE      @@ret_false\r
34222         //PUSH     EAX\r
34223         CALL     TControl.DoSelChange\r
34224         //POP      EAX\r
34225         {CMP      [EAX].TControl.fTransparent, 0\r
34226         JZ       @@ret_false\r
34227         CALL     TControl.Invalidate}\r
34228 @@ret_false:\r
34229         XOR      EAX, EAX\r
34230         RET\r
34231 { //YS\r
34232 @@chk_WM_SETCURSOR:\r
34233         CMP      word ptr [EDX].TMsg.message, WM_SETCURSOR\r
34234         JNE      @@ret_false\r
34235         PUSH     EBX\r
34236         MOV      EBX, EAX\r
34237         PUSH     ECX\r
34238         PUSH     EDX\r
34239         INC      [Global_DisableParentCursor]\r
34240         CALL     TControl.CallDefWndProc\r
34241         DEC      [Global_DisableParentCursor]\r
34242         POP      EDX\r
34243         MOVZX    EDX, word ptr [EDX].TMsg.lParam\r
34244         POP      ECX\r
34245         MOV      [ECX], EAX\r
34246         TEST     EAX, EAX\r
34247         MOV      EAX, [EBX].TControl.fCursor\r
34248         POP      EBX\r
34249         JNZ      @@ret_true\r
34250         INC      dword ptr [ECX]\r
34251         CMP      EDX, HTCLIENT\r
34252         JE       @@set_cursor\r
34253         CMP      EDX, HTVSCROLL\r
34254         JE       @@set_arrow_cursor\r
34255         CMP      EDX, HTHSCROLL\r
34256         JNE      @@ret_false\r
34257 @@set_arrow_cursor:\r
34258         PUSH     int_IDC_ARROW\r
34259         PUSH     0\r
34260         CALL     LoadCursor\r
34261 @@set_cursor:\r
34262         PUSH     EAX\r
34263         CALL     Windows.SetCursor\r
34264 @@ret_true:\r
34265         MOV      AL, 1\r
34267 end;\r
34268 {$ELSE ASM_VERSION} //Pascal\r
34269 function WndProcRichEditNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
34270 var NMhdr: PNMHdr;\r
34271 //    TestCode: Integer;\r
34272     {FR: TFormatRange;\r
34273     I: Integer;\r
34274     R: TRect;\r
34275     LogX, LogY: Integer;}\r
34276 begin\r
34277   Result := False;\r
34278   if Msg.message = WM_NOTIFY then\r
34279   begin\r
34280     NMHdr := Pointer( Msg.lParam );\r
34281     case NMHdr.code of\r
34282     EN_SELCHANGE:\r
34283       begin\r
34284         Self_.DoSelChange;\r
34285         if Self_.fTransparent then\r
34286           Self_.Invalidate;\r
34287       end;\r
34288     end;\r
34289   end\r
34290 { // YS\r
34291      else\r
34292   if Msg.message = WM_SETCURSOR then\r
34293   begin\r
34294     Result := True;\r
34295     TestCode := LoWord( Msg.lParam );\r
34296     Global_DisableParentCursor := True;\r
34297     Rslt := Self_.CallDefWndProc( Msg );\r
34298     Global_DisableParentCursor := False;\r
34299     if Rslt = 0 then\r
34300     begin\r
34301       Rslt := 1;\r
34302       case TestCode of\r
34303       HTVSCROLL, HTHSCROLL: Windows.SetCursor( LoadCursor( 0, IDC_ARROW ) );\r
34304       HTCLIENT: Windows.SetCursor( Self_.fCursor );\r
34305       else Result := False;\r
34306       end;\r
34307     end;\r
34308   end;\r
34310 end;\r
34311 {$ENDIF ASM_VERSION}\r
34312 //[END WndProcRichEditNotify]\r
34314 var FRichEditModule: Integer;\r
34315     RichEditClass: PChar = 'RichEdit20A';\r
34316     RichEditLib: PChar = 'RICHED32.DLL';\r
34318 const RichEditLibnames: array[ 0..2 ] of PChar =\r
34319       ( 'RICHED20.DLL', 'RICHED32.DLL', 'RICHED.DLL' );\r
34320 const RichEditflags: array [ TEditOption ] of Integer = (\r
34321                   not (es_AutoHScroll or WS_HSCROLL),\r
34322                   not (es_AutoVScroll or WS_VSCROLL),\r
34323                   0 {es_Lowercase - not supported},\r
34324                   0 {es_Multiline - RichEdit always multiline},\r
34325                   es_NoHideSel,\r
34326                   0 {es_OemConvert - not suppoted},\r
34327                   0 {es_Password - not supported},\r
34328                   es_Readonly,\r
34329                   0 {es_UpperCase - not supported},\r
34330                   es_WantReturn, 0, es_Number );\r
34332 {$IFDEF USE_CONSTRUCTORS}\r
34333 //[function NewRichEdit1]\r
34334 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;\r
34335 begin\r
34336   new( Result, CreateRichEdit1( AParent, Options ) );\r
34337 end;\r
34338 //[END NewRichEdit1]\r
34339 {$ELSE not_USE_CONSTRUCTORS}\r
34341 //[FUNCTION NewRichEdit1]\r
34342 {$IFDEF ASM_VERSION}\r
34343 const RichEditClass10: array[0..8] of Char = ('R','i','c','h','E','d','i','t',#0);\r
34344 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;\r
34345 asm\r
34346         PUSH     EDX\r
34348         MOV      ECX, [FRichEditModule]\r
34349         INC      ECX\r
34350         LOOP     @@loaded\r
34351         PUSHAD\r
34352         MOV      BL, 3\r
34353         LEA      ESI, [RichEditLibNames]\r
34354 @@loo:\r
34355         LODSD\r
34356         PUSH     EAX\r
34357         CALL     LoadLibrary\r
34358         CMP      EAX, HINSTANCE_ERROR\r
34359         JG       @@break\r
34360         MOV      [RichEditClass], offset[RichEditClass10]\r
34361         DEC      BL\r
34362         JNZ      @@loo\r
34363         JMP      @@fault\r
34364 @@break:\r
34365         MOV      [FRichEditModule], EAX\r
34366 @@fault:\r
34367         POPAD\r
34368 @@loaded:\r
34369         PUSH     EAX\r
34370         PUSH     EDX\r
34371         MOV      EAX, ESP\r
34372         MOV      EDX, offset[RichEditFlags]\r
34373         XOR      ECX, ECX\r
34374         MOV      CL, 10\r
34375         CALL     MakeFlags\r
34376         XCHG     ECX, EAX\r
34377         POP      EDX\r
34378         POP      EAX\r
34379         PUSH     1\r
34380         PUSH     offset[RichEditActions]\r
34381         MOV      EDX, [RichEditClass]\r
34382         OR       ECX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER or ES_MULTILINE\r
34383         CALL     _NewCommonControl\r
34384         INC      [EAX].TControl.fIgnoreDefault\r
34385         POP      EDX\r
34386         TEST     DH, 4 // is eoWantTab in Options ?\r
34387         SETZ     DL\r
34388         MOV      [EAX].TControl.fLookTabKeys, DL\r
34389         PUSH     EBX\r
34390         MOV      EBX, EAX\r
34391         MOV      EDX, offset[WndProcRichEditNotify]\r
34392         CALL     TControl.AttachProc\r
34393         MOV      [EBX].TControl.fDoubleBuffered, 0\r
34394         INC      [EBX].TControl.fCannotDoubleBuf\r
34395         ADD      [EBX].TControl.fBoundsRect.Right, 100-64\r
34396         ADD      [EBX].TControl.fBoundsRect.Bottom, 200-64\r
34397         PUSH     ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or ENM_PROTECTED or $04000000\r
34398         PUSH     0\r
34399         PUSH     EM_SETEVENTMASK\r
34400         PUSH     EBX\r
34401         CALL     TControl.Perform\r
34402         MOV      EAX, clWindow\r
34403         MOV      [EBX].TControl.fColor, EAX\r
34404         CALL     Color2RGB\r
34405         PUSH     EAX\r
34406         PUSH     0\r
34407         PUSH     EM_SETBKGNDCOLOR\r
34408         PUSH     EBX\r
34409         CALL     TControl.Perform\r
34410         XCHG     EAX, EBX\r
34411         POP      EBX\r
34412 end;\r
34413 {$ELSE ASM_VERSION} //Pascal\r
34414 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;\r
34415 var Flags, I: Integer;\r
34416 begin\r
34417   if FRichEditModule = 0 then\r
34418   begin\r
34419     for I := 0 to 2 do\r
34420     begin\r
34421       FRichEditModule := LoadLibrary( RichEditLibnames[ I ] );\r
34422       if FRichEditModule > HINSTANCE_ERROR then break;\r
34423       RichEditClass := 'RichEdit';\r
34424     end;\r
34425     if FRichEditModule <= HINSTANCE_ERROR then\r
34426       FRichEditModule := 0;\r
34427   end;\r
34428   Flags := MakeFlags( @Options, RichEditFlags );\r
34429   Result := _NewCommonControl( AParent, RichEditClass, WS_VISIBLE or WS_CHILD\r
34430                          or WS_TABSTOP or WS_BORDER or ES_MULTILINE or Flags,\r
34431                          True, @RichEditActions );\r
34432   Result.fIgnoreDefault := TRUE;\r
34433   Result.fLookTabKeys := [ tkTab ];\r
34434   if eoWantTab in Options then\r
34435      Result.fLookTabKeys := [ ];\r
34437   Result.AttachProc( WndProcRichEditNotify );\r
34438   Result.fDoubleBuffered := False;\r
34439   Result.fCannotDoubleBuf := True;\r
34440   with Result.fBoundsRect do\r
34441   begin\r
34442     Right := Right + 100;\r
34443     Bottom := Top + 200;\r
34444   end;\r
34445   Result.Perform( EM_SETEVENTMASK, 0,\r
34446     ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or\r
34447     ENM_PROTECTED or $04000000 {ENM_LINK} or ENM_KEYEVENTS {or ENM_MOUSEEVENTS} );\r
34448   Result.fColor := clWindow;\r
34449   Result.Perform( EM_SETBKGNDCOLOR, 0, Color2RGB(Result.fColor));\r
34450   //Result.Perform( WM_SIZE, 0, 0 );\r
34451 end;\r
34452 {$ENDIF ASM_VERSION}\r
34453 //[END NewRichEdit1]\r
34455 {$ENDIF USE_CONSTRUCTORS}\r
34457 //[API OleInitialize]\r
34458 function OleInitialize(pwReserved: Pointer): HResult; stdcall;\r
34459   external 'ole32.dll' name 'OleInitialize';\r
34460 procedure OleUninitialize; stdcall;\r
34461   external 'ole32.dll' name 'OleUninitialize';\r
34463 //[FUNCTION OleInit]\r
34464 {$IFDEF ASM_VERSION}\r
34465 function OleInit: Boolean;\r
34466 asm\r
34467         MOV      ECX, [OleInitCount]\r
34468         INC      ECX\r
34469         LOOP     @@init1\r
34470         PUSH     ECX\r
34471         CALL     OleInitialize\r
34472         TEST     EAX, EAX\r
34473         MOV      AL, 0\r
34474         JNZ      @@exit\r
34475 @@init1:\r
34476         INC      [OleInitCount]\r
34477         MOV      AL, 1\r
34478 @@exit:\r
34479 end;\r
34480 {$ELSE ASM_VERSION} //Pascal\r
34481 function OleInit: Boolean;\r
34482 begin\r
34483   if OleInitCount = 0 then\r
34484   begin\r
34485     Result := False;\r
34486     if OleInitialize( nil ) <> 0 then Exit;\r
34487   end;\r
34488   Inc( OleInitCount );\r
34489   Result := True;\r
34490 end;\r
34491 {$ENDIF ASM_VERSION}\r
34492 //[END OleInit]\r
34494 //[PROCEDURE OleUnInit]\r
34495 {$IFDEF ASM_VERSION}\r
34496 procedure OleUnInit;\r
34497 asm\r
34498         MOV      ECX, [OleInitCount]\r
34499         JECXZ    @@exit\r
34500         DEC      [OleInitCount]\r
34501         JNZ      @@exit\r
34502         CALL     OleUninitialize\r
34503 @@exit:\r
34504 end;\r
34505 {$ELSE ASM_VERSION} //Pascal\r
34506 procedure OleUnInit;\r
34507 begin\r
34508   if OleInitCount > 0 then\r
34509   begin\r
34510     Dec( OleInitCount );\r
34511     if OleInitCount = 0 then\r
34512       OleUninitialize;\r
34513   end;\r
34514 end;\r
34515 {$ENDIF ASM_VERSION}\r
34516 //[END OleUnInit]\r
34518 //[API SysAllocStringLen]\r
34519 function SysAllocStringLen;\r
34520          external 'oleaut32.dll' name 'SysAllocStringLen';\r
34521 procedure SysFreeString( psz: PWideChar ); stdcall;\r
34522          external 'oleaut32.dll' name 'SysFreeString';\r
34524 {-}\r
34525 //[function StringToOleStr]\r
34526 function StringToOleStr(const Source: string): PWideChar;\r
34527 var\r
34528   SourceLen, ResultLen: Integer;\r
34529   Buffer: array[0..1023] of WideChar;\r
34530 begin\r
34531   SourceLen := Length(Source);\r
34532   if Length(Source) < SizeOf(Buffer) div 2 then\r
34533     Result := SysAllocStringLen(Buffer, MultiByteToWideChar(0, 0,\r
34534       PChar(Source), SourceLen, Buffer, SizeOf(Buffer) div 2))\r
34535   else\r
34536   begin\r
34537     ResultLen := MultiByteToWideChar(0, 0,\r
34538       Pointer(Source), SourceLen, nil, 0);\r
34539     Result := SysAllocStringLen(nil, ResultLen);\r
34540     MultiByteToWideChar(0, 0, Pointer(Source), SourceLen,\r
34541       Result, ResultLen);\r
34542   end;\r
34543 end;\r
34544 {+}\r
34546 {$IFDEF USE_CONSTRUCTORS}\r
34547 //[function NewRichEdit]\r
34548 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;\r
34549 begin\r
34550   new( Result, CreateRichEdit( AParent, Options ) );\r
34551 end;\r
34552 //[END NewRichEdit]\r
34553 {$ELSE not_USE_CONSTRUCTORS}\r
34555 //[FUNCTION NewRichEdit]\r
34556 {$IFDEF ASM_VERSION}\r
34557 const RichEdit20A: array[0..11] of Char = ('R','i','c','h','E','d','i','t','2','0','A',#0 );\r
34558       RichEd20_DLL: array[ 0..12] of Char = ('R','I','C','H','E','D','2','0','.','D','L','L',#0 );\r
34559 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;\r
34560 const deltaChr = 24; // sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat );\r
34561       deltaPar = sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat );\r
34562 asm\r
34563         PUSHAD\r
34564         CALL     OleInit\r
34565         TEST     EAX, EAX\r
34566         POPAD\r
34567         JZ       @@new1\r
34568         PUSH     [RichEditClass]\r
34569         MOV      [RichEditClass], offset[RichEdit20A]\r
34570         PUSH     [RichEditLib]\r
34571         MOV      [RichEditLib], offset[RichEd20_DLL]\r
34572         CALL     NewRichEdit1\r
34573         POP      [RichEditLib]\r
34574         POP      [RichEditClass]\r
34575         MOV      byte ptr [EAX].TControl.fCharFmtDeltaSz, deltaChr\r
34576         MOV      byte ptr [EAX].TControl.fParaFmtDeltaSz, deltaPar\r
34577         RET\r
34578 @@new1: CALL     NewRichEdit1\r
34579 end;\r
34580 {$ELSE ASM_VERSION} //Pascal\r
34581 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;\r
34582 var OldRichEditClass, OldRichEditLib: PChar;\r
34583 begin\r
34584   if OleInit then\r
34585   begin\r
34586     OldRichEditClass := RichEditClass;\r
34587     RichEditClass := 'RichEdit20A';\r
34588     OldRichEditLib := RichEditLib;\r
34589     RichEditLib := 'RICHED20.DLL';\r
34590     Result := NewRichEdit1( AParent, Options );\r
34591     Result.fCharFmtDeltaSz := 24; //sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat );\r
34592                            // sizeof( TCharFormat2 ) is calculated incorrectly\r
34593     Result.fParaFmtDeltaSz := sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat );\r
34594     RichEditClass := OldRichEditClass;\r
34595     RichEditLib := OldRichEditLib;\r
34596   end\r
34597      else\r
34598     Result := NewRichEdit1( AParent, Options );\r
34599 end;\r
34600 {$ENDIF ASM_VERSION}\r
34601 //[END NewRichEdit]\r
34603 {$ENDIF USE_CONSTRUCTORS}\r
34605 //=====================================================================//\r
34626 { TControl }\r
34628 {$IFDEF ASM_VERSION}\r
34629 //[procedure TControl.Init]\r
34630 procedure TControl.Init;\r
34631 const\r
34632   IniStyle = WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or\r
34633             WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or\r
34634             WS_BORDER or WS_THICKFRAME;\r
34635 asm     //cmd    //opd\r
34636         PUSH     EBX\r
34637         MOV      EBX, EAX\r
34638         CALL     TObj.Init\r
34639         MOV      EDX, offset WndProcDummy\r
34640         MOV      [EBX].fOnDynHandlers, EDX\r
34641         MOV      [EBX].fWndProcKeybd, EDX\r
34642         MOV      [EBX].fWndProcResizeFlicks, EDX\r
34643         MOV      [EBX].fPass2DefProc, EDX\r
34644 //****        MOV      [EBX].fDefWndProc, offset DefWindowProc\r
34645         MOV      [EBX].fWndFunc, offset WndFunc\r
34646         MOV      EDX, offset ClearText\r
34647         MOV      [EBX].fCommandActions.aClear, EDX\r
34648         INC      dword ptr [EBX].fWindowed\r
34649         MOV      EDX, offset DummyObjProc\r
34650         MOV      [EBX].fControlClick, EDX\r
34651         MOV      EDX, clBtnFace\r
34652         MOV      [EBX].fColor, EDX\r
34653         MOV      DL, clWindowText and $FF\r
34654         MOV      [EBX].fTextColor, EDX\r
34655         MOV      byte ptr [EBX].fMargin, 2\r
34656         INC      dword ptr [EBX].fCtl3D\r
34657         INC      dword ptr [EBX].fCtl3Dchild\r
34658         DEC      byte ptr [EBX].fAlphaBlend\r
34659         CALL     NewList\r
34660         MOV      [EBX].fChildren, EAX\r
34661         MOV      byte ptr[EBX].fClsStyle, CS_OWNDC\r
34662         MOV      [EBX].fStyle, IniStyle\r
34663         INC      dword ptr[EBX].fExStyle+2\r
34664         INC      dword ptr[EBX].fVisible\r
34665         INC      dword ptr[EBX].fEnabled\r
34666         CALL     NewList\r
34667         MOV      [EBX].fDynHandlers, EAX\r
34668         POP      EBX\r
34669 end;\r
34670 {$ELSE ASM_VERSION} //Pascal\r
34671 procedure TControl.Init;\r
34672 begin\r
34673   inherited;\r
34674   fOnDynHandlers := WndProcDummy;\r
34675   fWndProcKeybd := WndProcDummy;\r
34676   fWndProcResizeFlicks := WndProcDummy;\r
34677   fPass2DefProc := WndProcDummy;\r
34678 //****  fDefWndProc := @DefWindowProc;\r
34679   fWndFunc := @ WndFunc;\r
34680   fCommandActions.aClear := ClearText;\r
34681   fWindowed := True;\r
34682   fControlClick := DummyObjProc;\r
34683   fColor := clBtnFace;\r
34684   fTextColor := clWindowText;\r
34685   fMargin := 2;\r
34686   fCtl3D := True;\r
34687   fCtl3Dchild := True;\r
34688   fAlphaBlend := 255;\r
34689   fChildren := NewList;\r
34690   fClsStyle := CS_OWNDC;\r
34691   fStyle := WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or\r
34692             WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or\r
34693             WS_BORDER or WS_THICKFRAME;\r
34694   fExStyle := WS_EX_CONTROLPARENT;\r
34695   fVisible := True;\r
34696   fEnabled := True;\r
34697   fDynHandlers := NewList;\r
34698 end;\r
34699 {$ENDIF ASM_VERSION}\r
34701 {$IFDEF ASM_VERSION}\r
34702 //[PROCEDURE CallTControlInit]\r
34703 procedure CallTControlInit( Ctl: PControl );\r
34704 begin\r
34705   Ctl.Init;\r
34706 end;\r
34707 //[END CallTControlInit]\r
34709 //[procedure TControl.InitParented]\r
34710 procedure TControl.InitParented( AParent: PControl );\r
34711 const IStyle = WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or\r
34712             WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or\r
34713             WS_BORDER or WS_THICKFRAME;\r
34714       IExStyle = WS_EX_CONTROLPARENT;\r
34715       IClsStyle = CS_OWNDC;\r
34716       int_IDC_ARROW = integer( IDC_ARROW );\r
34717 asm\r
34718         PUSH      EAX\r
34719         PUSH      EDX\r
34720         CALL      CallTControlInit\r
34721         POP       EDX\r
34722         POP       EAX\r
34723         TEST      EDX, EDX\r
34724         JZ        @@0\r
34725         MOV       ECX, [EDX].fColor\r
34726         MOV       [EAX].fColor, ECX\r
34727 @@0:\r
34728         CALL      SetParent\r
34729 end;\r
34730 {$ELSE ASM_VERSION} //Pascal\r
34731 procedure TControl.InitParented( AParent: PControl );\r
34732 begin\r
34733   Init;\r
34734   if AParent <> nil then\r
34735      fColor := AParent.fColor;\r
34736   Parent := AParent;\r
34737 end;\r
34738 {$ENDIF ASM_VERSION}\r
34740 {$IFDEF ASM_VERSION}\r
34741 //[destructor TControl.Destroy]\r
34742 destructor TControl.Destroy;\r
34743 asm\r
34744         PUSH     EBX\r
34745         MOV      EBX, EAX\r
34746         CALL     TControl.ParentForm\r
34747         TEST     EAX, EAX\r
34748         JZ       @@cur_ctl_removed\r
34749         CMP      [EAX].TControl.fCurrentControl, EBX\r
34750         JNE      @@cur_ctl_removed\r
34751         XOR      EDX, EDX\r
34752         MOV      [EAX].TControl.fCurrentControl, EDX\r
34753 @@cur_ctl_removed:\r
34755         MOV      ECX, [EBX].fHandle\r
34756         JECXZ    @@wndhidden\r
34757         PUSH     SW_HIDE\r
34758         PUSH     ECX\r
34759         CALL     ShowWindow\r
34760 @@wndhidden:\r
34762         MOV      EAX, EBX\r
34763         CALL     Final\r
34764         MOV      EAX, EBX\r
34765         CALL     DestroyChildren\r
34767         XOR      ECX, ECX\r
34768         CMP      [EBX].fDestroying, CL\r
34769         JNZ      @@destroyed\r
34771         XCHG     CL, [EBX].fCtlClsNameChg\r
34772         JECXZ    @@skip_free_clsname\r
34773         MOV      EAX, [EBX].fControlClassName\r
34774         CALL     System.@FreeMem\r
34775 @@skip_free_clsname:\r
34777         INC      [EBX].fDestroying\r
34778         MOV      EAX, [EBX].fFont\r
34779         CALL     TObj.Free\r
34780         MOV      EAX, [EBX].fBrush\r
34781         CALL     TObj.Free\r
34782         MOV      EAX, [EBX].fCanvas\r
34783         CALL     TObj.Free\r
34785         XOR      ECX, ECX\r
34787         MOV      [EBX].fFont, ECX        // +YS\r
34788         MOV      [EBX].fBrush, ECX       // +YS\r
34789         MOV      [EBX].fCanvas, ECX      // +YS\r
34791         XCHG     ECX, [EBX].fCustomData\r
34792         JECXZ    @@custfree\r
34793         XCHG     EAX, ECX\r
34794         CALL     System.@FreeMem\r
34795 @@custfree:\r
34796         MOV      EAX, [EBX].fCustomObj\r
34797         CALL     TObj.Free\r
34799         MOV      EAX, [EBX].fHandle\r
34800         TEST     EAX, EAX\r
34801         JZ       @@free_fields\r
34803         XOR      ECX, ECX\r
34804         XCHG     ECX, [EBX].fAccelTable\r
34805         JECXZ    @@accelTable_destroyed\r
34806         PUSH     ECX\r
34807         CALL     DestroyAcceleratorTable\r
34808 @@accelTable_destroyed:\r
34809         MOV      EAX, [EBX].fMenuObj\r
34810         CALL     TObj.Free\r
34811 @@destroy_img_list:\r
34812         MOV      EAX, [EBX].fImageList\r
34813         TEST     EAX, EAX\r
34814         JZ       @@img_list_destroyed\r
34815         CALL     TObj.Free\r
34816         JMP      @@destroy_img_list\r
34817 @@img_list_destroyed:\r
34819         PUSH     [EBX].fHandle\r
34820         CALL     IsWindow\r
34821         TEST     EAX, EAX\r
34822         JZ       @@destroy2\r
34824         PUSH     EAX\r
34825         PUSH     1\r
34826         PUSH     WM_SETICON\r
34827         PUSH     [EBX].fHandle\r
34828         CALL     SendMessage\r
34829         TEST     EAX, EAX\r
34830         JZ       @@icoremoved\r
34831         CMP      [EBX].fIconShared, 0\r
34832         JNZ      @@icoremoved\r
34833         PUSH     EAX\r
34834         CALL     DestroyIcon\r
34835 @@icoremoved:\r
34836 //********************************************************** Remarked By M.Gerasimov\r
34837 //      PUSH     offset[ID_SELF]\r
34838 //      PUSH     [EBX].fHandle\r
34839 //      CALL     RemoveProp\r
34840 //********************************************************** Remarked By M.Gerasimov\r
34841         CMP      [EBX].fNCDestroyed, 0\r
34842         JNZ      @@destroy2\r
34843         PUSH     [EBX].fHandle\r
34844         CALL     DestroyWindow\r
34845 @@destroy2:\r
34846         XOR      EAX, EAX\r
34847         MOV      [EBX].fHandle, EAX\r
34849 @@free_fields:\r
34850         MOV      EAX, [EBX].fCaption\r
34851         TEST     EAX, EAX\r
34852         JZ       @@caption_freed\r
34853         CALL     System.@FreeMem\r
34854 @@caption_freed:\r
34855         MOV      EAX, [EBX].fStatusTxt\r
34856         TEST     EAX, EAX\r
34857         JZ       @@statusTxt_freed\r
34858         CALL     System.@FreeMem\r
34859 @@statusTxt_freed:\r
34860         MOV      ECX, [EBX].fParent\r
34861         JECXZ    @@removed_from_parent\r
34862         CMP      [ECX].fCurrentControl, EBX\r
34863         JNE      @@removefromParent\r
34864         XOR      EAX, EAX\r
34865         MOV      [ECX].fCurrentControl, EAX\r
34866 @@removefromParent:\r
34867         MOV      EAX, [ECX].fChildren\r
34868         //PUSH     EAX\r
34869         MOV      EDX, EBX\r
34870         {CALL     TList.IndexOf\r
34871         TEST     EAX, EAX\r
34872         POP      EDX\r
34873         JL       @@removed_from_parent\r
34874         XCHG     EAX, EDX\r
34875         CALL     TList.Delete}\r
34876         CALL     TList.Remove\r
34877 @@removed_from_parent:\r
34878         MOV      ECX, [EBX].fTmpBrush\r
34879         JECXZ    @@tmpBrush_deleted\r
34880         PUSH     ECX\r
34881         CALL     DeleteObject\r
34882 @@tmpBrush_deleted:\r
34884         PUSH     EBX\r
34885         PUSH     [EBX].fChildren\r
34886         PUSH     [EBX].fTBttCmd\r
34887         PUSH     [EBX].fTBttTxt\r
34888         PUSH     [EBX].fTmpFont\r
34889         PUSH     [EBX].fDynHandlers\r
34890         MOV      BL, 5\r
34891 @@freeloo:\r
34892         POP      EAX\r
34893         CALL     TObj.Free\r
34894         DEC      BL\r
34895         JNZ      @@freeloo\r
34896         POP      EBX\r
34897         LEA      EAX, [EBX].fREUrl\r
34898         CALL     System.@LStrClr\r
34899         XCHG     EAX, EBX\r
34900         CALL     TObj.Destroy\r
34901 @@destroyed:\r
34902         POP      EBX\r
34903 end;\r
34904 {$ELSE ASM_VERSION} //Pascal\r
34905 destructor TControl.Destroy;\r
34906 var I: Integer;\r
34907     F: PControl;\r
34908     Ico: HIcon;\r
34909 begin\r
34910    {$IFDEF USE_MHTOOLTIP}\r
34911    {$DEFINE destroy}\r
34912    {$I KOLMHToolTip}\r
34913    {$UNDEF destroy}\r
34914    {$ENDIF USE_MHTOOLTIP}\r
34915    F := ParentForm; // or Applet - for form ???\r
34916    if F <> nil then\r
34917    if F.FCurrentControl = @Self then\r
34918       F.FCurrentControl := nil;\r
34920    if FHandle <> 0 then\r
34921       ShowWindow( fHandle, SW_HIDE );\r
34923    Final;\r
34924    DestroyChildren;\r
34926    if not fDestroying then\r
34927    begin\r
34928      fDestroying := True;\r
34930       if fCtlClsNameChg then\r
34931       begin\r
34932         FreeMem( fControlClassName );\r
34933         fCtlClsNameChg := FALSE;\r
34934       end;\r
34936      fFont.Free;\r
34937      fFont := nil;\r
34938      fBrush.Free;\r
34939      fBrush := nil;\r
34940      fCanvas.Free;\r
34941      fCanvas := nil;\r
34943      if fCustomData <> nil then\r
34944        FreeMem( fCustomData );\r
34945      fCustomData := nil;\r
34946      fCustomObj.Free;\r
34947      fCustomObj := nil;\r
34949      if fHandle <> 0 then\r
34950      begin\r
34951 {$IFNDEF NEW_MENU_ACCELL}\r
34952        if fAccelTable <> 0 then\r
34953        begin\r
34954          DestroyAcceleratorTable( fAccelTable );\r
34955          fAccelTable := 0;\r
34956        end;\r
34957 {$ENDIF}\r
34958        fMenuObj.Free;\r
34959        while fImageList <> nil do\r
34960          fImageList.Free;\r
34961        I := fHandle;\r
34962        if IsWindow( I ) then\r
34963        begin\r
34964          Ico := SendMessage( I, WM_SETICON, 1, 0 );\r
34965          if Ico <> 0 then\r
34966          if not fIconShared then\r
34967            DestroyIcon( Ico );\r
34968 //********************************************************** Remarked By M.Gerasimov\r
34969 //       RemoveProp( I, ID_SELF );\r
34970 //********************************************************** Remarked By M.Gerasimov\r
34971          if not fNCDestroyed then\r
34972          begin\r
34973            {$IFDEF DEBUG_ENDSESSION}\r
34974            if EndSession_Initiated then\r
34975              LogFileOutput( GetStartDir + 'es_debug.txt',\r
34976                             'DESTROYING HWND:' + Int2Str( I ) );\r
34977            {$ENDIF}\r
34978            DestroyWindow( I );\r
34979          end;\r
34980        end\r
34981        {$IFDEF TEST_CLOSE}\r
34982          else\r
34983          asm\r
34984            int 3\r
34985          end;\r
34986        {$ENDIF}\r
34987        ;\r
34988        fHandle := 0;\r
34989      end;\r
34991      if fTmpBrush <> 0 then\r
34992         DeleteObject( fTmpBrush );\r
34993      fTmpBrush := 0;\r
34995      if FCaption <> nil then\r
34996         FreeMem( FCaption );\r
34997      if fStatusTxt <> nil then\r
34998         FreeMem( fStatusTxt );\r
35000      if fParent <> nil then\r
35001      begin\r
35002         {I := fParent.fChildren.IndexOf( @Self );\r
35003         if I >= 0 then\r
35004            fParent.fChildren.Delete( I );}\r
35005         fParent.fChildren.Remove( @Self );\r
35006         if fParent.fCurrentControl = @Self then\r
35007           fParent.fCurrentControl := nil;\r
35008      end;\r
35010      fChildren.Free;\r
35011      fTBttCmd.Free;\r
35012      fTBttTxt.Free;\r
35013      fTmpFont.Free;\r
35014      fDynHandlers.Free;\r
35015      fREUrl := '';\r
35016      inherited;\r
35017    end;\r
35018 end;\r
35019 {$ENDIF ASM_VERSION}\r
35021    {$IFDEF USE_MHTOOLTIP}\r
35022    {$DEFINE code}\r
35023    {$I KOLMHToolTip}\r
35024    {$UNDEF code}\r
35025    {$ENDIF}\r
35027 {$IFDEF ASM_VERSION}\r
35028 //[procedure TControl.SetEnabled]\r
35029 procedure TControl.SetEnabled( Value: Boolean );\r
35030 asm\r
35031         PUSH     EBX\r
35032         MOV      EBX, EAX\r
35033         MOVZX    EDX, DL\r
35034         PUSH     EDX\r
35035         CALL     GetEnabled\r
35036         POP      EDX\r
35037         CMP      AL, DL\r
35038         JZ       @@exit\r
35039         MOV      [EBX].fEnabled, DL\r
35040         TEST     EDX, EDX\r
35041         JNZ      @@andnot\r
35042         OR       byte ptr [EBX].fStyle + 3, 8\r
35043         JMP      @@1\r
35044 @@andnot:\r
35045         AND      byte ptr [EBX].fStyle + 3, $F7\r
35046 @@1:\r
35047         MOV      ECX, [EBX].fHandle\r
35048         JECXZ    @@exit\r
35050         PUSH     EDX\r
35051         PUSH     ECX\r
35052         CALL     EnableWindow\r
35054 @@exit:\r
35055         POP      EBX\r
35056 end;\r
35057 {$ELSE ASM_VERSION} //Pascal\r
35058 procedure TControl.SetEnabled( Value: Boolean );\r
35059 begin\r
35060    if GetEnabled = Value then Exit;\r
35061    fEnabled := Value;\r
35062    if Value then\r
35063       fStyle := fStyle and not WS_DISABLED\r
35064    else\r
35065       fStyle := fStyle or WS_DISABLED;\r
35066    if fHandle <> 0 then\r
35067       EnableWindow( fHandle, fEnabled );\r
35068 end;\r
35069 {$ENDIF ASM_VERSION}\r
35071 {$IFDEF ASM_VERSION}\r
35072 //[function TControl.GetParentWindow]\r
35073 function TControl.GetParentWindow: HWnd;\r
35074 asm\r
35075         MOV       EAX, [EAX].fParent\r
35076         TEST      EAX, EAX\r
35077         {\r
35078         JZ        @@exit\r
35080         CALL      TControl.GetWindowHandle\r
35081 @@exit: --- replaced with following (6 bytes instead of 7):\r
35082         }\r
35083         JNZ       TControl.GetWindowHandle\r
35084 end;\r
35085 {$ELSE ASM_VERSION} //Pascal\r
35086 function TControl.GetParentWindow: HWnd;\r
35087 begin\r
35088    Result := 0;\r
35089    if fParent = nil then Exit;\r
35090    Result := fParent.GetWindowHandle;\r
35091 end;\r
35092 {$ENDIF ASM_VERSION}\r
35094 {$IFDEF ASM_VERSION}\r
35095 function TControl.GetWindowHandle: HWnd;\r
35096 asm\r
35097          MOV      ECX, [EAX].fHandle\r
35098          JECXZ    @@1\r
35099          XCHG     EAX, ECX\r
35100          RET\r
35101 @@1:\r
35102          CMP      [EAX].fCreateVisible, 0\r
35103          JNZ      @@2\r
35105          PUSH     EAX\r
35106          XOR      EDX, EDX\r
35107          CALL     TControl.Set_Visible\r
35108          POP      EAX\r
35109          PUSH     EAX\r
35110          //CALL     TControl.CreateWindow\r
35111          CALL     CallTControlCreateWindow\r
35112          { This is a call to Pascal piece of code, which\r
35113            calls virtual method TControl.CreateWindow }\r
35114          POP      EAX\r
35116          INC      [EAX].fCreateHidden\r
35117          JMP      @@0\r
35119 @@2:     PUSH     EAX\r
35120          //CALL     TControl.CreateWindow\r
35121          CALL     CallTControlCreateWindow\r
35122          POP      EAX\r
35123 @@0:\r
35124          MOV      EAX, [EAX].fHandle\r
35125 end;\r
35126 {$ELSE ASM_VERSION} //Pascal\r
35127 function TControl.GetWindowHandle: HWnd;\r
35128 begin\r
35129    if fHandle = 0 then\r
35130    begin\r
35131      if not fCreateVisible then\r
35132      begin\r
35133        Set_Visible( False );\r
35134        CreateWindow; //virtual!!!\r
35135        fCreateHidden := True;\r
35136      end\r
35137         else\r
35138      CreateWindow; //virtual!!!\r
35139    end;\r
35140    Result := fHandle;\r
35141 end;\r
35142 {$ENDIF ASM_VERSION}\r
35143 {-}\r
35145 {$IFDEF _D7orHigher}\r
35146 // may be it was a good idea to replace CreateWindowEx,\r
35147 // but Inprise forget about stdcall... In result, asm-version became broken.\r
35148 //[API CreateWindowEx]\r
35149 function CreateWindowEx(dwExStyle: DWORD; lpClassName: PChar;\r
35150   lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;\r
35151   hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;\r
35152   stdcall; external user32 name 'CreateWindowExA';\r
35153 {$ENDIF}\r
35155 {+}\r
35156 {$IFDEF ASM_VERSION}\r
35157 //[function TControl.CreateWindow]\r
35158 function TControl.CreateWindow: Boolean;\r
35159 const\r
35160   CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;\r
35161   CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;\r
35162   szWndClass = sizeof( TWndClass );\r
35163   int_IDC_ARROW = integer( IDC_ARROW );\r
35164 asm\r
35165         PUSH     EBX\r
35166         XCHG     EBX, EAX\r
35167         MOV      ECX, [EBX].fParent\r
35168         JECXZ    @@chk_handle\r
35169         XCHG     EAX, ECX\r
35170         CALL     GetWindowHandle\r
35171         TEST     EAX, EAX\r
35172         JZ       @@ret_false\r
35173 @@chk_handle:\r
35174         MOV      ECX, [EBX].fHandle\r
35175         JECXZ    @@prepare_Params\r
35176         MOV      DL, 0\r
35177         MOV      EAX, EBX\r
35178         CMP      [EBX].fCreateHidden, DL\r
35179         JZ       @@create_children\r
35180         CALL     CreateChildWindows\r
35181         MOV      EAX, EBX\r
35182         MOV      DL, 1\r
35183         CALL     Set_Visible\r
35184         MOV      [EBX].fCreateHidden, 0\r
35185         JMP      @@ret_true\r
35186 @@create_children:\r
35187         CALL     CreateChildWindows\r
35188 @@ret_true:\r
35189         MOV      AL, 1\r
35190         POP      EBX\r
35191         RET\r
35192 @@prepare_params:\r
35193         PUSH     EBP\r
35194         MOV      EBP, ESP\r
35196         PUSH     ECX        // Params.WindowClass.lpszClassName := nil\r
35197         PUSH     ECX        // Params.WindowClass.lpszMenuName := nil\r
35198         PUSH     ECX        // Params.WindowClass.hbrBackground := 0\r
35199         PUSH     int_IDC_ARROW\r
35200         PUSH     ECX\r
35201         CALL     LoadCursor\r
35202         PUSH     EAX        // Params.WindowClass.hCursor := LoadCursor( 0, IDC_ARROW )\r
35203         XOR      ECX, ECX\r
35204         PUSH     ECX        // Params.WindowClass.hIcon := 0\r
35205         PUSH     [hInstance]// Params.WindowClass.hInstance := hInstance\r
35206         PUSH     ECX        // Params.WindowClass.cbWndExtra := 0\r
35207         PUSH     ECX        // Params.WindowClass.cbClsExtra := 0\r
35208         //PUSH     offset DefWindowProc // Params.WindowClass.lpfnWndProc := @DefWindowProc\r
35209         PUSH     [EBX].fDefWndProc     // Params.WindowClass.lpfnWndProc := fDefWndProc\r
35210         PUSH     [EBX].fClsStyle       // Params.WindowClass.style := fStyle\r
35211         ADD      ESP, -64\r
35212         PUSH     ECX\r
35213         MOV      EAX, EBX\r
35214         MOV      EDX, ESP\r
35215         CALL     get_ClassName\r
35216         POP      EDX\r
35217         MOV      EAX, ESP\r
35218         PUSH     EDX\r
35219         //CALL     StrPCopy    // StrPCopy( Params.WinClsNamBuf, ClassName )\r
35220         CALL     StrCopy\r
35221         CALL     RemoveStr\r
35222         PUSH     0           // Params.Param := nil\r
35223         PUSH     [hInstance] // Params.Inst := fInstance\r
35224         PUSH     [EBX].fMenu // Params.Menu := fMenu\r
35225         MOV      DL, 1\r
35226         MOV      EAX, EBX\r
35227         CALL     GetParentWnd\r
35228         PUSH     EAX         // Params.WndParent := GetParentWnd( True )\r
35230         MOV      ECX, CW_USEDEFAULT\r
35231         MOV      EAX, [EBX].fBoundsRect.Bottom\r
35232         MOV      EDX, [EBX].fBoundsRect.Top\r
35233         SUB      EAX, EDX\r
35234         JNZ      @@1\r
35235         MOV      EAX, ECX\r
35236 @@1:    PUSH     EAX         // Params.Height := Height | CW_UseDefault\r
35237         MOV      EAX, [EBX].fBoundsRect.Right\r
35238         SUB      EAX, [EBX].fBoundsRect.Left\r
35239         {$IFDEF USE_CMOV}\r
35240         CMOVZ    EAX, ECX\r
35241         {$ELSE}\r
35242         JNZ      @@2\r
35243         MOV      EAX, ECX\r
35244 @@2:    {$ENDIF}\r
35246         PUSH     EAX         // Params.Width := Width | CW_UseDefault\r
35247         MOV      EAX, [EBX].fBoundsRect.Left\r
35248         CMP      [EBX].fIsControl, CL\r
35249         JNZ      @@3\r
35250         TEST     byte ptr [EBX].fChangedPosSz, 3\r
35251         JNZ      @@3\r
35252         MOV      EDX, ECX\r
35253         XCHG     EAX, ECX\r
35254 @@3:    PUSH     EDX         // Params.Y := Top | CW_UseDefault\r
35255         PUSH     EAX         // Params.X := Left | CW_UseDefault\r
35256         PUSH     [EBX].fStyle    // Params.Style := fStyle\r
35257         PUSH     [EBX].fCaption  // Params.Caption := fCaption\r
35258         LEA      EAX, [ESP+40]\r
35259         PUSH     EAX         // Params.WinClassName := @Params.WinClsNamBuf\r
35260         PUSH     [EBX].fExStyle  // Params.ExStyle := fExStyle\r
35262         MOV      ECX, [EBX].fControlClassName\r
35263         JECXZ    @@registerClass\r
35264         LEA      EAX, [ESP].TCreateWndParams.WindowClass\r
35265         PUSH     EAX           // @Params.WindowClass\r
35266         PUSH     ECX           // fControlClassName\r
35267         PUSH     [hInstance]   // hInstance\r
35268         CALL     GetClassInfo\r
35269         MOV      EAX, [ESP].TCreateWndParams.Inst\r
35270         MOV      [ESP].TCreateWndParams.WindowClass.hInstance, EAX\r
35271         AND      [ESP].TCreateWndParams.WindowClass.style, not CS_OFF\r
35272 @@registerClass:\r
35273         CMP      [EBX].fDefWndProc, 0\r
35274         JNE      @@fDefWndProc_ready\r
35275         MOV      EAX, [ESP].TCreateWndParams.WindowClass.lpfnWndProc\r
35276         MOV      [EBX].fDefWndProc, EAX\r
35277 @@fDefWndProc_ready:\r
35278         MOV      ECX, [ESP].TCreateWndParams.WndParent\r
35279         INC      ECX\r
35280         LOOP     @@registerClass1\r
35281         TEST     byte ptr [ESP].TCreateWndParams.Style+3, $40\r
35282         XCHG     EAX, ECX\r
35283         JNZ      @@fin\r
35284 @@registerClass1:\r
35285         MOV      EAX, [ESP].TCreateWndParams.WinClassName\r
35286         MOV      EDX, [ESP].TCreateWndParams.WindowClass.hInstance\r
35287         ADD      ESP, -szWndClass\r
35288         PUSH     ESP\r
35289         PUSH     EAX\r
35290         PUSH     EDX\r
35291         CALL     GetClassInfo\r
35292         ADD      ESP, szWndClass\r
35293         TEST     EAX, EAX\r
35294         JNZ      @@registered\r
35295         MOV      EAX, [ESP].TCreateWndParams.WinClassName\r
35296         MOV      [ESP].TCreateWndParams.WindowClass.lpszClassName, EAX\r
35297         MOV      [ESP].TCreateWndParams.WindowClass.lpfnWndProc, offset WndFunc\r
35298         LEA      EAX, [ESP].TCreateWndParams.WindowClass\r
35299         PUSH     EAX\r
35300         CALL     RegisterClass\r
35301         TEST     EAX, EAX\r
35302         JZ       @@fin\r
35303 @@registered:\r
35304         MOV      [CreatingWindow], EBX\r
35305         CALL     CreateWindowEx\r
35306         MOV      [EBX].fHandle, EAX\r
35307         TEST     EAX, EAX\r
35308         JZ       @@fin\r
35309         PUSH     EAX\r
35310         PUSH     offset ID_SELF\r
35311         PUSH     EAX\r
35313    //SendMessage(fHandle,WM_UPDATEUISTATE,UIS_CLEAR or (UISF_HIDEFOCUS shl 16),0);\r
35314         PUSH     0\r
35315         PUSH     $10002 //UIS_CLEAR or (UISF_HIDEFOCUS shl 16)\r
35316         PUSH     $0128  //WM_UPDATEUISTATE\r
35317         PUSH     EAX\r
35318         CALL     SendMessage\r
35320         CALL     GetProp\r
35321         XCHG     ECX, EAX\r
35322         POP      EAX\r
35323         INC      ECX\r
35324         LOOP     @@propSet\r
35325         MOV      [CreatingWindow], ECX\r
35326         PUSH     EBX\r
35327         PUSH     offset ID_SELF\r
35328         PUSH     EAX\r
35329         CALL     SetProp\r
35330 @@propSet:\r
35331         CMP      [EBX].fIsControl, 0\r
35332         JNZ      @@iconSet\r
35333         MOV      EAX, EBX\r
35334         CALL     GetIcon\r
35335         PUSH     EAX\r
35336         PUSH     1\r
35337         PUSH     WM_SETICON\r
35338         PUSH     EBX\r
35339         CALL     Perform\r
35340 @@iconSet:\r
35341         MOV      ECX, [EBX].fCreateWndExt\r
35342         JECXZ    @@dblbufcreate\r
35343         MOV      EAX, EBX\r
35344         CALL     ECX\r
35345 @@dblbufcreate:\r
35346         MOV      EAX, EBX\r
35347         CALL     Dword Ptr [ Global_DblBufCreateWnd ]\r
35348 @@applyfont:\r
35349         MOV      EAX, EBX\r
35350         CALL     ApplyFont2Wnd\r
35351         MOV      EAX, EBX\r
35352         CALL     ApplyFont2Wnd\r
35353         XCHG     EAX, EBX\r
35354         CALL     CreateChildWindows\r
35355         MOV      AL, 1\r
35356 @@fin:\r
35357         MOV      ESP, EBP\r
35358         POP      EBP\r
35359 @@ret_false:\r
35360         POP      EBX\r
35361 end;\r
35362 {$ELSE ASM_VERSION} //Pascal\r
35363 function TControl.CreateWindow: Boolean;\r
35364 const\r
35365   CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;\r
35366   CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;\r
35367 var TempClass: TWndClass;\r
35368     Params: TCreateWndParams;\r
35369     ClassRegistered: Boolean;\r
35370     {$IFDEF _FPC}\r
35371     SClassName: String;\r
35372     {$ENDIF ASM_VERSION}\r
35373 begin\r
35374    {$IFDEF DEBUG_CREATEWINDOW}\r
35375    LogFileOutput( GetStartDir + 'Session.log', 'TControl.CreateWindow, ' +\r
35376                   ' Self = ' + Int2Str( Integer( @ Self ) ) +\r
35377                   ' Caption = ' + fCaption +\r
35378                   ' fChildren = ' + Int2Hex( Integer( fChildren ), 4 ) +\r
35379                   ' ChildCount = ' + Int2Str( ChildCount ) );\r
35380    {$ENDIF DEBUG_CREATEWINDOW}\r
35381    Result := False;\r
35382    if fParent <> nil then\r
35383      if fParent.GetWindowHandle = 0 then\r
35384        Exit;\r
35385    if fHandle <> 0 then\r
35386    begin\r
35387      if fCreateHidden then\r
35388      begin\r
35389        CreateChildWindows;\r
35390        Set_Visible( True );\r
35391        fCreateHidden := False;\r
35392      end\r
35393         else\r
35394      begin\r
35395        CreateChildWindows;\r
35396      end;\r
35397      Result := True;\r
35398      Exit;\r
35399    end;\r
35401    FillChar( Params, Sizeof( Params ), 0 );\r
35402    Params.Caption := PChar( FCaption );\r
35403    Params.Style := FStyle;\r
35404    if not fEnabled then\r
35405       Params.Style := Params.Style or WS_DISABLED;\r
35406    Params.ExStyle := FExStyle;\r
35407    Params.WindowClass.style := FClsStyle;\r
35408    {Params.WindowClass.lpfnWndProc := @ DefWindowProc;\r
35409    if fDefWndProc <> nil then} //+-+\r
35410      Params.WindowClass.lpfnWndProc := FDefWndProc;\r
35411    Params.WindowClass.hCursor := LoadCursor( 0, IDC_ARROW );\r
35412    Params.WindowClass.hInstance := hInstance;\r
35413    Params.Inst := hInstance;\r
35414    {$IFDEF _FPC}\r
35415    SClassName := SubClassName;\r
35416    StrCopy( Params.WinClsNamBuf, @ SClassName[ 1 ] );\r
35417    {$ELSE}\r
35418    StrCopy( Params.WinClsNamBuf, @ SubClassName[ 1 ] );\r
35419    {$ENDIF}\r
35420    Params.WinClassName := @Params.WinClsNamBuf[ 0 ];\r
35421    Params.WndParent := GetParentWnd( True );\r
35422    Params.Menu := fMenu;\r
35423    Params.X := fBoundsRect.Left;\r
35424    Params.Y := fBoundsRect.Top;\r
35425    Params.Width := fBoundsRect.Right - fBoundsRect.Left;\r
35426    if Params.Width = 0 then\r
35427      Params.Width := CW_UseDefault;\r
35428    Params.Height := fBoundsRect.Bottom - fBoundsRect.Top;\r
35429    if Params.Height = 0 then\r
35430      Params.Height := CW_UseDefault;\r
35431    if not fIsControl then\r
35432    begin\r
35433      if not LongBool( fChangedPosSz and 3 ) then\r
35434      begin\r
35435        Params.X := CW_UseDefault;\r
35436        Params.Y := CW_UseDefault;\r
35437      end;\r
35438    end;\r
35440     if fControlClassName <> nil then\r
35441     begin // SUBCLASSING WINDOW\r
35442       GetClassInfo( Params.WindowClass.hInstance, fControlClassName,\r
35443                     Params.WindowClass);\r
35444       Params.WindowClass.hInstance := Params.Inst;\r
35445       Params.WindowClass.style := Params.WindowClass.style\r
35446                                and not CS_OFF or CS_ON;\r
35447     end;\r
35449    if FDefWndProc = nil then //+\r
35450    {$IFDEF F_P}\r
35451       Move( Params.WindowClass.lpfnWndProc, FDefWndProc, Sizeof( Pointer ) );\r
35452    {$ELSE}\r
35453       FDefWndProc := Params.WindowClass.lpfnWndProc;\r
35454    {$ENDIF}\r
35455    if (Params.WndParent = 0) and (Params.Style and WS_CHILD <> 0) then Exit;\r
35456    ClassRegistered := GetClassInfo( Params.WindowClass.hInstance,\r
35457                       Params.WinClassName, TempClass );\r
35458    if not ClassRegistered then\r
35459    begin\r
35460       Params.WindowClass.lpszClassName := Params.WinClassName;\r
35461       Params.WindowClass.lpfnWndProc := fWndFunc;\r
35462       if RegisterClass( Params.WindowClass ) = 0 then Exit;\r
35463    end;\r
35464    {$IFDEF DEBUG_CREATEWINDOW}\r
35465    LogFileOutput( GetStartDir + 'Session.log',\r
35466                   ' ExStyle=' + Int2Hex( Params.ExStyle, 4 ) +\r
35467                   ' WinClassName=' + Params.WinClassName +\r
35468                   ' Caption=' + Params.Caption +\r
35469                   ' Style=' + Int2Hex( Params.Style, 4 ) +\r
35470                   ' X=' + Int2Str( Params.X ) +\r
35471                   ' Y=' + Int2Str( Params.Y ) +\r
35472                   ' Width=' + Int2Str( Params.Width ) +\r
35473                   ' Height=' + Int2Str( Params.Height ) +\r
35474                   ' WndParent=' + Int2Str( Params.WndParent ) +\r
35475                   ' Menu=' + Int2Str( Params.Menu ) +\r
35476                   ' hInstance=' + Int2Str( Params.WindowClass.hInstance ) +\r
35477                   ' Param=' + Int2Str( Integer( Params.Param ) )\r
35478                    );\r
35479    {$ENDIF}\r
35480    CreatingWindow := @Self;\r
35481    fHandle := CreateWindowEx( Params.ExStyle, Params.WinClassName,\r
35482                               Params.Caption, Params.Style, Params.X, Params.Y,\r
35483                               Params.Width, Params.Height, Params.WndParent,\r
35484                               Params.Menu, Params.WindowClass.hInstance,\r
35485                               Params.Param );\r
35486    if fHandle = 0 then Exit;\r
35487    SendMessage( fHandle, $0128 {WM_UPDATEUISTATE},\r
35488                 2 {UIS_CLEAR} or (1 {UISF_HIDEFOCUS} shl 16),0);\r
35489    if GetProp(FHandle,ID_SELF) = 0 then\r
35490    begin\r
35491       CreatingWindow := nil;\r
35492       SetProp(FHandle, ID_SELF, THandle(@Self));\r
35493    end;\r
35494    //***\r
35495    if not fIsControl then\r
35496      SendMessage( fHandle, WM_SETICON, 1 {ICON_BIG}, GetIcon );\r
35497    if Assigned( FCreateWndExt ) then\r
35498       FCreateWndExt( @Self );\r
35499    Global_DblBufCreateWnd( @ Self );\r
35500    ApplyFont2Wnd;\r
35501    ApplyFont2Wnd;\r
35503    CreateChildWindows;\r
35504    Result := True;\r
35505 end;\r
35506 {$ENDIF}\r
35508 //-\r
35509 //[procedure TControl.CreateSubclass]\r
35510 procedure TControl.CreateSubclass(var Params: TCreateParams;\r
35511   ControlClassName: PChar);\r
35512 const\r
35513   CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;\r
35514   CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;\r
35515 var\r
35516   SaveInstance: THandle;\r
35517 begin\r
35518   if fControlClassName <> nil then\r
35519     with Params do\r
35520     begin\r
35521       SaveInstance := WindowClass.hInstance;\r
35522       if not GetClassInfo(HInstance, fControlClassName, WindowClass) and\r
35523         not GetClassInfo(0, fControlClassName, WindowClass)\r
35524         //and not GetClassInfo(HInstance {MainInstance}, fControlClassName, WindowClass)\r
35525       then\r
35526         GetClassInfo(WindowClass.hInstance, fControlClassName, WindowClass);\r
35527       WindowClass.hInstance := SaveInstance;\r
35528       WindowClass.style := WindowClass.style and not CS_OFF or CS_ON;\r
35529     end;\r
35530 end;\r
35532 //[FUNCTION WndProcMous]\r
35533 {$IFDEF ASM_VERSION}\r
35534 function WndProcMouse(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
35535 asm\r
35536          PUSH      EBX\r
35537          PUSH      ESI\r
35538          XCHG      EBX, EAX\r
35540          XOR       ECX, ECX // Rslt not used. ECX <= Result = 0\r
35541          MOV       EAX, [EDX].TMsg.message\r
35542          SUB       AH, WM_MOUSEFIRST shr 8\r
35543          CMP       EAX, $20A - WM_MOUSEFIRST //WM_MOUSELAST - WM_MOUSEFIRST\r
35544          JA        @@exit\r
35546          PUSH      dword ptr [EDX].TMsg.lParam // prepare X, Y\r
35548          PUSHAD\r
35550            PUSH      VK_MENU\r
35551            CALL      GetKeyState\r
35552            ADD       EAX, EAX\r
35553          POPAD\r
35554          XCHG        EAX, EDX\r
35555            MOV       EAX, [EAX].TMsg.wParam\r
35557            JNC       @@noset_MKALT\r
35558            {$IFDEF PARANOIA}\r
35559            DB $0C, MK_ALT\r
35560            {$ELSE}\r
35561            OR        AL, MK_ALT\r
35562            {$ENDIF}\r
35563 @@noset_MKALT:\r
35565          PUSH      EAX             // prepare Shift\r
35567          LEA       ESI, [EBX].TControl.fOnMouseDown\r
35568          CALL      dword ptr [EDX*4 + @@jump_table]\r
35570 @@call_evnt:\r
35571          PUSH      ECX             // prepare Button, StopHandling\r
35572          MOV       ECX, ESP        // ECX = @MouseData\r
35574          CMP       word ptr [ESI].TMethod.Code+2, 0\r
35575          JZ        @@after_call\r
35577          MOV       EDX, EBX        // EDX = Self_\r
35578          MOV       EAX, [ESI].TMethod.Data      // EAX = Target_\r
35579          CALL      dword ptr [ESI].TMethod.Code\r
35581 @@after_call:\r
35582          POP       ECX\r
35583          POP       EDX\r
35584          POP       EDX\r
35585          MOV       CL, CH           // Result := StopHandling\r
35587 @@exit:\r
35588          XCHG      EAX, ECX\r
35589          POP       ESI\r
35590          POP       EBX\r
35591          RET\r
35593 @@jump_table:\r
35594          DD Offset[@@MMove],Offset[@@LDown],Offset[@@LUp],Offset[@@LDblClk]\r
35595          DD Offset[@@RDown],Offset[@@RUp],Offset[@@RDblClk]\r
35596          DD Offset[@@MDown],Offset[@@MUp],Offset[@@MDblClk],Offset[@@MWheel]\r
35598 @@MDown: INC       ECX\r
35599 @@RDown: INC       ECX\r
35600 @@LDown: INC       ECX\r
35601          //LEA       ESI, [EBX].TControl.fOnMouseDown\r
35602          RET\r
35604 @@MUp:   INC       ECX\r
35605 @@RUp:   INC       ECX\r
35606 @@LUp:   INC       ECX\r
35607          //LEA       ESI, [EBX].TControl.fOnMouseUp\r
35608          LODSD\r
35609          LODSD\r
35610          RET\r
35612 @@MMove: LEA       ESI, [EBX].TControl.fOnMouseMove\r
35613          //ADD       ESI, 16\r
35614          RET\r
35616 @@MDblClk: INC     ECX\r
35617 @@RDblClk: INC     ECX\r
35618 @@LDblClk: INC     ECX\r
35619          LEA       ESI, [EBX].TControl.fOnMouseDblClk\r
35620          //ADD       ESI, 24\r
35621          RET\r
35623 @@MWheel:LEA       ESI, [EBX].TControl.fOnMouseWheel\r
35624          //ADD       ESI, 32\r
35625          //RET\r
35626 end;\r
35627 {$ELSE ASM_VERSION} //Pascal\r
35628 function WndProcMouse(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
35629 var MouseData: TMouseEventData;\r
35630 begin\r
35631   Result := False;\r
35632   if (Msg.message >= WM_MOUSEFIRST) and (Msg.message <= $20A {WM_MOUSELAST}) and\r
35633      (Msg.hwnd = Self_.fHandle) then\r
35634   with MouseData do\r
35635   begin\r
35636     Shift := Msg.wParam;\r
35637     if GetKeyState( VK_MENU ) < 0 then\r
35638        Shift := Shift or MK_ALT;\r
35639     X := LoWord( Msg.lParam );\r
35640     Y := HiWord( Msg.lParam );\r
35641     Button := mbNone;\r
35642     StopHandling := FALSE;\r
35643     Rslt := 0; // needed ?\r
35644     case Msg.message of\r
35645     WM_LBUTTONDOWN:\r
35646       if Assigned( Self_.OnMouseDown ) then\r
35647       begin\r
35648          Button := mbLeft;\r
35649          Self_.OnMouseDown( Self_, MouseData );\r
35650       end;\r
35651     WM_RBUTTONDOWN:\r
35652       if Assigned( Self_.OnMouseDown ) then\r
35653       begin\r
35654          Button := mbRight;\r
35655          Self_.OnMouseDown( Self_, MouseData );\r
35656       end;\r
35657     WM_MBUTTONDOWN:\r
35658       if Assigned( Self_.OnMouseDown ) then\r
35659       begin\r
35660          Button := mbMiddle;\r
35661          Self_.OnMouseDown( Self_, MouseData );\r
35662       end;\r
35663     WM_LBUTTONUP:\r
35664       if Assigned( Self_.OnMouseUp ) then\r
35665       begin\r
35666          Button := mbLeft;\r
35667          Self_.OnMouseUp( Self_, MouseData );\r
35668       end;\r
35669     WM_RBUTTONUP:\r
35670       if Assigned( Self_.OnMouseUp ) then\r
35671       begin\r
35672          Button := mbRight;\r
35673          Self_.OnMouseUp( Self_, MouseData );\r
35674       end;\r
35675     WM_MBUTTONUP:\r
35676       if Assigned( Self_.OnMouseUp ) then\r
35677       begin\r
35678          Button := mbMiddle;\r
35679          Self_.OnMouseUp( Self_, MouseData );\r
35680       end;\r
35681     WM_MOUSEMOVE:\r
35682       if Assigned( Self_.OnMouseMove ) then\r
35683          Self_.OnMouseMove( Self_, MouseData );\r
35684     WM_LBUTTONDBLCLK:\r
35685       if Assigned( Self_.OnMouseDblClk ) then\r
35686       begin\r
35687          Button := mbLeft;\r
35688          Self_.OnMouseDblClk( Self_, MouseData );\r
35689       end;\r
35690     WM_RBUTTONDBLCLK:\r
35691       if Assigned( Self_.OnMouseDblClk ) then\r
35692       begin\r
35693          Button := mbRight;\r
35694          Self_.OnMouseDblClk( Self_, MouseData );\r
35695       end;\r
35696     WM_MBUTTONDBLCLK:\r
35697       if Assigned( Self_.OnMouseDblClk ) then\r
35698       begin\r
35699          Button := mbMiddle;\r
35700          Self_.OnMouseDblClk( Self_, MouseData );\r
35701       end;\r
35702     $020A {WM_MOUSEWHEEL}:\r
35703       if Assigned( Self_.OnMouseWheel ) then\r
35704          Self_.OnMouseWheel( Self_, MouseData );\r
35705     else\r
35706       Exit; //Result := False;\r
35707     end;\r
35708     Result := StopHandling;\r
35709   end;\r
35710 end;\r
35711 {$ENDIF ASM_VERSION}\r
35712 //[END WndProcMous]\r
35714 //[FUNCTION WndProcKeybd]\r
35715 {$IFDEF ASM_VERSION}\r
35716 function WndProcKeybd( Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
35717 asm\r
35718         PUSH     EBX\r
35719         MOV      ECX, [EDX].TMsg.message\r
35720         SUB      CX, $100\r
35721         CMP      ECX, 5\r
35722         JA       @@fin_false\r
35723         XCHG     EBX, EAX   // EBX = @Self\r
35724         XCHG     EAX, ECX   // EAX = message - WM_KEYFIRST\r
35725         LEA      ECX, [EBX].TControl.fOnKeyUp\r
35726         JZ       @@event\r
35727         {$IFDEF PARANOIA}\r
35728         DB $34, 1\r
35729         {$ELSE}\r
35730         XOR      AL, 1\r
35731         {$ENDIF}\r
35732         JZ       @@event\r
35733         LEA      ECX, [EBX].TControl.fOnKeyDown\r
35734         {$IFDEF PARANOIA}\r
35735         DB $34, 1\r
35736         {$ELSE}\r
35737         XOR      AL, 1\r
35738         {$ENDIF}\r
35739         JZ       @@event\r
35740         {$IFDEF PARANOIA}\r
35741         DB $34, 4\r
35742         {$ELSE}\r
35743         XOR      AL, 4\r
35744         {$ENDIF}\r
35745         JZ       @@event\r
35746         LEA      ECX, [EBX].TControl.fOnChar\r
35747         {$IFDEF PARANOIA}\r
35748         DB $34, 6\r
35749         {$ELSE}\r
35750         XOR      AL, 2 xor 4\r
35751         {$ENDIF}\r
35752         JZ       @@event\r
35753         {$IFDEF PARANOIA}\r
35754         DB $34, 4\r
35755         {$ELSE}\r
35756         XOR      AL, 6 xor 2\r
35757         {$ENDIF}\r
35758         JNZ      @@fin_false\r
35759 @@event:\r
35760         CMP      word ptr [ECX].TMethod.Code+2, 0\r
35761         JZ       @@fin_false\r
35762         PUSH     EDX\r
35763         PUSH     ECX\r
35764         LEA      ECX, [EDX].TMsg.wParam\r
35765         PUSH     ECX\r
35766         CALL     GetShiftState\r
35767         POP      ECX         // @wParam\r
35768         XCHG     EAX, [ESP]  // ShiftState; EAX=@event\r
35769         MOV      EDX, EBX    // @Self\r
35770         MOV      EBX, [EAX].TMethod.Code\r
35771         MOV      EAX, [EAX].TMethod.Data\r
35772         CALL     EBX\r
35774         POP      EDX\r
35775         MOV      ECX, [EDX].TMsg.wParam\r
35776         JECXZ    @@fin_true\r
35778 @@fin_false:\r
35779         XOR      EAX, EAX\r
35780         POP      EBX\r
35781         RET\r
35783 @@fin_true:\r
35784         MOV      AL, 1\r
35785         POP      EBX\r
35786 end;\r
35787 {$ELSE ASM_VERSION} //Pascal\r
35788 function WndProcKeybd(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
35789 var C : Char;\r
35790 begin\r
35791   Result := True;\r
35792   case Msg.message of\r
35793     WM_KEYDOWN, WM_SYSKEYDOWN:\r
35794       if assigned( Self_.fOnKeyDown ) then\r
35795          Self_.fOnKeyDown( Self_, Msg.wParam, GetShiftState );\r
35796     WM_KEYUP, WM_SYSKEYUP:\r
35797       if assigned( Self_.fOnKeyUp ) then\r
35798          Self_.fOnKeyUp( Self_, Msg.wParam, GetShiftState );\r
35799     WM_CHAR, WM_SYSCHAR:\r
35800       if assigned( Self_.fOnChar ) then\r
35801       begin\r
35802          C := Char( Msg.wParam );\r
35803          Self_.fOnChar( Self_, C, GetShiftState );\r
35804          Msg.wParam := Integer( C );\r
35805       end;\r
35806     else begin\r
35807            Result := False;\r
35808            Exit;\r
35809          end;\r
35810   end;\r
35811   if Msg.wParam <> 0 then\r
35812     Result := False;\r
35813 end;\r
35814 {$ENDIF ASM_VERSION}\r
35815 //[END WndProcKeybd]\r
35817 //[function WndProcDummy]\r
35818 function WndProcDummy(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
35819 begin\r
35820   Result := False;\r
35821 end;\r
35823 //[procedure ExcludeCtlsWhichCannotDblBuf]\r
35824 procedure ExcludeCtlsWhichCannotDblBuf( Sender, ParentCtl: PControl; DC: HDC );\r
35825 var I: Integer;\r
35826     C: PControl;\r
35827     R, R1: TRect;\r
35828 begin\r
35829   for I := 0 to ParentCtl.fChildren.Count-1 do\r
35830   begin\r
35831     C := ParentCtl.fChildren.Items[ I ];\r
35832     if C.fCannotDoubleBuf then\r
35833     begin\r
35834       GetWindowRect( Sender.fHandle, R );\r
35835       GetWindowRect( C.fHandle, R1 );\r
35836       OffsetRect( R1, -R.Left, -R.Top );\r
35837       ExcludeClipRect(DC, R1.Left, R1.Top, R1.Right, R1.Bottom);\r
35838     end\r
35839       else\r
35840       ExcludeCtlsWhichCannotDblBuf( Sender, C, DC );\r
35841   end;\r
35842 end;\r
35844 //[procedure DoReleaseDblBufBmp]\r
35845 procedure DoReleaseDblBufBmp( Sender: PControl );\r
35846 begin\r
35847   if Sender.fDblBufBmp <> 0 then\r
35848     DeleteObject( Sender.fDblBufBmp );\r
35849 end;\r
35851 //[procedure DoDrawChildrenDblBuffered]\r
35852 procedure DoDrawChildrenDblBuffered( DC: HDC; WndParent: HWnd; const RectParent: TRect;\r
35853           W: HWnd );\r
35854 var R, CR: TRect;\r
35855     Save: Integer;\r
35856     P, P0: TPoint;\r
35857 begin\r
35858   while W <> 0 do\r
35859   begin\r
35860     if IsWindowVisible( W ) then\r
35861     begin\r
35862       Save := SaveDC( DC );\r
35863       GetWindowRect( W, R );\r
35864       GetWindowOrgEx( DC, P );\r
35865       SetWindowOrgEx( DC, P.x - ( R.Left - RectParent.Left ), P.y - ( R.Top - RectParent.Top ), nil );\r
35866       IntersectClipRect( DC, 0, 0, R.Right - R.Left, R.Bottom - R.Top );\r
35867       SendMessage( W, WM_PRINT, DC, PRF_NONCLIENT );\r
35868       GetClientRect( W, CR );\r
35869       P0.x := 0; P0.y := 0;\r
35870       ClientToScreen( W, P0 );\r
35871       OffsetRect( CR, P0.x, P0.y );\r
35872       SetWindowOrgEx( DC, P.x - (CR.Left - RectParent.Left), P.y - (CR.Top - RectParent.Top), nil );\r
35873       IntersectClipRect( DC, 0, 0, CR.Right - CR.Left, CR.Bottom - CR.Top );\r
35874       SendMessage( W, WM_ERASEBKGND, DC, 0 );\r
35875       SendMessage( W, WM_PAINT, DC, 0 );\r
35876       DoDrawChildrenDblBuffered( DC, W, CR, GetWindow( W, GW_CHILD ) );\r
35877       RestoreDC( DC, Save );\r
35878     end;\r
35879     W := GetWindow( W, GW_HWNDNEXT );\r
35880   end;\r
35881 end;\r
35883 //[procedure DoDrawDblBuffered]\r
35884 procedure DoDrawDblBuffered( Sender: PControl );\r
35885 var R: TRect;\r
35886     DC0, DC1, DC2: HDC;\r
35887     OldBmp: HBitmap;\r
35888     R2: TRect;\r
35889     P1, P2: TPoint;\r
35890     ClientOnly: Boolean;\r
35891     OldPaintDC: HDC;\r
35892 {$IFDEF DEBUGDBLBUFF}\r
35893 Tmp: PBitmap;\r
35894 {$ENDIF}\r
35895 begin\r
35896   if not GetUpdateRect( Sender.fHandle, R, FALSE ) then\r
35897     Exit; // nothing to paint\r
35899   Sender.fDblBufPainting := TRUE;\r
35901   ClientOnly := Sender.fIsForm {and (WinVer < wvNT)};\r
35902   if ClientOnly then\r
35903     GetClientRect( Sender.fHandle, R )\r
35904   else\r
35905   begin\r
35906     GetWindowRect( Sender.fHandle, R );\r
35907     OffsetRect( R, -R.Left, -R.Top );\r
35908   end;\r
35910   DC0 := GetDC( Sender.fHandle );\r
35911   DC1 := CreateCompatibleDC( DC0 );\r
35912   if Sender.fDblBufBmp = 0 then\r
35913     Sender.Add2AutoFreeEx( TObjectMethod( MakeMethod( Sender, @ DoReleaseDblBufBmp ) ) );\r
35914   if (Sender.fDblBufW < R.Right) or (Sender.fDblBufH < R.Bottom) or\r
35915      (Sender.fDblBufW > R.Right + 32) or (Sender.fDblBufH > R.Bottom + 32) then\r
35916     if Sender.fDblBufBmp <> 0 then\r
35917     begin\r
35918       DeleteObject( Sender.fDblBufBmp );\r
35919       Sender.fDblBufBmp := 0;\r
35920     end;\r
35921   if Sender.fDblBufBmp = 0 then\r
35922   begin\r
35923     Sender.fDblBufBmp := CreateCompatibleBitmap( DC0, R.Right, R.Bottom );\r
35924     Sender.fDblBufW := R.Right;\r
35925     Sender.fDblBufH := R.Bottom;\r
35926   end;\r
35927   OldBmp := SelectObject( DC1,  Sender.fDblBufBmp );\r
35929   OldPaintDC := Sender.fPaintDC;\r
35930   Sender.fPaintDC := DC1;\r
35931   if ClientOnly then\r
35932   begin\r
35933     GetClientRect( Sender.fHandle, R2 );\r
35934     P2.x := 0; P2.y := 0;\r
35935     ClientToScreen( Sender.fHandle, P2 );\r
35936     OffsetRect( R2, P2.x, P2.y );\r
35937     SendMessage( Sender.fHandle, WM_ERASEBKGND, DC1, 0 );\r
35938     SendMessage( Sender.fHandle, WM_PAINT, DC1, 0 );\r
35939     DoDrawChildrenDblBuffered( DC1, Sender.fHandle, R2,\r
35940                                GetWindow( Sender.fHandle, GW_CHILD ) );\r
35941   end\r
35942     else\r
35943   begin\r
35944     {Sender.Perform( WM_PRINT, DC1,\r
35945       PRF_CLIENT or PRF_NONCLIENT or PRF_ERASEBKGND or PRF_CHILDREN );}\r
35946     GetWindowRect( Sender.fHandle, R2 );\r
35947     DoDrawChildrenDblBuffered( DC1, Sender.fHandle, R2, Sender.fHandle );\r
35948   end;\r
35949   //Sender.fPaintDC := DC1;\r
35951   DC2 := GetWindowDC( Sender.fHandle );\r
35953   ExcludeCtlsWhichCannotDblBuf( Sender, Sender, DC2 );\r
35955   P1.x := 0; P1.y := 0;\r
35956   if ClientOnly then\r
35957   begin\r
35958     GetWindowRect( Sender.fHandle, R2 );\r
35959     ClientToScreen( Sender.fHandle, P1 );\r
35960     P1.x := P1.x - R2.Left;\r
35961     P1.y := P1.y - R2.Top;\r
35962     GetClientRect( Sender.fHandle, R );\r
35963   end;\r
35964   BitBlt( DC2, P1.x, P1.y, R.Right, R.Bottom, DC1, 0, 0, SRCCOPY );\r
35966 {$IFDEF DEBUGDBLBUFF}\r
35967 Tmp := NewDIBBitmap( R.Right, R.Bottom, pf16bit );\r
35968 BitBlt( Tmp.Canvas.Handle, 0, 0, R.Right, R.Bottom, DC1, 0, 0, SRCCopy );\r
35969 Tmp.SaveToFile( 'c:\tmp.bmp' );\r
35970 Tmp.Free;\r
35971 {$ENDIF}\r
35973   ReleaseDC( Sender.fHandle, DC2 );\r
35975   SelectObject( DC1, OldBmp );\r
35976   DeleteDC( DC1 );\r
35977   ReleaseDC( Sender.fHandle, DC0 );\r
35979   Sender.fPaintDC := OldPaintDC;\r
35980   ValidateRect( Sender.fHandle, nil );\r
35982   Sender.fDblBufPainting := FALSE;\r
35983 end;\r
35985 //[function WndProcBufferedDraw]\r
35986 function WndProcBufferedDraw( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
35987 var Self_DblBufTopParent: PControl;\r
35988 begin\r
35989   Result := False;\r
35990   //if AppletTerminated then Exit;\r
35991   case Msg.message of\r
35992   WM_ERASEBKGND:\r
35993     begin\r
35994       if Self_.fCannotDoubleBuf then Exit;\r
35995       if Self_.DblBufTopParent <> nil then\r
35996         // if the Control is not DoubleBuffered, and none of its Parent controls are\r
35997         // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work\r
35998         // as usual.\r
35999       begin // Call made in WndProcBufferedDraw of the top DoubleBuffered\r
36000             // Parent control, while processing WM_PAINT\r
36001         if Self_.fTransparent\r
36002              // Handle opaque control as usual.\r
36003              // For transparent (child) controls, do nothing at all\r
36004              // in responce to WM_ERASEBKGND (just tell to the system, that\r
36005              // the operation completed).\r
36006         OR\r
36007              // If DoubleBuffered control or control's DoubleBuffered parent\r
36008              // is not painting now through buffer, just ignore the message\r
36009            not Self_.DblBufTopParent.fDblBufPainting\r
36010            then\r
36011         begin\r
36012           if Self_.fParent <> nil then\r
36013           begin\r
36014             Rslt := 1;\r
36015             Result := TRUE;\r
36016             Exit;\r
36017           end;\r
36018         end;\r
36019       end;\r
36020     end;\r
36021   WM_PAINT:\r
36022     begin\r
36023       if Self_.fCannotDoubleBuf then Exit;\r
36024       Self_DblBufTopParent := Self_.DblBufTopParent;\r
36025       if Self_DblBufTopParent = nil then\r
36026         // if the Control is not DoubleBuffered, and none of its Parent controls are\r
36027         // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work\r
36028         // as usual.\r
36029         Exit;\r
36030       if Self_DblBufTopParent <> Self_ then\r
36031         // if one of the Parent controls is DoubleBuffered, than ignore this call\r
36032         // in Global_OnBufferedDraw, and work as usual (actually this allows to\r
36033         // paint children of the DoubleBuffered Parent control to be painted on\r
36034         // its buffer).\r
36035       begin\r
36036         if (not Self_DblBufTopParent.fDblBufPainting) or\r
36037            (Self_DblBufTopParent.fPaintDC = 0) then\r
36038         begin // Usual call. Ignore it.\r
36039           ValidateRect( Self_.fHandle, nil );\r
36040           //RedrawWindow( Self_.fHandle, nil, 0, RDW_VALIDATE ); experiment\r
36041           if not Self_DblBufTopParent.fDblBufPainting then\r
36042           begin\r
36043             Self_.DblBufTopParent.Invalidate;\r
36044             //RedrawWindow( Self_DblBufTopParent.fHandle, nil, 0, RDW_INVALIDATE ); exp.\r
36045             //RedrawWindow( Self_DblBufTopParent.fHandle, nil, 0, RDW_UPDATENOW );  exp.\r
36046           end;\r
36047           Rslt := 0;\r
36048           Result := True;\r
36049         end;\r
36050         Exit; // Call from DoDrawDblBuffered of the top doublebuffered Parent\r
36051       end;\r
36052       if Msg.wParam <> 0 then Exit;\r
36053       DoDrawDblBuffered( Self_ );\r
36054       Rslt := 0;\r
36055       Result := True;\r
36056     end;\r
36057   WM_NCPAINT:\r
36058     begin\r
36059       if Self_.fIsForm {and (WinVer < wvNT)} then Exit;\r
36060       if Self_.CannotDoubleBuf then Exit;\r
36061       Self_DblBufTopParent := Self_.DblBufTopParent;\r
36062       if Self_DblBufTopParent = nil then\r
36063         // if the Control is not DoubleBuffered, and none of its Parent controls are\r
36064         // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work\r
36065         // as usual.\r
36066         Exit;\r
36067       //if Self_.DblBufTopParent <> Self_ then\r
36068         // if one of the Parent controls is DoubleBuffered, than ignore this call\r
36069         // in Global_OnBufferedDraw, and work as usual (actually this allows to\r
36070         // paint children of the DoubleBuffered Parent control to be painted on\r
36071         // its buffer).\r
36072       begin\r
36073         if not Self_DblBufTopParent.fDblBufPainting\r
36074         then\r
36075         begin // Usual call. Ignore it.\r
36076           //ValidateRect( Self_.fHandle, nil );\r
36077           Rslt := 0;\r
36078           Result := True;\r
36079         end;\r
36080       end;\r
36081     end;\r
36082   WM_SETTEXT:\r
36083     begin\r
36084       if Self_.DblBufTopParent = nil then Exit;\r
36085       if not Self_.fIsStaticControl then Exit;\r
36086       ShowWindow( Self_.fHandle, SW_HIDE );\r
36087       Rslt := DefWindowProc( Self_.fHandle, WM_SETTEXT, Msg.wParam, Msg.lParam );\r
36088       ShowWindow( Self_.fHandle, SW_SHOWNA );\r
36089       UpdateWindow( Self_.fHandle ); // necessary!!!\r
36090       Result := True;\r
36091     end;\r
36092   WM_HSCROLL, WM_VSCROLL, WM_WINDOWPOSCHANGED:\r
36093     begin\r
36094       if Self_.DblBufTopParent = nil then Exit;\r
36095       Self_.Invalidate;\r
36096     end;\r
36097   WM_COMMAND:\r
36098     case HiWord( Msg.wParam ) of\r
36099     LBN_SELCHANGE {, CBN_SELCHANGE }:\r
36100       begin\r
36101         if Self_.DblBufTopParent = nil then Exit;\r
36102         Self_.Invalidate;\r
36103       end;\r
36104     end;\r
36105   end;\r
36106 end;\r
36108 const\r
36109   MM_MCINOTIFY        = $3B9;\r
36111 {$IFDEF ASM_VERSION}\r
36113 {$DEFINE ASM_LOCAL}\r
36114 {$IFDEF NEW_MODAL}\r
36115   {$UNDEF ASM_LOCAL}\r
36116 {$ENDIF}\r
36118 {$ELSE}\r
36120 {$IFDEF ASM_LOCAL}\r
36121   {$UNDEF ASM_LOCAL}\r
36122 {$ENDIF}\r
36124 {$ENDIF}\r
36126 {$IFDEF ASM_LOCAL}\r
36127 //[function TControl.WndProc]\r
36128 function TControl.WndProc( var Msg: TMsg ): Integer;\r
36129 asm     //cmd    //opd\r
36130         PUSH     EBX\r
36131         PUSH     ESI\r
36132         PUSH     EDI\r
36133         XCHG     ESI, EAX\r
36134         MOV      EDI, EDX\r
36135         XOR      EAX, EAX\r
36136         CMP      EAX, [EDX].TMsg.hWnd\r
36137         JNE      @@1\r
36138         CMP      EAX, [ESI].TControl.fHandle\r
36139         JNE      @@1\r
36140         MOV      EAX, [EDX].TMsg.hWnd\r
36141         MOV      [ESI].TControl.fHandle, EAX\r
36142 @@1:\r
36143         PUSH     0\r
36144         MOV      ECX, ESP\r
36145         MOV      EAX, ESI\r
36146         CALL     dword ptr [Global_OnBufferedDraw]\r
36147         TEST     AL, AL\r
36148         POP      EAX\r
36149         JNZ      @@pass2defproc\r
36151         CMP      [AppletRunning], 0\r
36152         JZ       @@dyn2\r
36153         MOV      ECX, [Applet]\r
36154         JECXZ    @@dyn2\r
36155         CMP      ECX, ESI\r
36156         JE       @@dyn2\r
36158         CALL     @@onmess\r
36160 @@dyn2: MOV      ECX, ESI\r
36161         CALL     @@onmess\r
36163         MOV      EBX, [ESI].TControl.fOnDynHandlers\r
36164         MOV      EAX, ESI\r
36165         CALL     @@callonmes\r
36167 @@flicksproc:\r
36168         MOV      EAX, ESI\r
36169         MOV      EDX, EDI\r
36170         PUSH     0\r
36171         MOV      ECX, ESP\r
36172         CALL     dword ptr [ESI].TControl.fWndProcResizeFlicks\r
36173         TEST     AL, AL\r
36174         POP      EAX\r
36175         JNZ      @@pass2defproc\r
36177         MOVZX    EAX, word ptr [EDI].TMsg.message\r
36179         //CMP      word ptr [EDI].TMsg.message, WM_CLOSE\r
36180         CMP      AX, WM_CLOSE\r
36181 //********************************************************** Changed By M.Gerasimov\r
36182 //      JNE      @@chk_WM_NCDESTROY\r
36183         JNE      @@chk_WM_DESTROY\r
36184 //********************************************************** Changed By M.Gerasimov\r
36186         MOV      ECX, [ESI].TControl.fOnClose.TMethod.Code\r
36187         JECXZ    @@wm_close1\r
36188         MOV      EBX, ECX\r
36189         PUSH     1\r
36190         MOV      ECX, ESP\r
36191         MOV      EDX, ESI\r
36192         MOV      EAX, [ESI].TControl.fOnClose.TMethod.Data\r
36193         CALL     EBX\r
36194         POP      ECX\r
36195         INC      ECX\r
36196         LOOP     @@wm_close0\r
36197         CMP      [AppletRunning], CL\r
36198         JZ       @@wm_close0\r
36199         //XOR      EAX, EAX\r
36200         //MOV      [ESI].TControl.fModalResult, 0\r
36201         JMP      @@0pass2defproc\r
36203 /////////////////\r
36204 @@onmess:\r
36205         MOV      EAX, [ECX].TControl.fOnMessage.TMethod.Data\r
36206         MOV      EBX, [ECX].TControl.fOnMessage.TMethod.Code\r
36207 @@callonmes:\r
36208         TEST     EBX, EBX\r
36209         JNZ      @@onmess1 // @@dynmes1\r
36210 @@2onmessret:\r
36211         RET\r
36212 @@onmess1:\r
36213         PUSH     0\r
36215         MOV      EDX, EDI\r
36216         MOV      ECX, ESP\r
36217         CALL     EBX\r
36218         TEST     AL, AL\r
36220         POP      EAX\r
36221         JZ       @@2onmessret\r
36222         POP      EDX // pop retaddr\r
36223         JMP      @@pass2defproc\r
36224 /////////////////\r
36226 @@wm_close0:\r
36227         XOR      EAX, EAX\r
36228         MOV      [ESI].TControl.fOnClose.TMethod.Code, EAX\r
36229 @@wm_close1:\r
36230         MOV      EAX, ESI\r
36231         CALL     TControl.IsMainWindow\r
36232         TEST     AL, AL\r
36233         MOV      ECX, [Applet]\r
36234         JNZ      @@wm_close2\r
36235         CMP      ESI, ECX\r
36236         JNE      @@calldef\r
36238 @@wm_close2:\r
36239         JECXZ    @@postquit\r
36240         CMP      ECX, ESI\r
36241         JE       @@postquit\r
36242         PUSH     0\r
36243         PUSH     0\r
36244         PUSH     WM_CLOSE\r
36245         PUSH     ECX\r
36246         CALL     TControl.Perform\r
36247 @@postquit:\r
36248         PUSH     0\r
36249         CALL     PostQuitMessage\r
36250         //XOR      EAX, EAX\r
36251         JMP      @@0pass2defproc\r
36253 //********************************************************** Added By M.Gerasimov\r
36254 //*\r
36255 @@chk_WM_DESTROY:\r
36256         {CMP      word ptr [EDI].TMsg.message, WM_DESTROY\r
36257         JNE      @@chk_WM_NCDESTROY\r
36258         PUSH     GW_CHILD\r
36259         PUSH     [ESI].fHandle\r
36260         CALL     GetWindow\r
36261         TEST     EAX,EAX\r
36262         JZ       @@chk_WM_NCDESTROY\r
36263 @@RmvNext:\r
36264         PUSH     EAX\r
36265         PUSH     offset[ID_PREVPROC]\r
36266         PUSH     EAX\r
36267         CALL     GetProp\r
36268         TEST     EAX,EAX\r
36269         JZ       @@GetNextChild\r
36270         POP      EAX\r
36271         PUSH     EAX\r
36272         PUSH     offset[ID_PREVPROC]\r
36273         PUSH     EAX\r
36274         CALL     RemoveProp\r
36275 @@GetNextChild:\r
36276         POP      EAX\r
36277         PUSH     GW_HWNDNEXT\r
36278         PUSH     EAX\r
36279         CALL     GetWindow\r
36280         TEST     EAX,EAX\r
36281         JNZ       @@RmvNext}\r
36282 //*\r
36283 //********************************************************** Added By M.Gerasimov\r
36284 @@chk_WM_NCDESTROY:\r
36285         //CMP      word ptr [EDI].TMsg.message, WM_NCDESTROY\r
36286         CMP      AX, WM_NCDESTROY\r
36287         JNE      @@chk_CM_RELEASE\r
36288 //********************************************************** Added By M.Gerasimov\r
36289 //*\r
36290         PUSH     offset[ID_SELF]\r
36291         PUSH     [ESI].fHandle\r
36292         CALL     RemoveProp\r
36293 //*\r
36294 //********************************************************** Added By M.Gerasimov\r
36296         MOV      ECX, [Applet]\r
36297         JECXZ    @@nc_destroy1\r
36298         MOV      EAX, [ESI].TControl.fHandle\r
36299         CMP      EAX, [ECX].TControl.fHandle\r
36300         JE       @@calldef\r
36301 @@nc_destroy1:\r
36302         MOV      EAX, ESI\r
36303         CALL     TControl.IsMainWindow\r
36304         TEST     AL, AL\r
36305         JZ       @@nc_destroy2\r
36306         PUSH     0\r
36307         PUSH     0\r
36308         PUSH     CM_RELEASE\r
36309         PUSH     [ESI].TControl.fHandle\r
36310         CALL     PostMessage\r
36311         JMP      @@calldef\r
36313 @@nc_destroy2:\r
36314         MOV      EAX, [ESI].TControl.fParent\r
36315         CMP      EAX, [Applet]\r
36316         JNE      @@calldef\r
36318         MOV      [ESI].TControl.fNCDestroyed, 1\r
36319 @@do_free:\r
36320         XCHG     EAX, ESI\r
36321         CALL     TObj.Free\r
36323         XOR      EAX, EAX\r
36324         JMP      @@exit // WM_NCDESTROY and CM_RELEASE\r
36325                         // is not a subject to pass it\r
36326                         // to fPass2DefProc\r
36328 @@chk_CM_RELEASE:\r
36329         //CMP      word ptr [EDI].TMsg.message, CM_RELEASE\r
36330         CMP      AX, CM_RELEASE\r
36331         JNE      @@chk_WM_SIZE\r
36333         MOV      [ESI].TControl.fDestroying, 1\r
36334         JMP      @@do_free\r
36336 @@chk_WM_SIZE:\r
36337         //CMP      word ptr [EDI].TMsg.message, WM_SIZE\r
36338         CMP      AX, WM_SIZE\r
36339         JNE      @@chk_WM_SHOWWINDOW\r
36341         MOV      EDX, EDI\r
36342         MOV      EAX, ESI\r
36343         CALL     TControl.CallDefWndProc\r
36344         PUSH     EAX\r
36346         MOV      ECX, [EDI].TMsg.wParam\r
36347         MOV      [ESI].TControl.fWindowState, CL\r
36349         CMP      [ESI].TControl.fIsForm, 0\r
36350         JNZ      @@doGlobalAlignSelf\r
36351         MOV      EAX, [ESI].TControl.fParent\r
36352         TEST     EAX, EAX\r
36353         JZ       @@doGlobalAlignSelf\r
36354         CALL     dword ptr [Global_Align]\r
36355 @@doGlobalAlignSelf:\r
36356         XCHG     EAX, ESI\r
36357         CALL     dword ptr [Global_Align]\r
36359         //POP      EAX\r
36360         JMP      @@popeax_exit\r
36361                         // fPass2DefProc not needed,\r
36362                         // CallDefWndProc already called\r
36364 @@chk_WM_SHOWWINDOW:\r
36365         //CMP      word ptr [EDI].TMsg.message, WM_SHOWWINDOW\r
36366         CMP      AX, WM_SHOWWINDOW\r
36367         JNE      @@chk_WM_SYSCOMMAND\r
36369         MOV      ECX, [EDI].TMsg.lParam\r
36370         LOOP     @@chk_SW_PARENTOPENING\r
36372         PUSH     [ESI].TControl.fHandle\r
36373         CALL     IsIconic\r
36374         XOR      EBX, EBX\r
36375         MOV      BL, SW_SHOWMINNOACTIVE\r
36376         TEST     EAX, EAX\r
36377         JNZ      @@store_action\r
36379         PUSH     [ESI].TControl.fHandle\r
36380         CALL     IsZoomed\r
36381         MOV      BL, SW_SHOWMAXIMIZED\r
36382         TEST     EAX, EAX\r
36383         JNZ      @@store_action\r
36385         MOV      BL, SW_SHOWNOACTIVATE\r
36386 @@store_action:\r
36387         MOV      [ESI].TControl.fShowAction, EBX\r
36388 @@2calldef:\r
36389         JMP      @@calldef\r
36391 @@chk_SW_PARENTOPENING:\r
36392         DEC      ECX\r
36393         LOOP     @@2calldef\r
36395         MOV      ECX, [ESI].TControl.fShowAction\r
36396         JECXZ    @@ret_0\r
36398         PUSH     ECX\r
36399         PUSH     [ESI].TControl.fHandle\r
36400         CALL     ShowWindow\r
36402         XOR      EAX, EAX\r
36403         MOV      [ESI].TControl.fShowAction, EAX\r
36404 @@ret_0:\r
36405         //XOR      EAX, EAX\r
36406         JMP      @@0pass2defproc\r
36408 @@chk_WM_SYSCOMMAND:\r
36409         //CMP      word ptr [EDI].TMsg.message, WM_SYSCOMMAND\r
36410         CMP      AX, WM_SYSCOMMAND\r
36411         JNE      @@chk_WM_SETFOCUS\r
36413         MOV      EAX, [EDI].TMsg.wParam\r
36414         {$IFDEF PARANOIA}\r
36415         DB $24, $F0\r
36416         {$ELSE}\r
36417         AND      AL, $F0\r
36418         {$ENDIF}\r
36419         CMP      AX, SC_MINIMIZE\r
36420         JNE      @@calldef\r
36422         MOV      EAX, ESI\r
36423         CALL     TControl.IsMainWindow\r
36424         TEST     AL, AL\r
36425         JZ       @@calldef\r
36427         CMP      ESI, [Applet]\r
36428         JE       @@calldef\r
36430         PUSH     0\r
36431         PUSH     SC_MINIMIZE\r
36432         PUSH     WM_SYSCOMMAND\r
36433         MOV      EAX, [Applet]\r
36434         PUSH     [EAX].TControl.fHandle\r
36435         CALL     PostMessage\r
36436         JMP      @@ret_0\r
36438 @@chk_WM_SETFOCUS:\r
36439         //CMP      word ptr [EDI].TMsg.message, WM_SETFOCUS\r
36440         CMP      AX, WM_SETFOCUS\r
36441         JNE      @@chk_WM_SETCURSOR\r
36443         MOV      EAX, ESI\r
36444         CALL     TControl.DoSetFocus\r
36445         TEST     AL, AL\r
36446         JZ       @@0pass2defproc\r
36448 //@@calldef_clickdisabled:\r
36449         INC      [ESI].TControl.fClickDisabled\r
36451         MOV      EAX, ESI\r
36452         MOV      EDX, EDI\r
36453         CALL     TControl.CallDefWndProc\r
36455         DEC      [ESI].TControl.fClickDisabled\r
36456         JMP      @@exit\r
36458 @@chk_WM_SETCURSOR:\r
36459         //CMP      word ptr [EDI].TMsg.message, WM_SETCURSOR\r
36460         CMP      AX, WM_SETCURSOR\r
36461         JNE      @@chk_WM_CTLCOLOR\r
36463         CMP      [Global_DisableParentCursor], 0\r
36464         JNE      @@calldef\r
36466         CALL     GetCapture\r
36467         TEST     EAX, EAX\r
36468         JNZ      @@calldef\r
36470         CMP      word ptr [EDI].TMsg.lParam, HTCLIENT\r
36471         JNE      @@calldef\r
36473         MOV      ECX, [ScreenCursor]\r
36474         INC      ECX\r
36475         LOOP     @@setupCursor\r
36477         MOV      ECX, [ESI].TControl.fCursor\r
36478         TEST     ECX, ECX                    //YS\r
36479         JE       @@calldef                   //YS\r
36480 @@setupCursor:\r
36481         PUSH     ECX\r
36482         CALL     Windows.SetCursor\r
36484         MOV      AL, 1\r
36485         JMP      @@exit\r
36487 @@chk_WM_CTLCOLOR:\r
36488         //MOV      EAX, [EDI].TMsg.message\r
36489         MOV      EDX, EAX\r
36490         SUB      DX, WM_CTLCOLORMSGBOX\r
36491         CMP      DX, WM_CTLCOLORSTATIC-WM_CTLCOLORMSGBOX\r
36492         JA       @@chk_WM_COMMAND\r
36494         PUSH     [EDI].TMsg.lParam\r
36495         PUSH     [EDI].TMsg.wParam\r
36496         ADD      AX, CN_BASE //+WM_CTLCOLORMSGBOX\r
36497         PUSH     EAX\r
36498         PUSH     [EDI].TMsg.lParam\r
36499         CALL     SendMessage\r
36500         JMP      @@pass2defproc\r
36502 @@chk_WM_COMMAND:\r
36503         //CMP      word ptr [EDI].TMsg.message, WM_COMMAND\r
36504         CMP      AX, WM_COMMAND\r
36505         JNE      @@chk_WM_KEY\r
36507         PUSH     offset[ID_SELF]\r
36508         PUSH     [EDI].TMsg.lParam\r
36509         CALL     GetProp\r
36510         TEST     EAX, EAX\r
36511         JZ       @@calldef\r
36513         PUSH     [EDI].TMsg.lParam\r
36514         PUSH     [EDI].TMsg.wParam\r
36515         PUSH     CM_COMMAND\r
36516         PUSH     [EDI].TMsg.lParam\r
36517         CALL     SendMessage\r
36518         JMP      @@pass2defproc\r
36520 @@chk_WM_KEY:\r
36521         //MOV      EAX, [EDI].TMsg.message\r
36522         MOV      EDX, EAX\r
36523         SUB      DX, WM_KEYFIRST\r
36524         CMP      DX, WM_KEYLAST-WM_KEYFIRST\r
36525         JA       @@chk_CM_EXECPROC\r
36527         CALL     GetFocus\r
36528         CMP      EAX, [ESI].TControl.fFocusHandle\r
36529         JE       @@in_focus\r
36530         CMP      EAX, [ESI].TControl.fHandle\r
36531         JNE      @@0pass2defproc\r
36533 @@in_focus:\r
36534         PUSH     EAX\r
36536         MOV      ECX, ESP\r
36537         MOV      EDX, EDI\r
36538         MOV      EAX, ESI\r
36539         CALL     dword ptr [fGlobalProcKeybd]\r
36540         TEST     AL, AL\r
36541         JNZ      @@to_exit\r
36543         MOV      ECX, ESP\r
36544         MOV      EDX, EDI\r
36545         MOV      EAX, ESI\r
36546         CALL     [ESI].fWndProcKeybd\r
36547         TEST     AL, AL\r
36548 @@to_exit:\r
36549         POP      EAX\r
36550         JNZ      @@pass2defproc\r
36552         PUSH     VK_CONTROL\r
36553         CALL     GetKeyState\r
36554         XCHG     EBX, EAX\r
36555         PUSH     VK_MENU\r
36556         CALL     GetKeyState\r
36557         OR       EAX, EBX\r
36558         ADD      EAX, EAX\r
36559         JC       @@calldef\r
36561         CMP      word ptr [EDI].TMsg.message, WM_CHAR\r
36562         JNE      @@to_fGotoControl\r
36564         CMP      byte ptr [EDI].TMsg.wParam, 9\r
36565         JE       @@clear_wParam\r
36566         JMP      @@calldef\r
36568 @@to_fGotoControl:\r
36569         MOV      EAX, ESI\r
36570         CALL     TControl.ParentForm\r
36571         TEST     EAX, EAX\r
36572         JZ       @@calldef\r
36574         MOV      ECX, [EAX].fGotoControl\r
36575         JECXZ    @@calldef\r
36577         MOV      EBX, ECX\r
36578         CMP      [EDI].TMsg.message, WM_KEYDOWN\r
36579         SETNE    CL\r
36580         MOV      EDX, [EDI].TMsg.wParam\r
36581         MOV      EAX, ESI\r
36582         CALL     EBX\r
36583         TEST     AL, AL\r
36584         JZ       @@calldef\r
36586 @@clear_wParam:\r
36587         XOR      EAX, EAX\r
36588         MOV      [EDI].TMsg.wParam, EAX\r
36589         JMP      @@pass2defproc\r
36591 @@chk_CM_EXECPROC:\r
36592         //CMP      word ptr [EDI].TMsg.message, CM_EXECPROC\r
36593         CMP      AX, CM_EXECPROC\r
36594         JNE      @@chk_MM_MCINOTIFY\r
36596         MOV      EAX, [EDI].TMsg.lParam\r
36597         MOV      EDX, [EDI].TMsg.wParam\r
36598         CALL     [Global_Synchronized]\r
36599         JMP      @@0pass2defproc\r
36601 @@chk_MM_MCINOTIFY:\r
36602         //CMP      word ptr [EDI].TMsg.message, MM_MCINOTIFY\r
36603         CMP      AX, MM_MCINOTIFY\r
36604         JNE      @@calldef\r
36606         MOV      ECX, [FMMNotify]\r
36607         JECXZ    @@ret_0_MM\r
36609         XCHG     EAX, EDI\r
36610         CALL     ECX\r
36611 @@ret_0_MM:\r
36612         XOR      EAX, EAX\r
36613         JMP      @@exit\r
36615 @@calldef:\r
36616         XCHG     EAX, ESI\r
36617         MOV      EDX, EDI\r
36618         CALL     TControl.CallDefWndProc\r
36619         JMP      @@exit\r
36621 @@0pass2defproc:\r
36622         XOR      EAX, EAX\r
36623 @@pass2defproc:\r
36624         PUSH     EAX\r
36625 @@1pass2defproc:\r
36626         CMP      [AppletTerminated], 0 //\r
36627         JNZ      @@popeax_exit         // uncommented 25-Oct-2003\r
36628         CMP      [ESI].fNCDestroyed, 0 //\r
36629         JNZ      @@popeax_exit         //\r
36631         MOV      ECX, ESP\r
36632         XCHG     EAX, ESI\r
36633         MOV      EDX, EDI\r
36634         CALL     dword ptr[EAX].fPass2DefProc\r
36635 @@popeax_exit:\r
36636         POP      EAX\r
36638 @@exit:\r
36639         POP      EDI\r
36640         POP      ESI\r
36641         POP      EBX\r
36642 end;\r
36643 {$ELSE ASM_LOCAL} //Pascal\r
36645   {$IFDEF DEBUG_CREATEWINDOW}\r
36646   var DbgCWCount: Integer = 0;\r
36647   {$ENDIF DEBUG_CREATEWINDOW}\r
36648 function TControl.WndProc( var Msg: TMsg ): Integer;\r
36649 var Accept: Boolean;\r
36650     C : PControl;\r
36651     F {, Chld}: HWnd;\r
36652     Cur: HCURSOR; // YS\r
36653     PassFun: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
36655     procedure Default;\r
36656     begin\r
36657       Result := CallDefWndProc( Msg );\r
36658     end;\r
36660 begin\r
36661    {$IFDEF DEBUG_CREATEWINDOW}\r
36662    Inc( DbgCWCount );\r
36663    if DbgCWCount < 10 then\r
36664      LogFileOutput( GetStartDir + 'Session.log', 'TControl.WndProc: ' +\r
36665      ' Msg.hwnd=' + Int2Str( Msg.hwnd ) +\r
36666      ' Msg.message=' + Int2Hex( Msg.message, 2 ) +\r
36667      ' Msg.wParam=' + Int2Str( Msg.wParam ) + '=$' + Int2Hex( Msg.wParam, 4 ) +\r
36668      ' Msg.lParam=' + Int2Str( Msg.lParam ) + '=$' + Int2Hex( Msg.lParam, 4 ) );\r
36669    {$ENDIF DEBUG_CREATEWINDOW}\r
36670    if (Msg.hwnd <> 0) and (fHandle = 0) then\r
36671       fHandle := Msg.hwnd;\r
36673    PassFun := fPass2DefProc;\r
36674    if not Global_OnBufferedDraw( @Self, Msg, Result ) then\r
36675    if not (AppletRunning and (Applet <> @Self) and Assigned( Applet ) and\r
36676       Assigned( Applet.OnMessage ) and Applet.OnMessage( Msg, Result )) then\r
36677    if not (Assigned( OnMessage ) and OnMessage( Msg, Result )) then\r
36678    if not fOnDynHandlers( @Self, Msg, Result ) then\r
36679    begin\r
36680      if not fWndProcResizeFlicks( @Self, Msg, Result ) then\r
36681      case Msg.message of\r
36682      {$IFDEF NEW_MODAL}\r
36683      // version of code by Alexander Pravdin\r
36684      WM_CLOSE:\r
36685                 begin\r
36686                   Accept := True;\r
36687                   if Assigned( fOnClose ) then begin\r
36688                     fOnClose( @Self, Accept );\r
36689                     if AppletRunning then\r
36690                       if Accept then\r
36691                         if fModal > 0 then begin\r
36692                           if ModalResult = 0 then\r
36693                             fModalResult := Integer($80000000);\r
36694                           Msg.message := 0;\r
36695                           Exit;\r
36696                         end\r
36697                         else\r
36698                           fOnClose := nil\r
36699                       else begin\r
36700                         Result := 0;\r
36701                         fModalResult := 0;\r
36702                       end\r
36703                     else\r
36704                       fOnClose := nil;\r
36705                   end\r
36706                   else begin\r
36707                     if fModal > 0 then begin\r
36708                       if ModalResult = 0 then\r
36709                         fModalResult := Integer($80000000);\r
36710                       Exit;\r
36711                     end;\r
36712                   end;\r
36714                   if Accept then begin\r
36715                     if IsMainWindow or ( Applet = @Self ) then begin\r
36716                       if Assigned( Applet ) and ( Applet <> @Self ) then\r
36717                         Applet.Perform( WM_CLOSE, 0, 0 );\r
36718                       PostQuitMessage( 0 );\r
36719                       Result := 0;\r
36720                     end\r
36721                     else\r
36722                       Default;\r
36723                   end;\r
36724                 end;\r
36725     {$ELSE}\r
36726      WM_CLOSE: begin\r
36727                   Accept := True;\r
36728                   if Assigned( fOnClose ) then\r
36729                   begin\r
36730                      fOnClose( @Self, Accept );\r
36731                      if (not Accept) and (AppletRunning) then\r
36732                      begin\r
36733                         Result := 0;\r
36734                         //ModalResult := 0;\r
36735                         //Exit; //?????????????????\r
36736                      end\r
36737                        else //+-+\r
36738                      fOnClose := nil;\r
36739                   end;\r
36740                   if Accept then\r
36741                   begin\r
36742                     if IsMainWindow or (Applet = @Self) then\r
36743                     begin\r
36744                        if Assigned( Applet ) and (Applet <> @Self) then\r
36745                           Applet.Perform( WM_CLOSE, 0, 0 );\r
36746                        PostQuitMessage( 0 );\r
36747                        Result := 0;\r
36748                        //Exit; //???????????????\r
36749                     end\r
36750                       else\r
36751                     Default;\r
36752                   end;\r
36753                end;\r
36754      {$ENDIF}\r
36755 {//********************************************************** Added By M.Gerasimov\r
36756 //*\r
36757      WM_DESTROY:\r
36758                begin\r
36759                 Chld := GetWindow( fHandle, GW_CHILD );\r
36760                 while Chld <> 0 do\r
36761                  begin\r
36762                   if GetProp( Chld, ID_PREVPROC ) <> 0 then\r
36763                    RemoveProp(Chld, ID_PREVPROC);\r
36764                    Chld := GetWindow( Chld, GW_HWNDNEXT );\r
36765                  end;\r
36766                end;\r
36767 //*\r
36768 //********************************************************** Added By M.Gerasimov}\r
36769      WM_NCDESTROY:\r
36770                begin\r
36771 //********************************************************** Added By M.Gerasimov\r
36772 //*\r
36773                 RemoveProp( fHandle, ID_SELF );\r
36774 //*\r
36775 //********************************************************** Added By M.Gerasimov\r
36776                 if (Applet = nil) or (Handle <> Applet.Handle) then\r
36777                   begin\r
36778                     if IsMainWindow then\r
36779                      begin\r
36780                       PostMessage( fHandle, CM_RELEASE, 0, 0 );\r
36781                       Default;\r
36782                      end\r
36783                     else\r
36784                      if fParent = Applet then\r
36785                       begin\r
36786                        fNCDestroyed := True;\r
36787                        Free;\r
36788                        Result := 0;\r
36789                        Exit; //!!!!!!!!!!!!!!!!!!!!!!!!!\r
36790                       end\r
36791                      else\r
36792                        Default;\r
36793                   end;\r
36794                end;\r
36796      CM_RELEASE: begin\r
36797                   fDestroying := True;\r
36798                   Free;\r
36799                   Result := 0;\r
36800                   //Exit; //??????????????????????????\r
36801                  end;\r
36803      WM_SIZE:  begin\r
36804                   Default;\r
36805                   case Msg.wParam of\r
36806                     SIZENORMAL: fWindowState := wsNormal;\r
36807                     SIZEICONIC: fWindowState := wsMinimized;\r
36808                     SIZEFULLSCREEN: fWindowState := wsMaximized;\r
36809                   end;\r
36810                   if not fIsForm and (fParent <> nil) then\r
36811                     Global_Align( fParent );\r
36812                   Global_Align( @Self );\r
36813                   Exit;\r
36814                end;\r
36815      WM_SHOWWINDOW:\r
36816                begin\r
36817                   case Msg.lParam of\r
36818                     SW_PARENTCLOSING:\r
36819                        begin\r
36820                           if IsIconic( fHandle ) then\r
36821                              fShowAction := SW_SHOWMINNOACTIVE\r
36822                           else\r
36823                           if IsZoomed( fHandle ) then\r
36824                              fShowAction := SW_SHOWMAXIMIZED\r
36825                           else\r
36826                              fShowAction := SW_SHOWNOACTIVATE;\r
36827                           Default;\r
36828                        end;\r
36829                     SW_PARENTOPENING:\r
36830                        begin\r
36831                           if fShowAction <> 0 then\r
36832                           begin\r
36833                              ShowWindow( Handle, fShowAction );\r
36834                              fShowAction := 0;\r
36835                           end;\r
36836                           Result := 0;\r
36837                           //Exit; //?????????????????????????\r
36838                        end;\r
36839                     else Default;\r
36840                   end;\r
36841                end;\r
36842      WM_SysCommand:\r
36843                begin\r
36844                   if ((Msg.wParam and $FFF0) = SC_MINIMIZE) and\r
36845                      IsMainWindow and (@Self <> Applet) then\r
36846                   begin\r
36847                      PostMessage( Applet.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0 );\r
36848                      Result := 0;\r
36849                      //Exit; //???????????????????????????\r
36850                   end\r
36851                   else Default;\r
36852                end;\r
36853      WM_SETFOCUS:\r
36854                begin\r
36855                  if not DoSetFocus then\r
36856                  begin\r
36857                    Result := 0;\r
36858                    //Exit; //???????????????????????????\r
36859                  end\r
36860                    else\r
36861                  begin\r
36862                    Inc( fClickDisabled );\r
36863                    Default;\r
36864                    Dec( fClickDisabled );\r
36865                    Exit;\r
36866                  end;\r
36867                end;\r
36868      WM_SETCURSOR:\r
36869                if not Global_DisableParentCursor then\r
36870                begin\r
36871                   if (GetCapture = 0) and\r
36872                      (LOWORD( Msg.lParam ) = HTCLIENT) then\r
36873                   begin\r
36874                     if ScreenCursor <> 0 then                  //YS\r
36875                       Cur := ScreenCursor                      //YS\r
36876                     else                                       //YS\r
36877                       Cur := fCursor;                          //YS\r
36878                     if Cur <> 0 then                           //YS\r
36879                     begin                                      //YS\r
36880                       Windows.SetCursor( Cur );                //YS\r
36881                       Result := 1;                             //YS\r
36882                     end                                        //YS\r
36883                     else                                       //YS\r
36884                       Default;                                 //YS\r
36885                     //Exit; //?????????????????????\r
36886                   end\r
36887                   else Default;\r
36888                end\r
36889                else Default;\r
36890      WM_CTLCOLORMSGBOX..WM_CTLCOLORSTATIC:\r
36891      begin\r
36892        Result := SendMessage(Msg.LParam, CN_BASE + Msg.message, Msg.WParam, Msg.LParam);\r
36893        //exit; //???????????????????????\r
36894      end;\r
36895      WM_COMMAND:\r
36896                begin\r
36897                  C := Pointer( GetProp( Msg.lParam, ID_SELF ) );\r
36898                  if C <> nil then\r
36899                  begin\r
36900                    Result := SendMessage( Msg.lParam, CM_COMMAND, Msg.wParam, Msg.lParam );\r
36901                    //Exit; //???????????????????????\r
36902                  end\r
36903                  else Default;\r
36904                end;\r
36905      WM_KEYFIRST..WM_KEYLAST:\r
36906                begin\r
36907                  F := GetFocus;\r
36908                  if (F <> fFocusHandle) and (F <> fHandle) then\r
36909                  begin\r
36910                    Result := 0;\r
36911                    // Jump to PassFun here. Prevents beep in case when WM_KEYDOWN\r
36912                    // called another form and focus is changed, so WM_KEYUP failed\r
36913                    // to handle.\r
36914                  end\r
36915                    else\r
36916                  begin\r
36917                    if fGlobalProcKeybd( @Self, Msg, Result ) then Exit; //??????????????????\r
36918                      //else\r
36919                    if fWndProcKeybd( @Self, Msg, Result ) then Exit; //???????????????????\r
36920                      //else\r
36921                    if ((GetKeystate( VK_CONTROL ) or GetKeyState( VK_MENU )) >= 0) then\r
36922                    begin\r
36923                      //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
36924                      if (Msg.message <> WM_CHAR) // v1.02 Tabulate AND " in EditBox fix\r
36925                      //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
36926                      then\r
36927                      begin\r
36928                        C := ParentForm;\r
36929                        if (C <> nil) and Assigned(C.fGotoControl) and\r
36930                           C.fGotoControl( @Self, Msg.wParam, Msg.message <> WM_KEYDOWN ) then\r
36931                        begin\r
36932                             Msg.wParam := 0;\r
36933                             Result := 0;\r
36934                             //+-+exit;\r
36935                        end\r
36936                        else Default;\r
36937                      end\r
36938                      //+++++++++++++++++++++++++++++++++++++++++++++//\r
36939                        else                                         //\r
36940                      if Msg.wParam = 9 then // prevent system beep  //\r
36941                      begin                                          //\r
36942                         Msg.wParam := 0;                            //\r
36943                         Result := 0;                                //\r
36944                         //+-+exit;                                  //\r
36945                      end                                            //\r
36946                      //+++++++++++++++++++++++++++++++++++++++++++++//\r
36947                      else Default;\r
36948                    end\r
36949                    else Default;\r
36950                  end;\r
36951                end;\r
36952      CM_EXECPROC: begin\r
36953                     Global_Synchronized( Pointer( Msg.lParam ), Pointer( Msg.wParam ) );\r
36954                     Result := 0;\r
36955                     //Exit; //???????????????????\r
36956                   end;\r
36957      MM_MCINOTIFY: begin\r
36958                      if Assigned( FMMNotify ) then\r
36959                         FMMNotify( Msg );\r
36960                      Result := 0;\r
36961                      exit;\r
36962                    end;\r
36963      else  begin\r
36964              Default; //+-+\r
36965              Exit;    //+-+\r
36966            end;\r
36967      end;\r
36968    end;\r
36970    if not AppletTerminated and not fNCDestroyed then\r
36971      PassFun( @Self, Msg, Result ); //+-+\r
36972 end;\r
36973 {$ENDIF ASM_LOCAL}\r
36974 //[END TContro]\r
36976 {$UNDEF ASM_LOCAL}\r
36978 //[procedure SetMouseEvent]\r
36979 procedure SetMouseEvent( Self_: PControl );\r
36980 begin\r
36981   Self_.AttachProc( WndProcMouse );\r
36982 end;\r
36984 //[procedure TControl.SetMouseDown]\r
36985 procedure TControl.SetMouseDown(const Value: TOnMouse);\r
36986 begin\r
36987   fOnMouseDown := Value;\r
36988   SetMouseEvent( @Self );\r
36989 end;\r
36991 //[procedure TControl.SetMouseMove]\r
36992 procedure TControl.SetMouseMove(const Value: TOnMouse);\r
36993 begin\r
36994   fOnMouseMove := Value;\r
36995   SetMouseEvent( @Self );\r
36996 end;\r
36998 //[procedure TControl.SetMouseUp]\r
36999 procedure TControl.SetMouseUp(const Value: TOnMouse);\r
37000 begin\r
37001   fOnMouseUp := Value;\r
37002   SetMouseEvent( @Self );\r
37003 end;\r
37005 //[procedure TControl.SetMouseDblClk]\r
37006 procedure TControl.SetMouseDblClk(const Value: TOnMouse);\r
37007 begin\r
37008   fOnMouseDblClk := Value;\r
37009   SetMouseEvent( @Self );\r
37010 end;\r
37012 //[procedure TControl.SetMouseWheel]\r
37013 procedure TControl.SetMouseWheel(const Value: TOnMouse);\r
37014 begin\r
37015   fOnMouseWheel := Value;\r
37016   SetMouseEvent( @Self );\r
37017 end;\r
37019 {$IFDEF ASM_VERSION}\r
37020 //[procedure TControl.SetClsStyle]\r
37021 procedure TControl.SetClsStyle( Value: DWord );\r
37022 asm     //cmd    //opd\r
37023         CMP      EDX, [EAX].TControl.fClsStyle\r
37024         JE       @@exit\r
37025         MOV      [EAX].TControl.fClsStyle, EDX\r
37026         MOV      ECX, [EAX].TControl.fHandle\r
37027         JECXZ    @@exit\r
37028         PUSH     EDX\r
37029         PUSH     GCL_STYLE\r
37030         PUSH     ECX\r
37031         CALL     SetClassLong\r
37032 @@exit:\r
37033 end;\r
37034 {$ELSE ASM_VERSION} //Pascal\r
37035 procedure TControl.SetClsStyle( Value: DWord );\r
37036 begin\r
37037    if fClsStyle = Value then Exit;\r
37038    fClsStyle := Value;\r
37039    if fHandle = 0 then Exit;\r
37040    SetClassLong( fHandle, GCL_STYLE, Value );\r
37041 end;\r
37042 {$ENDIF ASM_VERSION}\r
37044 {$IFDEF ASM_VERSION}\r
37045 //[procedure TControl.SetStyle]\r
37046 procedure TControl.SetStyle( Value: DWord );\r
37047 const SWP_FLAGS = SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or\r
37048                  SWP_NOZORDER or SWP_FRAMECHANGED;\r
37049 asm\r
37050         CMP      EDX, [EAX].fStyle\r
37051         JZ       @@exit\r
37052         MOV      [EAX].fStyle, EDX\r
37053         MOV      ECX, [EAX].fHandle\r
37054         JECXZ    @@exit\r
37056         PUSH     EAX\r
37058         PUSH     SWP_FLAGS\r
37059         XOR      EAX, EAX\r
37060         PUSH     EAX\r
37061         PUSH     EAX\r
37062         PUSH     EAX\r
37063         PUSH     EAX\r
37064         PUSH     EAX\r
37065         PUSH     ECX\r
37067         PUSH     EDX\r
37068         PUSH     GWL_STYLE\r
37069         PUSH     ECX\r
37070         CALL     SetWindowLong\r
37072         CALL     SetWindowPos\r
37074         POP      EAX\r
37075         CALL     Invalidate\r
37076 @@exit:\r
37077 end;\r
37078 {$ELSE ASM_VERSION} //Pascal\r
37079 procedure TControl.SetStyle( Value: DWord );\r
37080 begin\r
37081    if fStyle = Value then Exit;\r
37082    fStyle := Value;\r
37083    if fHandle = 0 then Exit;\r
37084    SetWindowLong( fHandle, GWL_STYLE, Value );\r
37086    SetWindowPos( fHandle, 0, 0, 0, 0, 0,\r
37087                  SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or\r
37088                  SWP_NOZORDER or SWP_FRAMECHANGED );\r
37089    Invalidate;\r
37090 end;\r
37091 {$ENDIF ASM_VERSION}\r
37093 {$IFDEF ASM_VERSION}\r
37094 //[procedure TControl.SetExStyle]\r
37095 procedure TControl.SetExStyle( Value: DWord );\r
37096 const SWP_FLAGS = SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or\r
37097                  SWP_NOZORDER or SWP_FRAMECHANGED;\r
37098 asm\r
37099         CMP      EDX, [EAX].fExStyle\r
37100         JZ       @@exit\r
37101         MOV      [EAX].fExStyle, EDX\r
37102         MOV      ECX, [EAX].fHandle\r
37103         JECXZ    @@exit\r
37105         PUSH     EAX\r
37107         PUSH     SWP_FLAGS\r
37108         XOR      EAX, EAX\r
37109         PUSH     EAX\r
37110         PUSH     EAX\r
37111         PUSH     EAX\r
37112         PUSH     EAX\r
37113         PUSH     EAX\r
37114         PUSH     ECX\r
37116         PUSH     EDX\r
37117         PUSH     GWL_EXSTYLE\r
37118         PUSH     ECX\r
37119         CALL     SetWindowLong\r
37121         CALL     SetWindowPos\r
37123         POP      EAX\r
37124         CALL     Invalidate\r
37125 @@exit:\r
37126 end;\r
37127 {$ELSE ASM_VERSION} //Pascal\r
37128 procedure TControl.SetExStyle( Value: DWord );\r
37129 begin\r
37130    if fExStyle = Value then Exit;\r
37131    fExStyle := Value;\r
37132    if fHandle = 0 then Exit;\r
37133    SetWindowLong( fHandle, GWL_EXSTYLE, Value );\r
37135    SetWindowPos( fHandle, 0, 0, 0, 0, 0,\r
37136                  SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or\r
37137                  SWP_NOZORDER or SWP_FRAMECHANGED );\r
37138    Invalidate;\r
37139 end;\r
37140 {$ENDIF ASM_VERSION}\r
37142 {$IFDEF ASM_VERSION}\r
37143 //[procedure TControl.SetCursor]\r
37144 procedure TControl.SetCursor( Value: HCursor );\r
37145 asm     //cmd    //opd\r
37146         CMP      EDX, [EAX].TControl.fCursor\r
37147         JE       @@exit\r
37148         MOV      [EAX].TControl.fCursor, EDX\r
37149         MOV      ECX, [EAX].TControl.fHandle\r
37150         JECXZ    @@exit\r
37151         TEST     EDX, EDX                      //YS\r
37152         JE       @@exit                        //YS\r
37153         MOV      ECX, [ScreenCursor]\r
37154         INC      ECX\r
37155         LOOP     @@exit\r
37157         PUSH     EBX\r
37158         XCHG     EBX, EAX\r
37159         PUSH     EDX\r
37160         PUSH     EAX\r
37161         PUSH     EAX\r
37162         PUSH     ESP\r
37163         CALL     GetCursorPos\r
37164         MOV      EDX, ESP\r
37165         MOV      ECX, EDX\r
37166         MOV      EAX, EBX\r
37167         CALL     Screen2Client\r
37168         ADD      ESP, -16\r
37169         MOV      EDX, ESP\r
37170         MOV      EAX, EBX\r
37171         CALL     TControl.ClientRect\r
37172         MOV      EDX, ESP\r
37173         LEA      EAX, [ESP+16]\r
37174         CALL     PointInRect\r
37175         ADD      ESP, 24\r
37176         TEST     AL, AL\r
37177         JZ       @@fin\r
37178         CALL     Windows.SetCursor\r
37179         PUSH     EAX\r
37180 @@fin:  POP      EAX\r
37181         POP      EBX\r
37182 @@exit:\r
37183 end;\r
37184 {$ELSE ASM_VERSION} //Pascal\r
37185 procedure TControl.SetCursor( Value: HCursor );\r
37186 var P: TPoint;\r
37187 begin\r
37188    if fCursor = Value then Exit;\r
37189    fCursor := Value;\r
37190    if (fHandle = 0) or (fCursor = 0) then Exit;        //YS\r
37191    if ScreenCursor <> 0 then Exit;\r
37192    GetCursorPos( P );\r
37193    P := Screen2Client( P );\r
37194    if PointInRect( P, ClientRect ) then\r
37195    Windows.SetCursor( Value );\r
37196 end;\r
37197 {$ENDIF ASM_VERSION}\r
37199 //[procedure TControl.CursorLoad]\r
37200 procedure TControl.CursorLoad(Inst: Integer; ResName: PChar);\r
37201 begin\r
37202   Cursor := LoadCursor( Inst, ResName );\r
37203   fCursorShared := TRUE;\r
37204 end;\r
37206 {$IFDEF ASM_VERSION}\r
37207 //[procedure TControl.SetIcon]\r
37208 procedure TControl.SetIcon( Value: HIcon );\r
37209 asm     //cmd    //opd\r
37210         CMP      EDX, [EAX].TControl.fIcon\r
37211         JE       @@exit\r
37212         MOV      [EAX].TControl.fIcon, EDX\r
37213         INC      EDX\r
37214         JZ       @@1\r
37215         DEC      EDX\r
37216 @@1:\r
37217         PUSH     EDX\r
37218         PUSH     1 //ICON_BIG\r
37219         PUSH     WM_SETICON\r
37220         PUSH     EAX\r
37221         CALL     Perform\r
37222         TEST     EAX, EAX\r
37223         JZ       @@exit\r
37224         PUSH     EAX\r
37225         CALL     DestroyIcon\r
37226 @@exit:\r
37227 end;\r
37228 {$ELSE ASM_VERSION} //Pascal\r
37229 procedure TControl.SetIcon( Value: HIcon );\r
37230 var OldIco: HIcon;\r
37231 begin\r
37232    if fIcon = Value then Exit;\r
37233    fIcon := Value;\r
37234    if Value = THandle(-1) then\r
37235      Value := 0;\r
37236    OldIco := Perform( WM_SETICON, 1 {ICON_BIG}, Value );\r
37237    if OldIco <> 0 then\r
37238      DestroyIcon( OldIco );\r
37239 end;\r
37240 {$ENDIF ASM_VERSION}\r
37242 {$IFDEF ASM_VERSION}\r
37243 //[procedure TControl.SetMenu]\r
37244 procedure TControl.SetMenu( Value: HMenu );\r
37245 asm\r
37246         PUSH     EBX\r
37247         XCHG     EBX, EAX\r
37248         CMP      [EBX].fMenu, EDX\r
37249         JZ       @@exit\r
37250         PUSH     EDX\r
37251         MOV      ECX, [EBX].fMenuObj\r
37252         JECXZ    @@no_free_menuctl\r
37253         XCHG     EAX, EDX\r
37254         CALL     TObj.Free\r
37255 @@no_free_menuctl:\r
37256         MOV      ECX, [EBX].fMenu\r
37257         JECXZ    @@no_destroy\r
37258         PUSH     ECX\r
37259         CALL     DestroyMenu\r
37260 @@no_destroy:\r
37261         POP      EDX\r
37262         MOV      [EBX].fMenu, EDX\r
37263         MOV      ECX, [EBX].fHandle\r
37264         JECXZ    @@exit\r
37265         PUSH     EDX\r
37266         PUSH     ECX\r
37267         CALL     Windows.SetMenu\r
37268 @@exit:\r
37269         POP      EBX\r
37270 end;\r
37271 {$ELSE ASM_VERSION} //Pascal\r
37272 procedure TControl.SetMenu( Value: HMenu );\r
37273 begin\r
37274   if fMenu = Value then Exit;\r
37275   if fMenuObj <> nil then\r
37276      fMenuObj.Free;\r
37277   if fMenu <> 0 then\r
37278      DestroyMenu( fMenu );\r
37279   fMenu := Value;\r
37280   if fHandle = 0 then Exit;\r
37281   Windows.SetMenu( fHandle, Value );\r
37282 end;\r
37283 {$ENDIF ASM_VERSION}\r
37285 //[procedure CallWinHelp]\r
37286 procedure CallWinHelp( Context: Integer; CtxCtl: PControl );\r
37287 var Cmd: Integer;\r
37288     Form: PControl;\r
37289     Popup: Boolean;\r
37290 begin\r
37291   Cmd := HELP_CONTEXT;\r
37292   if CtxCtl <> nil then\r
37293   begin\r
37294     Form := CtxCtl.ParentForm;\r
37295     if Form <> nil then\r
37296     if Assigned( Form.OnHelp ) then\r
37297     begin\r
37298       Popup := FALSE;\r
37299       Form.OnHelp( CtxCtl, Context, Popup );\r
37300       if Popup then\r
37301         Cmd := HELP_CONTEXTPOPUP;\r
37302       if CtxCtl = nil then Exit;\r
37303     end;\r
37304   end\r
37305     else\r
37306   if Context = 0 then\r
37307     Cmd := HELP_CONTENTS;\r
37308   WinHelp( Applet.Handle, PChar( Applet.GetHelpPath ), Cmd, Context );\r
37309 end;\r
37311 var HHCtrl: THandle;\r
37312     HtmlHelp: procedure( Wnd: HWnd; Path: PChar; Cmd, Data: Integer ); stdcall;\r
37314 //[procedure HtmlHelpCommand]\r
37315 procedure HtmlHelpCommand( Wnd: HWnd; const HelpFilePath: String; Cmd, Data: Integer );\r
37316 begin\r
37317   if HHCtrl = 0 then\r
37318     HHCtrl := LoadLibrary( 'HHCTRL.OCX' );\r
37319   if HHCtrl = 0 then Exit;\r
37320   if not Assigned( HtmlHelp ) then\r
37321     HtmlHelp := GetProcAddress( HHCtrl, 'HtmlHelpA' );\r
37322   if not Assigned( HtmlHelp ) then Exit;\r
37323   HtmlHelp( Wnd, PChar( HelpFilePath ), Cmd, Data );\r
37324 end;\r
37326 //[procedure CallHtmlHelp]\r
37327 procedure CallHtmlHelp( Context: Integer; CtxCtl: PControl );\r
37328 var Cmd: Integer;\r
37329     Form: PControl;\r
37330     Popup: Boolean;\r
37331     Ids: array[ 0..2 ] of DWORD;\r
37332 begin\r
37334   Cmd := $F; // HH_HELP_CONTEXT;\r
37335   if CtxCtl <> nil then\r
37336   begin\r
37337     Form := CtxCtl.ParentForm;\r
37338     if Form <> nil then\r
37339     if Assigned( Form.OnHelp ) then\r
37340     begin\r
37341       Popup := FALSE;\r
37342       Form.OnHelp( CtxCtl, Context, Popup );\r
37343       if Popup then\r
37344       begin\r
37345         Cmd := $10; //HH_TP_HELPCONTEXTMENU;\r
37346         Ids[ 0 ] := CtxCtl.fMenu;\r
37347         Ids[ 1 ] := Context;\r
37348         Ids[ 2 ] := 0;\r
37349         Context := Integer( @ Ids );\r
37350       end;\r
37351       if CtxCtl = nil then Exit;\r
37352     end;\r
37353   end\r
37354     else\r
37355   if Context = 0 then\r
37356     Cmd := 1; // HH_DISPLAY_TOC;\r
37357   HtmlHelpCommand( Applet.Handle, HelpFilePath, Cmd, Context );\r
37358 end;\r
37360 var\r
37361   Global_HelpProc: procedure( Context: Integer; CtxCtl: PControl ) = CallWinHelp;\r
37363 //[function WndProcHelp]\r
37364 function WndProcHelp( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
37365 var HI: PHelpInfo;\r
37366     Ctx: Integer;\r
37367     Ctl: PControl;\r
37368 begin\r
37369   Result := FALSE;\r
37370   if Msg.message = WM_HELP then\r
37371   begin\r
37372     Ctx := 0;\r
37373     Ctl := nil;\r
37374     HI := Pointer( Msg.lParam );\r
37375     if HI.iContextType = HELPINFO_WINDOW then\r
37376     begin\r
37377       Ctl := Pointer( GetProp( HI.hItemHandle, ID_SELF ) );\r
37378       while Ctl <> nil do\r
37379       begin\r
37380         Ctx := Ctl.fHelpContext;\r
37381         if Ctx <> 0 then break;\r
37382         Ctl := Ctl.Parent;\r
37383       end;\r
37384     end\r
37385       else\r
37386     //if HI.iContextType = HELPINFO_MENUITEM then\r
37387       Ctx := GetMenuContextHelpID( HI.hItemHandle );\r
37388     Applet.CallHelp( Ctx, Ctl );\r
37389     Rslt := 1;\r
37390     Result := TRUE;\r
37391   end\r
37392   {$IFDEF AUTO_CONTEXT_HELP}\r
37393     else\r
37394   if (Msg.message = WM_CONTEXTMENU) then\r
37395   begin\r
37396     Ctl := Pointer( GetProp( Msg.wParam, ID_SELF ) );\r
37397     if (Ctl <> nil) and (Ctl.fHelpContext <> 0) then\r
37398     //if (Ctl.fAutoPopupMenu = nil) then // seems not working\r
37399     begin\r
37400       Applet.CallHelp( Ctl.fHelpContext, Ctl );\r
37401       Rslt := 1;\r
37402       Result := TRUE;\r
37403     end;\r
37404   end\r
37405   {$ENDIF}\r
37406      ;\r
37407 end;\r
37409 //[procedure TControl.SetHelpContext]\r
37410 procedure TControl.SetHelpContext(Value: Integer);\r
37411 var F: PControl;\r
37412 begin\r
37413   fHelpContext := Value;\r
37414   F := ParentForm;\r
37415   if F = nil then Exit;\r
37416   F.AttachProc( WndProcHelp );\r
37417   SetWindowContextHelpId( GetWindowHandle, Value );\r
37418 end;\r
37420 //[function TControl.AssignHelpContext]\r
37421 function TControl.AssignHelpContext(Context: Integer): PControl;\r
37422 begin\r
37423   SetHelpContext( Context );\r
37424   Result := @ Self;\r
37425 end;\r
37427 //[procedure AssignHtmlHelp]\r
37428 procedure AssignHtmlHelp( const HtmlHelpPath: String );\r
37429 begin\r
37430   Assert( (HtmlHelpPath <> '') and (Applet <> nil), 'Error parameters' );\r
37431   if HelpFilePath <> '' then\r
37432     FreeMem( HelpFilePath );\r
37433   GetMem( HelpFilePath, Length( HtmlHelpPath ) + 1 );\r
37434   StrCopy( HelpFilePath, @ HtmlHelpPath[ 1 ] );\r
37435   Global_HelpProc := CallHtmlHelp;\r
37436   Applet.AttachProc( WndProcHelp );\r
37437 end;\r
37439 //[procedure TControl.CallHelp]\r
37440 procedure TControl.CallHelp(Context: Integer; CtxCtl: PControl {; CtlID: Integer} );\r
37441 begin\r
37442   Global_HelpProc( Context, CtxCtl {, CtlID} );\r
37443 end;\r
37445 //[function TControl.GetHelpPath]\r
37446 function TControl.GetHelpPath: String;\r
37447 begin\r
37448   Result := HelpFilePath;\r
37449   if Result = '' then\r
37450   begin\r
37451     Result := ParamStr( 0 );\r
37452     Result := ReplaceFileExt( Result, '.hlp' );\r
37453   end;\r
37454 end;\r
37456 //[procedure TControl.SetHelpPath]\r
37457 procedure TControl.SetHelpPath(const Value: String);\r
37458 begin\r
37459   Assert( Value <> '', 'Error parameter' );\r
37460   if HelpFilePath <> '' then\r
37461     FreeMem( HelpFilePath );\r
37462   GetMem( HelpFilePath, Length( Value ) + 1 );\r
37463   StrCopy( HelpFilePath, @ Value[ 1 ] );\r
37464 end;\r
37466 {$IFDEF ASM_VERSION}\r
37467 //[function TControl.GetCaption]\r
37468 function TControl.GetCaption: String;\r
37469 asm\r
37470         XCHG      EAX, EDX\r
37471         MOVZX     ECX, [EDX].fIgnoreWndCaption\r
37472         JECXZ     @@getwndcaption\r
37474 @@ret_fCaption:\r
37475         MOV       EDX, [EDX].fCaption\r
37476         JMP       System.@LStrFromPChar\r
37478 @@getwndcaption:\r
37479         MOV       ECX, [EDX].fHandle\r
37480         JECXZ     @@ret_fCaption\r
37482         PUSH      EBX\r
37483         PUSH      ESI\r
37484         XCHG      EBX, EAX\r
37486         MOV       ESI, ECX\r
37487         PUSH      ESI\r
37488         CALL      GetWindowTextLength\r
37489         MOV       EDX, EAX\r
37490         INC       EAX\r
37491         PUSH      EAX // MaxLen\r
37493         MOV       EAX, EBX\r
37494         CALL      System.@LStrSetLength\r
37496         POP       EDX\r
37497         MOV       ECX, [EBX]\r
37498         JECXZ     @@exit\r
37499         PUSH      EDX // MaxLen = Length(Result) + 1\r
37501         PUSH      ECX //@Result[1]\r
37502         PUSH      ESI // fHandle\r
37503         CALL      GetWindowText\r
37505 @@exit:\r
37506         POP       ESI\r
37507         POP       EBX\r
37508 end;\r
37509 {$ELSE ASM_VERSION} //Pascal\r
37510 function TControl.GetCaption: String;\r
37511 var Buf: PChar;\r
37512     Sz: Integer;\r
37513 begin\r
37514    if not fIgnoreWndCaption and (FHandle <> 0) then\r
37515    begin\r
37516      Sz := GetWindowTextLength( FHandle );\r
37517      if Sz = 0 then\r
37518         Buf := nil\r
37519      else\r
37520      begin\r
37521        GetMem( Buf, Sz + 1 );\r
37522        GetWindowText( FHandle, Buf, Sz + 1 );\r
37523      end;\r
37524      Result := Buf;\r
37525      if Buf <> nil then\r
37526         FreeMem( Buf );\r
37527      Exit;\r
37528    end;\r
37529    Result := FCaption;\r
37530 end;\r
37531 {$ENDIF ASM_VERSION}\r
37533 {$IFDEF ASM_VERSION}\r
37534 //[procedure TControl.SetCaption]\r
37535 procedure TControl.SetCaption( const Value: String );\r
37536 asm\r
37537         PUSH    EBX\r
37538         XCHG    EBX, EAX\r
37539         PUSH    EDX\r
37540         MOV     EAX, [EBX].fCaption\r
37541         TEST    EAX, EAX\r
37542         JZ      @@store_Caption\r
37543         CALL    System.@FreeMem\r
37544 @@store_Caption:\r
37545         POP     EAX\r
37546         CALL    EAX2PChar\r
37547         PUSH    EAX\r
37548         CALL    StrLen\r
37549         INC     EAX\r
37550         CALL    System.@GetMem\r
37551         MOV     [EBX].fCaption, EAX\r
37552         POP     EDX\r
37553         CALL    StrCopy\r
37554         MOV     ECX, [EBX].fHandle\r
37555         JECXZ   @@exit\r
37556         PUSH    [EBX].fCaption\r
37557         PUSH    ECX\r
37558         CALL    SetWindowText\r
37559         CMP     [EBX].fIsStaticControl, 0\r
37560         JZ      @@1\r
37561         MOV     EAX, EBX\r
37562         CALL    Invalidate\r
37563 @@1:\r
37564         XCHG    EAX, EBX\r
37565         MOV     ECX, [EAX].fAutoSize\r
37566         JECXZ   @@exit\r
37567         CALL    ECX\r
37568 @@exit: POP     EBX\r
37569 end;\r
37570 {$ELSE ASM_VERSION} //Pascal\r
37571 procedure TControl.SetCaption( const Value: String );\r
37572 var L: DWORD;\r
37573 begin\r
37574   //if fHandle = 0 then\r
37575   begin\r
37576     if fCaption <> nil then\r
37577        FreeMem( fCaption );\r
37578     L := Length( Value ) + 1;\r
37579     GetMem( fCaption, L );\r
37580     StrCopy( fCaption, PChar( Value ) );\r
37581     //Exit;\r
37582   end;\r
37583   if fHandle = 0 then Exit;\r
37584   SetWindowText( fHandle, @Value[ 1 ] );\r
37585   if not fIsStaticControl then\r
37586     Invalidate;\r
37587   if Assigned( fAutoSize ) then\r
37588     fAutoSize( @Self );\r
37589 end;\r
37590 {$ENDIF ASM_VERSION}\r
37592 {$IFDEF ASM_VERSION}\r
37593 //[function TControl.GetVisible]\r
37594 function TControl.GetVisible: Boolean;\r
37595 asm\r
37596         MOV     ECX, [EAX].fHandle\r
37597         JECXZ   @@check_fStyle\r
37599         {CMP     [EAX].fIsControl, 0\r
37600         JNE     @@check_fStyle}\r
37602           PUSH  EAX\r
37603         PUSH    ECX\r
37604         CALL    IsWindowVisible\r
37605         TEST    EAX, EAX\r
37606           POP   EAX\r
37607         JMP     @@checked // Z if not visible\r
37609 @@check_fStyle:\r
37610         TEST    byte ptr [EAX].fStyle+3, 10h // WS_VISIBLE shr 3\r
37611 @@checked:\r
37612         SETNZ   DL\r
37613         MOV     [EAX].fVisible, DL\r
37614         XCHG    EAX, EDX\r
37615 end;\r
37616 {$ELSE ASM_VERSION}\r
37617 function TControl.GetVisible: Boolean;\r
37618 begin\r
37619    if (fHandle <> 0)\r
37620       //and (not fIsControl or (ParentForm <> nil) and ParentForm.Visible)\r
37621       //and not fIsControl\r
37622    then\r
37623       fVisible :=\r
37624         //LongBool( GetWindowLong( fHandle, GWL_STYLE ) and WS_VISIBLE )\r
37625         IsWindowVisible( fHandle )\r
37626    else\r
37627       fVisible := (FStyle and WS_VISIBLE) <> 0;\r
37628    Result := fVisible;\r
37629 end;\r
37630 {$ENDIF ASM_VERSION}\r
37632 {$IFDEF ASM_VERSION}\r
37633 //[function TControl.Get_Visible]\r
37634 function TControl.Get_Visible: Boolean;\r
37635 asm     //     //\r
37636         MOV    ECX, [EAX].fHandle\r
37637         JECXZ  @@ret_fVisible\r
37638         CMP    [EAX].fIsControl, 0\r
37639         JNZ    @@ret_fVisible\r
37640         PUSH   EAX\r
37641         PUSH   ECX\r
37642         CALL   IsWindowVisible\r
37643         XCHG   EDX, EAX\r
37644         POP    EAX\r
37645         MOV    [EAX].fVisible, DL\r
37646 @@ret_fVisible:\r
37647         MOVZX  EAX, [EAX].fVisible\r
37648 end;\r
37649 {$ELSE ASM_VERSION} // Pascal\r
37650 function TControl.Get_Visible: Boolean;\r
37651 begin\r
37652    if (fHandle <> 0)\r
37653       //and (not fIsControl or (ParentForm <> nil) and ParentForm.Visible)\r
37654       and not fIsControl\r
37655    then\r
37656       fVisible :=\r
37657         //LongBool( GetWindowLong( fHandle, GWL_STYLE ) and WS_VISIBLE )\r
37658         IsWindowVisible( fHandle );\r
37659    Result := fVisible;\r
37660 end;\r
37661 {$ENDIF ASM_VERSION}\r
37663 {$IFDEF ASM_VERSION}\r
37664 //[procedure TControl.Set_Visible]\r
37665 procedure TControl.Set_Visible( Value: Boolean );\r
37666 const wsVisible = $10;\r
37667 asm\r
37668         PUSH     EBX\r
37669         PUSH     ESI\r
37670         //MOV      ESI, EAX\r
37671         XCHG     ESI, EAX\r
37672         MOVZX    EBX, DL\r
37673         {CALL     Get_Visible\r
37674         CMP      AL, BL\r
37675         JE       @@reset_fCreateHidden}\r
37677         MOV      AL, byte ptr [ESI].fStyle + 3\r
37678         TEST     EBX, EBX\r
37679         JZ       @@reset_WS_VISIBLE\r
37680         OR       AL, wsVisible\r
37681         PUSH     SW_SHOW\r
37682         JMP      @@store_Visible\r
37683 @@reset_WS_VISIBLE:\r
37684         AND      AL, not wsVisible\r
37685         PUSH     SW_HIDE\r
37687 @@store_Visible:\r
37688         MOV      byte ptr [ESI].fStyle + 3, AL\r
37689         MOV      [ESI].fVisible, BL\r
37690         MOV      ECX, [ESI].fHandle\r
37691         JECXZ    @@after_showwindow\r
37693         PUSH     ECX\r
37694         CALL     ShowWindow\r
37695         PUSH     ECX\r
37696 @@after_showwindow:\r
37697         POP      ECX\r
37699         MOV      ECX, [ESI].fParent\r
37700         JECXZ    @@chk_align_Self\r
37701         XCHG     EAX, ECX\r
37702         CALL     dword ptr [Global_Align]\r
37704 @@chk_align_Self:\r
37705         TEST     EBX, EBX\r
37706         JZ       @@reset_fCreateHidden\r
37707         MOV      EAX, ESI\r
37708         CALL     dword ptr [Global_Align]\r
37711 @@reset_fCreateHidden:\r
37712         MOV      ECX, [ESI].fHandle\r
37713         JECXZ    @@exit\r
37714         TEST     BL, BL\r
37715         JNZ      @@exit\r
37716         MOV      [ESI].fCreateHidden, 0 { +++ }\r
37717 @@exit:\r
37718         POP      ESI\r
37719         POP      EBX\r
37720 end;\r
37721 {$ELSE ASM_VERSION} // Pascal\r
37722 procedure TControl.Set_Visible( Value: Boolean );\r
37723 var CmdShow: DWORD;\r
37724 begin\r
37725    //if Get_Visible <> Value then // commented to allow to set up controls visibility\r
37726    begin                          // on invisible form (Vladimir Piven)\r
37727      if Value then\r
37728      begin\r
37729        fStyle := fStyle or WS_VISIBLE;\r
37730        CmdShow := SW_SHOW;\r
37731      end\r
37732         else\r
37733      begin\r
37734        fStyle := fStyle and not WS_VISIBLE;\r
37735        CmdShow := SW_HIDE;\r
37736      end;\r
37737      fVisible := Value;\r
37738      if fHandle = 0 then Exit;\r
37739      ShowWindow( fHandle, CmdShow );\r
37740      if fParent <> nil then\r
37741        Global_Align( fParent );\r
37742      //else\r
37743      if Value then\r
37744        Global_Align( @Self );\r
37745    end;\r
37746    if not Value and (fHandle <> 0) then\r
37747      fCreateHidden := FALSE; // { +++ }\r
37748 end;\r
37749 {$ENDIF ASM_VERSION}\r
37751 //[procedure TControl.SetVisible]\r
37752 procedure TControl.SetVisible( Value: Boolean );\r
37753 begin\r
37754    fCreateVisible := TRUE;\r
37755    Set_Visible( Value );\r
37756 end;\r
37758 {$IFDEF ASM_VERSION}\r
37759 //[function TControl.GetBoundsRect]\r
37760 function TControl.GetBoundsRect: TRect;\r
37761 asm\r
37762         PUSH      ESI\r
37763         PUSH      EDI\r
37764         LEA       ESI, [EAX].fBoundsRect\r
37765         MOV       EDI, EDX\r
37767         PUSH      EDX\r
37769         MOVSD\r
37770         MOVSD\r
37771         MOVSD\r
37772         MOVSD\r
37774         POP       EDI\r
37776         XCHG      ESI, EAX\r
37777         MOV       ECX, [ESI].fHandle\r
37778         JECXZ     @@exit\r
37780         PUSH      EDI\r
37781         PUSH      ECX\r
37782         CALL      GetWindowRect\r
37784         CMP       [ESI].fIsControl, 0\r
37785         JZ        @@storeBounds\r
37787         MOV       EAX, [ESI].fParent\r
37789         TEST      EAX, EAX\r
37790         JZ        @@exit\r
37792         XOR       EDX, EDX\r
37793         PUSH      EDX\r
37794         PUSH      EDX\r
37795         MOV       ECX, ESP\r
37796         PUSH      EDX\r
37797         PUSH      EDX\r
37798         MOV       EDX, ESP\r
37799         CALL      TControl.Client2Screen\r
37800         POP       EAX\r
37801         POP       EAX\r
37803         POP       EAX\r
37804         NEG       EAX\r
37805         POP       ECX\r
37806         NEG       ECX\r
37807         PUSH      ECX\r
37808         PUSH      EAX\r
37809         PUSH      EDI\r
37810         CALL      OffsetRect\r
37812 @@storeBounds:\r
37813         XCHG      ESI, EDI\r
37814         LEA       EDI, [EDI].fBoundsRect\r
37815         MOVSD\r
37816         MOVSD\r
37817         MOVSD\r
37818         MOVSD\r
37820 @@exit:\r
37821         POP       EDI\r
37822         POP       ESI\r
37823 end;\r
37824 {$ELSE ASM_VERSION} //Pascal\r
37825 function TControl.GetBoundsRect: TRect;\r
37826 var W: PControl;\r
37827     P: TPoint;\r
37828 begin\r
37829    Result := fBoundsRect;\r
37830    if fHandle <> 0 then\r
37831    begin\r
37832       GetWindowRect( fHandle, Result );\r
37833       if fIsControl then\r
37834       begin\r
37835         W := fParent; // WindowedParent;\r
37836         if W <> nil then\r
37837         begin\r
37838           P.x := 0; P.y := 0;\r
37839           P := W.Client2Screen( P );\r
37840           OffsetRect( Result, -P.x, -P.y );\r
37841         end;\r
37842       end;\r
37843       fBoundsRect := Result;\r
37844    end;\r
37845 end;\r
37846 {$ENDIF ASM_VERSION}\r
37848 //[PROCEDURE HelpGetBoundsRect]\r
37849 {$IFDEF ASM_VERSION}\r
37850 procedure HelpGetBoundsRect;\r
37851 asm\r
37852         POP       ECX\r
37853         ADD       ESP, - size_TRect\r
37854         MOV       EDX, ESP\r
37855         PUSH      ECX\r
37856         PUSH      EAX\r
37857         CALL      TControl.GetBoundsRect\r
37858         POP       EAX\r
37859 end;\r
37860 {$ENDIF ASM_VERSION}\r
37861 //[END HelpGetBoundsRect]\r
37863 {$IFDEF ASM_VERSION}\r
37864 //[procedure TControl.SetBoundsRect]\r
37865 procedure TControl.SetBoundsRect( const Value: TRect );\r
37866 const swp_flags = SWP_NOZORDER or SWP_NOACTIVATE;\r
37867 asm\r
37868         PUSH      EDI\r
37869         MOV       EDI, EAX\r
37871         PUSH      ESI\r
37872         MOV       ESI, EDX\r
37874         CALL      HelpGetBoundsRect\r
37876         MOV       EAX, ESI\r
37877         MOV       EDX, ESP\r
37878         CALL      RectsEqual\r
37879         TEST      AL, AL\r
37880         JNZ       @@exit\r
37882         POP       EDX   // left\r
37883         POP       ECX   // top\r
37884         POP       EAX   // right\r
37885         PUSH      EAX\r
37886         PUSH      ECX\r
37887         PUSH      EDX\r
37889         SUB       EAX, EDX  // EAX = width\r
37890         CMP       EDX, [ESI].TRect.Left\r
37891         MOV       DL, 0\r
37892         JE        @@1\r
37893         INC       EDX\r
37894 @@1:    CMP       ECX, [ESI].TRect.Top\r
37895         JE        @@2\r
37896         OR        DL, 2\r
37897 @@2:    OR        [EDI].fChangedPosSz, DL\r
37899         PUSH      EAX      // W saved\r
37901         MOV       EAX, [EDI].fBoundsRect.Bottom\r
37902         SUB       EAX, ECX\r
37903         PUSH      EAX      // H saved\r
37905         PUSH      EDI      // @Self saved\r
37907         LEA       EDI, [EDI].fBoundsRect\r
37908         MOVSD\r
37909         MOVSD\r
37910         MOVSD\r
37911         MOVSD\r
37913         MOV       ESI, EDI\r
37914         POP       EDI     // @ Self restored\r
37915         MOV       ECX, [EDI].fHandle\r
37916         JECXZ     @@fin\r
37918         STD\r
37920         PUSH      swp_flags\r
37922         LODSD\r
37923         LODSD\r
37924         XCHG      EDX, EAX // EDX = bottom\r
37925         LODSD\r
37926         XCHG      ECX, EAX // ECX = right\r
37927         LODSD\r
37928         SUB       EDX, EAX // EAX = bottom - top\r
37929         PUSH      EDX       // push HEIGHT\r
37930         XCHG      EDX, EAX  // EDX = top\r
37931         LODSD     // EAX = left\r
37932         CLD\r
37934         SUB       ECX, EAX\r
37935         PUSH      ECX       // push WIDTH\r
37937         PUSH      EDX       // push TOP\r
37938         PUSH      EAX       // push LEFT\r
37939         PUSH      0\r
37941         PUSH      [EDI].fHandle\r
37942         CALL      SetWindowPos\r
37944         CMP       [EDI].fSizeRedraw, 0\r
37945         JE        @@fin\r
37946         XCHG      EAX, EDI\r
37947         CALL      Invalidate  // *MUST* be called?\r
37949 @@fin:\r
37950         POP       EDX       // H restored\r
37951         POP       EAX       // W restored\r
37953 @@exit:\r
37954         ADD       ESP, size_TRect\r
37955         POP       ESI\r
37956         POP       EDI\r
37957 end;\r
37958 {$ELSE ASM_VERSION} //Pascal\r
37959 procedure TControl.SetBoundsRect( const Value: TRect );\r
37960 var Rect: TRect;\r
37961 begin\r
37962    Rect := GetBoundsRect;\r
37963    if RectsEqual( Value, Rect ) then Exit;\r
37964    if Value.Left <> fBoundsRect.Left then fChangedPosSz := fChangedPosSz or 1;\r
37965    if Value.Top  <> fBoundsRect.Top  then fChangedPosSz := fChangedPosSz or 2;\r
37966    fBoundsRect := Value;\r
37967    Rect := Value;\r
37969    if fHandle <> 0 then\r
37970    begin\r
37971      SetWindowPos( fHandle, 0, Rect.Left, Rect.Top, Rect.Right - Rect.Left,\r
37972                    Rect.Bottom - Rect.Top, SWP_NOZORDER or SWP_NOACTIVATE );\r
37973      if fSizeRedraw then\r
37974        Invalidate;\r
37975    end;\r
37976 end;\r
37977 {$ENDIF ASM_VERSION}\r
37979 const\r
37980   WindowStateShowCommands: array[TWindowState] of Byte =\r
37981     (SW_SHOWNOACTIVATE, SW_SHOWMINNOACTIVE, SW_SHOWMAXIMIZED);\r
37982 {$IFDEF ASM_VERSION}\r
37983 //[procedure TControl.SetWindowState]\r
37984 procedure TControl.SetWindowState( Value: TWindowState );\r
37985 asm     //cmd    //opd\r
37986         CMP      [EAX].TControl.fWindowState, DL\r
37987         JE       @@exit\r
37988         MOV      [EAX].TControl.fWindowState, DL\r
37989         XCHG     EAX, EDX\r
37990         CBW\r
37991         CWDE\r
37992         MOV      AL, byte ptr [WindowStateShowCommands+EAX]\r
37993         PUSH     EAX\r
37994         XCHG     EAX, EDX\r
37995         CALL     TControl.GetWindowHandle\r
37996         PUSH     EAX\r
37997         CALL     ShowWindow\r
37998 @@exit:\r
37999 end;\r
38000 {$ELSE ASM_VERSION} //Pascal\r
38001 procedure TControl.SetWindowState( Value: TWindowState );\r
38002 begin\r
38003    if fWindowState <> Value then\r
38004    begin\r
38005       fWindowState := Value;\r
38006       ShowWindow(GetWindowHandle, WindowStateShowCommands[Value]);\r
38007    end;\r
38008 end;\r
38009 {$ENDIF ASM_VERSION}\r
38011 {$IFDEF ASM_VERSION}\r
38012 //[procedure TControl.Show]\r
38013 procedure TControl.Show;\r
38014 asm\r
38015         PUSH     EBX\r
38016         MOV      EBX, EAX\r
38017         CALL     CreateWindow\r
38018         MOV      DL, 1\r
38019         MOV      EAX, EBX\r
38020         CALL     SetVisible\r
38021         PUSH     [EBX].fHandle\r
38022         CALL     SetForegroundWindow\r
38023         XCHG     EAX, EBX\r
38024         CALL     DoSetFocus\r
38025         POP      EBX\r
38026 end;\r
38027 {$ELSE ASM_VERSION} //Pascal\r
38028 procedure TControl.Show;\r
38029 begin\r
38030    CreateWindow;\r
38031    SetVisible( True );\r
38032    SetForegroundWindow( Handle );\r
38033    DoSetFocus;\r
38034 end;\r
38035 {$ENDIF ASM_VERSION}\r
38037 //[procedure TControl.Hide]\r
38038 procedure TControl.Hide;\r
38039 begin\r
38040    SetVisible( False );\r
38041 end;\r
38043 {$IFDEF ASM_VERSION}\r
38044 //[function TControl.Client2Screen]\r
38045 function TControl.Client2Screen( const P: TPoint ): TPoint;\r
38046 asm\r
38047         PUSH      ESI\r
38048         PUSH      EDI\r
38050         MOV       ESI, EDX\r
38051         MOV       EDI, ECX\r
38053         MOVSD\r
38054         MOVSD\r
38056         PUSH      ECX\r
38057         MOV       ECX, [EAX].fHandle\r
38058         JECXZ     @@exit\r
38060         PUSH      ECX\r
38061         CALL      ClientToScreen\r
38062         PUSH      ECX\r
38064 @@exit: POP       ECX\r
38065         POP       EDI\r
38066         POP       ESI\r
38067 end;\r
38068 {$ELSE ASM_VERSION} //Pascal\r
38069 function TControl.Client2Screen( const P: TPoint ): TPoint;\r
38070 begin\r
38071    Result := P;\r
38072    if fHandle <> 0 then\r
38073       Windows.ClientToScreen( fHandle, Result );\r
38074 end;\r
38075 {$ENDIF ASM_VERSION}\r
38077 {$IFDEF ASM_VERSION}\r
38078 //[function TControl.Screen2Client]\r
38079 function TControl.Screen2Client( const P: TPoint ): TPoint;\r
38080 asm\r
38081         PUSH      ESI\r
38082         PUSH      EDI\r
38084         MOV       ESI, EDX\r
38085         MOV       EDI, ECX\r
38087         MOVSD\r
38088         MOVSD\r
38090         PUSH      ECX\r
38091         MOV       ECX, [EAX].fHandle\r
38092         JECXZ     @@exit\r
38094         PUSH      ECX\r
38095         CALL      ScreenToClient\r
38096         PUSH      ECX\r
38098 @@exit: POP       ECX\r
38099         POP       EDI\r
38100         POP       ESI\r
38101 end;\r
38102 {$ELSE ASM_VERSION} //Pascal\r
38103 function TControl.Screen2Client( const P: TPoint ): TPoint;\r
38104 begin\r
38105    Result := P;\r
38106    if Handle <> 0 then\r
38107       Windows.ScreenToClient( Handle, Result );\r
38108 end;\r
38109 {$ENDIF ASM_VERSION}\r
38111 {$IFDEF ASM_VERSION}\r
38112 //[function TControl.ClientRect]\r
38113 function TControl.ClientRect: TRect;\r
38114 asm\r
38115         PUSH      [EAX].fClientLeft\r
38116         PUSH      [EAX].fClientRight\r
38117         PUSH      [EAX].fClientTop\r
38118         PUSH      [EAX].fClientBottom\r
38119         PUSH      EDX\r
38120         PUSH      EDX      // prepare 'dest' for GetClientRect\r
38122           PUSH      EAX\r
38123             LEA       EAX, [EAX].fBoundsRect\r
38125             XOR       ECX, ECX\r
38126             MOV       CL, size_TRect\r
38128             CALL      System.Move\r
38129           POP       EAX  // EAX = @Self\r
38131           CALL      TControl.GetWindowHandle\r
38133           // this version is more correct ?:\r
38134           //------------------------------\r
38135           {PUSH      EAX\r
38136           CALL      CallTControlCreateWindow\r
38137           POP       EAX\r
38138           MOV       EAX, [EAX].fHandle}\r
38139           //-------------------------------\r
38141           TEST      EAX, EAX\r
38142           JZ        @@exit\r
38144           PUSH      EAX    // prepare 'handle' for GetClientRect\r
38145           CALL      GetClientRect\r
38146           PUSH      EAX\r
38148 @@exit: POP       EDX\r
38149         POP       EDX  // EDX = @Result\r
38150         POP       EAX  // EAX = fClientBottom\r
38151         SUB       [EDX].TRect.Bottom, EAX\r
38152         POP       EAX  // EAX = fClientTop\r
38153         ADD       [EDX].TRect.Top, EAX  // Correct Result.Top\r
38154         POP       EAX  // EAX = fClientRight\r
38155         SUB       [EDX].TRect.Right, EAX\r
38156         POP       EAX // EAX = fClientLeft\r
38157         ADD       [EDX].TRect.Left, EAX\r
38158 end;\r
38159 {$ELSE ASM_VERSION} //Pascal\r
38160 function TControl.ClientRect: TRect;\r
38161 const BorderParams: array[ 0..5 ] of DWORD =\r
38162       ( SM_CXBORDER, SM_CXFRAME, SM_CXSIZEFRAME, SM_CYBORDER, SM_CYFRAME, SM_CYSIZEFRAME );\r
38163 begin\r
38164    Result := fBoundsRect;\r
38165    GetWindowHandle;\r
38166    //CreateWindow; //virtual!!!\r
38167    if (fHandle <> 0) then\r
38168       GetClientRect( fHandle, Result );\r
38169    Inc( Result.Top, fClientTop );\r
38170    Dec( Result.Bottom, fClientBottom );\r
38171    Inc( Result.Left, fClientLeft );\r
38172    Dec( Result.Right, fClientRight );\r
38173 end;\r
38174 {$ENDIF ASM_VERSION}\r
38176 {$IFDEF ASM_VERSION}\r
38177 //[procedure TControl.Invalidate]\r
38178 procedure TControl.Invalidate;\r
38179 asm\r
38180         XOR       EDX, EDX\r
38181         CMP       [AppletTerminated], DL\r
38182         JNZ       @@exit\r
38183         MOV       ECX, [EAX].fHandle\r
38184         JECXZ     @@exit\r
38185         PUSH      EAX\r
38186         PUSH      1\r
38187         PUSH      EDX //=0\r
38188         PUSH      ECX\r
38189         CALL      Windows.InvalidateRect\r
38190         POP       EAX\r
38191         CALL      dword ptr[Global_Invalidate]\r
38192 @@exit:\r
38193 end;\r
38194 {$ELSE ASM_VERSION} //Pascal\r
38195 procedure TControl.Invalidate;\r
38196 begin\r
38197    if AppletTerminated then Exit;\r
38198    if fHandle = 0 then Exit;\r
38199    InvalidateRect( fHandle, nil, True );\r
38201    Global_Invalidate( @Self );\r
38202 end;\r
38203 {$ENDIF ASM_VERSION}\r
38205 {$IFDEF ASM_VERSION}\r
38206 //[function TControl.GetIcon]\r
38207 function TControl.GetIcon: HIcon;\r
38208 asm\r
38209         PUSH      EBX\r
38210         XCHG      EBX, EAX\r
38211         MOV       EAX, [EBX].fIcon\r
38212         INC       EAX\r
38213         JZ        @@exit\r
38214         DEC       EAX\r
38215         JNZ       @@exit\r
38217         MOV       ECX, [Applet]\r
38218         JECXZ     @@load\r
38219         CMP       ECX, EBX\r
38220         JZ        @@load\r
38222         XCHG      EAX, ECX\r
38223         CALL      TControl.GetIcon\r
38224         TEST      EAX, EAX\r
38225         JZ        @@exit\r
38227         XOR       EDX, EDX\r
38228         PUSH      EDX\r
38229         PUSH      EDX\r
38230         PUSH      EDX\r
38231         INC       EDX  // IMAGE_ICON = 1\r
38232         PUSH      EDX\r
38233         PUSH      EAX\r
38234         CALL      CopyImage\r
38235         JMP       @@store_fIcon\r
38237 @@main_icon:\r
38238         DB  'MAINICON',0\r
38240 @@load:\r
38241         PUSH      offset @@main_icon\r
38242         PUSH      [hInstance]\r
38243         CALL      LoadIcon\r
38244 @@store_fIcon:\r
38245         MOV       [EBX].fIcon, EAX\r
38246 @@exit:\r
38247         POP       EBX\r
38248 end;\r
38249 {$ELSE ASM_VERSION} //Pascal\r
38250 function TControl.GetIcon: HIcon;\r
38251 begin\r
38252    Result := fIcon;\r
38253    if Result = THandle( -1 ) then\r
38254    begin\r
38255      Result := 0;\r
38256      Exit;\r
38257    end;\r
38258    if Result = 0 then\r
38259    if (Assigned( Applet )) and\r
38260       (@Self <> Applet) then\r
38261    begin\r
38262       Result := Applet.Icon;\r
38263       if Result <> 0 then\r
38264         Result := CopyImage( Result, IMAGE_ICON, 0, 0, 0 );\r
38265    end\r
38266      else\r
38267    begin\r
38268      //if Result = 0 then\r
38269         Result := LoadIcon( hInstance, 'MAINICON' );\r
38270         //Result := LoadImage( hInstance, 'MAINICON', IMAGE_ICON, 16, 16, LR_SHARED );\r
38271    end;\r
38272    fIcon := Result;\r
38273 end;\r
38274 {$ENDIF ASM_VERSION}\r
38276 //*\r
38277 //[procedure TControl.IconLoad]\r
38278 procedure TControl.IconLoad(Inst: Integer; ResName: PChar);\r
38279 begin\r
38280   Icon := LoadIcon( Inst, ResName );\r
38281   fIconShared := TRUE;\r
38282 end;\r
38284 //[procedure TControl.IconLoadCursor]\r
38285 procedure TControl.IconLoadCursor(Inst: Integer; ResName: PChar);\r
38286 begin\r
38287   Icon := LoadCursor( Inst, ResName );\r
38288   fIconShared := TRUE;\r
38289 end;\r
38291 {$IFDEF ASM_VERSION}\r
38292 //[function TControl.CallDefWndProc]\r
38293 function TControl.CallDefWndProc(var Msg: TMsg): Integer;\r
38294 asm\r
38295         PUSH     [EDX].TMsg.lParam\r
38296         PUSH     [EDX].TMsg.wParam\r
38297         PUSH     [EDX].TMsg.message\r
38299         MOV      ECX, [EAX].fDefWndProc\r
38300         JECXZ    @@defwindowproc\r
38302         PUSH     [EAX].fHandle\r
38303         PUSH     ECX\r
38304         CALL     CallWindowProc\r
38305         RET\r
38307 @@defwindowproc:\r
38308         PUSH     [EDX].TMsg.hwnd\r
38309         CALL     DefWindowProc\r
38310 end;\r
38311 {$ELSE ASM_VERSION} //Pascal\r
38312 function TControl.CallDefWndProc(var Msg: TMsg): Integer;\r
38313 begin\r
38314     if FDefWndProc <> nil then\r
38315        Result := CallWindowProc( FDefWndProc, FHandle, Msg.message, Msg.wParam, Msg.lParam )\r
38316     else\r
38317        Result := DefWindowProc( Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam );\r
38318 end;\r
38319 {$ENDIF ASM_VERSION}\r
38321 {$IFDEF ASM_VERSION}\r
38322 //[function TControl.GetWindowState]\r
38323 function TControl.GetWindowState: TWindowState;\r
38324 asm     //cmd    //opd\r
38325         PUSH     EBX\r
38326         PUSH     ESI\r
38327         XCHG     ESI, EAX\r
38328         MOVZX    EBX, [ESI].TControl.fWindowState\r
38329         MOV      ECX, [ESI].TControl.fHandle\r
38330         JECXZ    @@ret_EBX\r
38331         MOV      BL, 2\r
38332         MOV      ESI, ECX\r
38333         PUSH     ESI\r
38334         CALL     IsZoomed\r
38335         TEST     EAX, EAX\r
38336         JNZ      @@ret_EBX\r
38337         DEC      EBX\r
38338         PUSH     ESI\r
38339         CALL     IsIconic\r
38340         TEST     EAX, EAX\r
38341         JNZ      @@ret_EBX\r
38342         DEC      EBX\r
38343 @@ret_EBX:\r
38344         XCHG     EAX, EBX\r
38345         POP      ESI\r
38346         POP      EBX\r
38347 end;\r
38348 {$ELSE ASM_VERSION} //Pascal\r
38349 function TControl.GetWindowState: TWindowState;\r
38350 begin\r
38351    Result := fWindowState;\r
38352    if Handle <> 0 then\r
38353    begin\r
38354       if IsIconic( Handle ) then\r
38355          Result := wsMinimized\r
38356       else\r
38357       if IsZoomed( Handle ) then\r
38358          Result := wsMaximized\r
38359       else\r
38360          Result := wsNormal;\r
38361       fWindowState := Result;\r
38362    end;\r
38363 end;\r
38364 {$ENDIF ASM_VERSION}\r
38366 {$IFDEF ASM_VERSION}\r
38367 //[function TControl.DoSetFocus]\r
38368 function TControl.DoSetFocus: Boolean;\r
38369 asm\r
38370         PUSH      ESI\r
38371         MOV       ESI, EAX\r
38373         {MOV       EDX, [ESI].fStyle\r
38374         TEST      EDX, WS_TABSTOP\r
38375         JZ        @@exit}\r
38377         CALL      GetEnabled\r
38378         TEST      AL, AL\r
38379         JZ        @@exit\r
38381         XOR       EAX, EAX\r
38382         CMP       [ESI].fTabstop, AL\r
38383         JZ        @@exit\r
38385         INC       [ESI].TControl.fClickDisabled\r
38387         PUSH      [ESI].fHandle\r
38388         CALL      SetFocus\r
38390         DEC       [ESI].TControl.fClickDisabled\r
38392         MOV       AL, 1\r
38394 @@exit:\r
38395         POP       ESI\r
38396 end;\r
38397 {$ELSE ASM_VERSION} //Pascal\r
38398 function TControl.DoSetFocus: Boolean;\r
38399 begin\r
38400   Result := False;\r
38401   if Enabled and fTabstop {and (fStyle and WS_TABSTOP <> 0)} then\r
38402   begin\r
38403     Inc( fClickDisabled );\r
38404     SetFocus( fHandle );\r
38405     Dec( fClickDisabled );\r
38406     Result := True;\r
38407   end;\r
38408 end;\r
38409 {$ENDIF ASM_VERSION}\r
38411 //[function TControl.HandleAllocated]\r
38412 function TControl.HandleAllocated: Boolean;\r
38413 begin\r
38414   Result := FHandle <> 0;\r
38415 end;\r
38417 {$IFDEF ASM_VERSION}\r
38418 //[function TControl.GetEnabled]\r
38419 function TControl.GetEnabled: Boolean;\r
38420 asm\r
38421         MOV       ECX, [EAX].fHandle\r
38422         JECXZ     @@get_field\r
38424         PUSH      ECX\r
38425         CALL      IsWindowEnabled\r
38426         {                  but 00000001 is returned anywhere...\r
38427         NEG       EAX\r
38428         SBB       EAX, EAX\r
38429         NEG       EAX\r
38430         }\r
38431         RET\r
38433 @@get_field:\r
38434         TEST      byte ptr [EAX].fStyle + 3, 8 //WS_DISABLED shr 3\r
38435         SETZ      AL\r
38436 end;\r
38437 {$ELSE ASM_VERSION} //Pascal\r
38438 function TControl.GetEnabled: Boolean;\r
38439 begin\r
38440   if FHandle = 0 then\r
38441      Result := (Style and WS_DISABLED) = 0\r
38442   else\r
38443      Result := IsWindowEnabled( FHandle );\r
38444 end;\r
38445 {$ENDIF ASM_VERSION}\r
38447 {$IFDEF ASM_VERSION}\r
38448 //[function TControl.IsMainWindow]\r
38449 function TControl.IsMainWindow: Boolean;\r
38450 asm\r
38451         CMP       [EAX].fIsControl, 0\r
38452         JNZ       @@no_notmain\r
38454         XCHG      EDX, EAX\r
38455         MOV       EAX, [EDX].fParent\r
38457         TEST      EAX, EAX\r
38458         JZ        @@1\r
38460         MOV       ECX, [EAX].fParent\r
38461         INC       ECX\r
38462         LOOP      @@no_notmain\r
38464         MOV       EAX, [EAX].fChildren\r
38466         MOV       ECX, [EAX].TList.fCount\r
38467         JECXZ     @@no_notmain\r
38469         MOV       EAX, [EAX].TList.fItems\r
38470         CMP       EDX, [EAX]\r
38471         MOV       AL, 1\r
38472         JMP       @@2\r
38473 @@1:\r
38474         INC       EAX\r
38475         MOVZX     ECX, [AppButtonUsed]\r
38476         JECXZ     @@yes_main\r
38477         CMP       EDX, [Applet]\r
38478 @@2:\r
38479         JZ        @@yes_main\r
38481 @@no_notmain:\r
38482         XOR       EAX, EAX\r
38483 @@yes_main:\r
38484 end;\r
38485 {$ELSE ASM_VERSION} //Pascal\r
38486 function TControl.IsMainWindow: Boolean;\r
38487 var A: PControl;\r
38488 begin\r
38489   Result := False;\r
38490   if fIsControl then Exit;\r
38491   A := fParent; // WindowedParent;\r
38492   if A = nil then\r
38493   begin\r
38494     Result := (@Self = Applet) or not AppButtonUsed;\r
38495     Exit;\r
38496   end\r
38497      else\r
38498   if A.fParent <> nil then Exit;\r
38499   //--------------------------------------------------------------------------------\r
38500   if A.fChildren.fCount = 0 then Exit; // by ECM, fixes AV when user changed (logoff)\r
38501   //--------------------------------------------------------------------------------\r
38502   Result := A.fChildren.fItems[ 0 ] = @Self;\r
38503 end;\r
38504 {$ENDIF ASM_VERSION}\r
38506 {$IFDEF ASM_VERSION}\r
38507 //[function TControl.get_ClassName]\r
38508 function TControl.get_ClassName: String;\r
38509 asm\r
38510         PUSH      EBX\r
38511         XCHG      EBX, EAX\r
38512         XCHG      EAX, EDX\r
38513         MOV       EDX, [EBX].fControlClassName\r
38514         PUSH      EAX\r
38515         CALL      System.@LStrFromPChar\r
38516         POP       EAX\r
38517         CMP       [EBX].fCtlClsNameChg, 0\r
38518         JNZ       @@exit\r
38519         MOV       ECX, [EAX]\r
38520         MOV       EDX, offset[ @@obj ]\r
38521         CALL      System.@LStrCat3\r
38522         JMP       @@exit\r
38524         DD        -1, 4\r
38525 @@obj:  DB        'obj_', 0\r
38527 @@exit:\r
38528         POP       EBX\r
38529 end;\r
38530 {$ELSE ASM_VERSION} //Pascal\r
38531 function TControl.get_ClassName: String;\r
38532 begin\r
38533   if not fCtlClsNameChg then\r
38534     Result := 'obj_' + fControlClassName\r
38535   else\r
38536     Result := fControlClassName;\r
38537 end;\r
38538 {$ENDIF ASM_VERSION}\r
38540 //[procedure TControl.set_ClassName]\r
38541 procedure TControl.set_ClassName(const Value: String);\r
38542 begin\r
38543   if fCtlClsNameChg then\r
38544     FreeMem( fControlClassName );\r
38545   GetMem( fControlClassName, Length( Value ) + 1 );\r
38546   StrCopy( fControlClassName, @ Value[ 1 ] );\r
38547   fCtlClsNameChg := TRUE;\r
38548 end;\r
38550 //[function WndProcQueryEndSession]\r
38551 function WndProcQueryEndSession( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
38552 var Accept: Boolean;\r
38553 begin\r
38554   Result := FALSE;\r
38555   if Msg.message = WM_QUERYENDSESSION then\r
38556   begin\r
38557     if Assigned( Sender.fOnQueryEndSession ) then\r
38558     begin\r
38559       Accept := TRUE;\r
38560       Sender.fCloseQueryReason := qShutdown;\r
38561       if LongBool(Msg.lParam and {ENDSESSION_LOGOFF} DWORD($80000000)) then\r
38562         Sender.fCloseQueryReason := qLogoff;\r
38563       Sender.fOnQueryEndSession( Sender, Accept );\r
38564       Sender.fCloseQueryReason := qClose;\r
38565       Rslt := Integer( Accept );\r
38566       // Äîáàâèòü. Íóæíî äëÿ òîãî, ÷òîáû îòìåíèëîñü çàâåðøåíèå ñåàíñà,\r
38567       // åñëè Accept óñòàíîâëåí â False è ñåàíñ çàâåðøèëñÿ ïðè Accept = True\r
38568       // Add (YS). To cancel ending session if Accept=FALSE but allow ending\r
38569       // session if Accept=TRUE.\r
38570       Result := True;  // {YS}: no further processing\r
38571     end;\r
38572   end;\r
38573 end;\r
38575 //[procedure TControl.SetOnQueryEndSession]\r
38576 procedure TControl.SetOnQueryEndSession(const Value: TOnEventAccept);\r
38577 begin\r
38578   AttachProc( WndProcQueryEndSession );\r
38579   fOnQueryEndSession := Value;\r
38580 end;\r
38582 //[function WndProcMinMaxRestore]\r
38583 function WndProcMinMaxRestore( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
38584 begin\r
38585   Result := FALSE;\r
38586   if Msg.message = WM_SYSCOMMAND then\r
38587   begin\r
38588     case Msg.wParam of\r
38589     SC_MINIMIZE: if Assigned( Sender.fOnMinimize ) then\r
38590                    Sender.fOnMinimize( Sender );\r
38591     SC_MAXIMIZE: if Assigned( Sender.fOnMaximize ) then\r
38592                    Sender.fOnMaximize( Sender );\r
38593     SC_RESTORE:  if Assigned( Sender.fOnRestore ) then\r
38594                    Sender.fOnRestore( Sender );\r
38595     end;\r
38596   end;\r
38597 end;\r
38599 //[procedure TControl.SetOnMinMaxRestore]\r
38600 procedure TControl.SetOnMinMaxRestore(const Index: Integer;\r
38601   const Value: TOnEvent);\r
38602 type POnEvent = ^TOnEvent;\r
38603 {$IFDEF F_P}\r
38604 var Ptr1: Pointer;\r
38605 {$ELSE DELPHI}\r
38606 var Ev: POnEvent;\r
38607 {$ENDIF F_P/DELPHI}\r
38608 begin\r
38609   AttachProc( WndProcMinMaxRestore );\r
38610   {$IFDEF F_P}\r
38611   Ptr1 := Self;\r
38612   asm\r
38613     MOV  EAX, [Ptr1]\r
38614     LEA  EAX, [EAX].TControl.fOnMinimize\r
38615     ADD  EAX, [Index]\r
38616     MOV  EDX, [Value]\r
38617     MOV  [EAX], EDX\r
38618     MOV  EDX, [Value+4]\r
38619     MOV  [EAX+4], EDX\r
38620   end [ 'EAX', 'EDX' ];\r
38621   {$ELSE DELPHI}\r
38622   Ev := Pointer( Integer( @ TMethod( fOnMinimize ).Code ) + Index );\r
38623   //Ev := Pointer( Integer( @ fOnMinimize ) + Index );\r
38624   Ev^ := Value;\r
38625   {$ENDIF}\r
38626 end;\r
38628 {$IFDEF F_P}\r
38629 //[function TControl.GetOnMinMaxRestore]\r
38630 function TControl.GetOnMinMaxRestore(const Index: Integer): TOnEvent;\r
38631 begin\r
38632   CASE Index OF\r
38633   0: Result := fOnMinimize;\r
38634   8: Result := fOnMaximize;\r
38635   16: Result := fOnRestore;\r
38636   END;\r
38637 end;\r
38638 {$ENDIF F_P}\r
38640 {$IFDEF INPACKAGE}\r
38641   {$IFDEF ASM_LOCAL}\r
38642     {$UNDEF ASM_LOCAL}\r
38643   {$ENDIF}\r
38644 {$ELSE}\r
38645   {$IFDEF ASM_VERSION}\r
38646     {$DEFINE ASM_LOCAL}\r
38647   {$ENDIF}\r
38648 {$ENDIF}\r
38650 {$IFDEF ASM_LOCAL} \r
38651 //[procedure TControl.SetParent]\r
38652 procedure TControl.SetParent( Value: PControl );\r
38653 asm\r
38654         PUSH     EBX\r
38655         PUSH     EDI\r
38656         XCHG     EBX, EAX\r
38657         MOV      EDI, [EBX].fParent\r
38659         CMP      EDX, EDI\r
38660         JZ       @@exit\r
38662         PUSH     EDX\r
38663         TEST     EDI, EDI\r
38664         JZ       @@set_another_parent\r
38666         MOV      EAX, [EDI].fChildren\r
38667         MOV      EDX, EBX\r
38668         CALL     TList.Remove\r
38670         MOV      ECX, [EDI].fNotifyChild\r
38671         JECXZ    @@set_another_parent\r
38673         MOV      EAX, EDI\r
38674         XOR      EDX, EDX\r
38675         CALL     ECX\r
38677 @@set_another_parent:\r
38678         POP      EDI\r
38679         MOV      [EBX].fParent, EDI\r
38680         TEST     EDI, EDI\r
38681         JZ       @@exit\r
38683         MOV      EAX, [EDI].fChildren\r
38684         MOV      EDX, EBX\r
38685         CALL     TList.Add\r
38687         {$IFNDEF INPACKAGE}\r
38688         MOV      ECX, [EBX].FHandle\r
38689         JECXZ    @@parentwnd_assigned\r
38690         PUSH     ECX\r
38691         MOV      EAX, EDI\r
38692         CALL     GetWindowHandle\r
38693         POP      ECX\r
38694         PUSH     EAX\r
38695         PUSH     ECX\r
38696         CALL     Windows.SetParent\r
38698 @@parentwnd_assigned:\r
38699         {$ENDIF}\r
38701         MOV      ECX, [EDI].fNotifyChild\r
38702         JECXZ    @@exit\r
38704         MOV      EAX, EDI\r
38705         MOV      EDX, EBX\r
38706         CALL     ECX\r
38708 @@exit:\r
38709         POP      EDI\r
38710         POP      EBX\r
38711 end;\r
38712 {$ELSE ASM_VERSION} //Pascal\r
38713 procedure TControl.SetParent( Value: PControl );\r
38714 begin\r
38715    if Value = fParent then Exit;\r
38716    if fParent <> nil then\r
38717    begin\r
38718      fParent.fChildren.Remove( @Self );\r
38719      if Assigned( fParent.fNotifyChild ) then\r
38720        fParent.fNotifyChild( fParent, nil );\r
38721    end;\r
38722    fParent := Value;\r
38723    if fParent <> nil then\r
38724    begin\r
38725      fParent.fChildren.Add( @Self );\r
38726      {$IFNDEF INPACKAGE}\r
38727      if FHandle <> 0 then\r
38728        Windows.SetParent( FHandle, Value.GetWindowHandle );\r
38729      {$ENDIF}\r
38730      if Assigned( fParent.fNotifyChild ) then\r
38731        fParent.fNotifyChild( fParent, @ Self );\r
38732    end;\r
38733 end;\r
38734 {$ENDIF ASM_VERSION}\r
38736 //[function TControl.ChildIndex]\r
38737 function TControl.ChildIndex(Child: PControl): Integer;\r
38738 begin\r
38739   Result := fChildren.IndexOf( Child );\r
38740 end;\r
38742 //*\r
38743 //[procedure TControl.MoveChild]\r
38744 procedure TControl.MoveChild(Child: PControl; NewIdx: Integer);\r
38745 var I: Integer;\r
38746 begin\r
38747   I := ChildIndex( Child );\r
38748   Assert( I>=0, 'TControl.MoveChild: index out of bounds' );\r
38749   fChildren.MoveItem( I, NewIdx );\r
38750 end;\r
38752 //[procedure TControl.EnableChildren]\r
38753 procedure TControl.EnableChildren(Enable, Recursive: Boolean);\r
38754 var I: Integer;\r
38755     C: PControl;\r
38756 begin\r
38757   for I := 0 to ChildCount-1 do\r
38758   begin\r
38759     C := Children[ I ];\r
38760     C.Enabled := Enable;\r
38761     if Recursive then\r
38762       C.EnableChildren( Enable, TRUE );\r
38763   end;\r
38764 end;\r
38766 {$IFDEF ASM_VERSION}\r
38767 //[constructor TControl.CreateParented]\r
38768 constructor TControl.CreateParented(AParent: PControl);\r
38769 asm     //cmd    //opd\r
38770         //CALL     System.@ObjSetup // generated automatically\r
38771         //JZ       @@exit           // generated automatically\r
38772         PUSH     EAX\r
38773         MOV      EDX, ECX\r
38774         MOV      ECX, [EAX]\r
38775         CALL     dword ptr [ECX+8]\r
38776         POP      EAX\r
38777 @@exit:\r
38778 end;\r
38779 {$ELSE ASM_VERSION} //Pascal\r
38780 constructor TControl.CreateParented(AParent: PControl);\r
38781 begin\r
38782   InitParented( AParent );\r
38783 end;\r
38784 {$ENDIF ASM_VERSION}\r
38786 {$IFDEF ASM_VERSION}\r
38787 //[function TControl.GetLeft]\r
38788 function TControl.GetLeft: Integer;\r
38789 asm\r
38790         CALL      HelpGetBoundsRect\r
38791         POP       EAX\r
38793         POP       ECX\r
38794         POP       ECX\r
38795         POP       ECX\r
38796 end;\r
38797 {$ELSE ASM_VERSION} //Pascal\r
38798 function TControl.GetLeft: Integer;\r
38799 begin\r
38800    Result := BoundsRect.Left;\r
38801 end;\r
38802 {$ENDIF ASM_VERSION}\r
38804 {$IFDEF ASM_VERSION}\r
38805 //[procedure TControl.SetLeft]\r
38806 procedure TControl.SetLeft( Value: Integer );\r
38807 asm\r
38808         PUSH      EDI\r
38810         PUSH      EDX\r
38811         CALL      HelpGetBoundsRect\r
38812         POP       EDX           // EDX = Left\r
38813         POP       ECX           // ECX = Top\r
38814         POP       EDI           // EDI = Right\r
38816         SUB       EDI, EDX      // EDI = width\r
38817         MOV       EDX, [ESP+4]  // EDX = Left'\r
38818         ADD       EDI, EDX      // EDI = Right'\r
38820         PUSH      EDI\r
38821         PUSH      ECX\r
38822         PUSH      EDX\r
38823         MOV       EDX, ESP\r
38825         CALL      SetBoundsRect\r
38826         ADD       ESP, size_TRect + 4\r
38828         POP       EDI\r
38830 end;\r
38831 {$ELSE ASM_VERSION} //Pascal\r
38832 procedure TControl.SetLeft( Value: Integer );\r
38833 var R: TRect;\r
38834 begin\r
38835    R := BoundsRect;\r
38836    R.Left := Value;\r
38837    R.Right := Value + Width;\r
38838    SetBoundsRect( R );\r
38839 end;\r
38840 {$ENDIF ASM_VERSION}\r
38842 {$IFDEF ASM_VERSION}\r
38843 //[function TControl.GetTop]\r
38844 function TControl.GetTop: Integer;\r
38845 asm\r
38846         CALL      HelpGetBoundsRect\r
38847         POP       EDX\r
38848           POP       EAX\r
38849         POP       EDX\r
38850         POP       EDX\r
38851 end;\r
38852 {$ELSE ASM_VERSION} //Pascal\r
38853 function TControl.GetTop: Integer;\r
38854 begin\r
38855    Result := BoundsRect.Top;\r
38856 end;\r
38857 {$ENDIF ASM_VERSION}\r
38859 {$IFDEF ASM_VERSION}\r
38860 //[procedure TControl.SetTop]\r
38861 procedure TControl.SetTop( Value: Integer );\r
38862 asm\r
38863         PUSH      ESI\r
38864         PUSH      EDI\r
38866           PUSH      EDX\r
38867         CALL      HelpGetBoundsRect\r
38868         POP       EDX           // EDX = Left\r
38869         POP       ECX           // ECX = Top\r
38870         POP       EDI           // EDI = Right\r
38871         POP       ESI           // ESI = Bottom\r
38873         SUB       ESI, ECX      // ESI = Height'\r
38874           POP       ECX         // ECX = Top'\r
38875         ADD       ESI, ECX      // ESI = Bottom'\r
38877         PUSH      ESI\r
38878         PUSH      EDI\r
38879         PUSH      ECX\r
38880         PUSH      EDX\r
38881         MOV       EDX, ESP\r
38883         CALL      SetBoundsRect\r
38884         ADD       ESP, size_TRect\r
38886         POP       EDI\r
38887         POP       ESI\r
38888 end;\r
38889 {$ELSE ASM_VERSION} //Pascal\r
38890 procedure TControl.SetTop( Value: Integer );\r
38891 var R: TRect;\r
38892 begin\r
38893    R := BoundsRect;\r
38894    R.Top := Value;\r
38895    R.Bottom := Value + Height;\r
38896    SetBoundsRect( R );\r
38897 end;\r
38898 {$ENDIF ASM_VERSION}\r
38900 {$IFDEF ASM_VERSION}\r
38901 //[function TControl.GetWidth]\r
38902 function TControl.GetWidth: Integer;\r
38903 asm\r
38904         CALL      HelpGetBoundsRect\r
38905         POP       EDX\r
38906           POP       ECX\r
38907         POP       EAX\r
38908         SUB       EAX, EDX\r
38909           POP       ECX\r
38910 end;\r
38911 {$ELSE ASM_VERSION} //Pascal\r
38912 function TControl.GetWidth: Integer;\r
38913 begin\r
38914   with BoundsRect do\r
38915     Result := Right - Left;\r
38916 end;\r
38917 {$ENDIF ASM_VERSION}\r
38919 {$IFDEF ASM_VERSION}\r
38920 //[procedure TControl.SetWidth]\r
38921 procedure TControl.SetWidth( Value: Integer );\r
38922 asm\r
38923         PUSH      EDX\r
38925         CALL      HelpGetBoundsRect\r
38926         POP       EDX\r
38927         PUSH      EDX\r
38928         ADD       EDX, [ESP].size_TRect\r
38929         MOV       [ESP].TRect.Right, EDX\r
38931         MOV       EDX, ESP\r
38932         CALL      SetBoundsRect\r
38934         ADD       ESP, size_TRect + 4\r
38935 end;\r
38936 {$ELSE ASM_VERSION} //Pascal\r
38937 procedure TControl.SetWidth( Value: Integer );\r
38938 var R: TRect;\r
38939 begin\r
38940   R := BoundsRect;\r
38941   with R do\r
38942     Right := Left + Value;\r
38943   SetBoundsRect( R );\r
38944 end;\r
38945 {$ENDIF ASM_VERSION}\r
38947 {$IFDEF ASM_VERSION}\r
38948 //[function TControl.GetHeight]\r
38949 function TControl.GetHeight: Integer;\r
38950 asm\r
38951         CALL      HelpGetBoundsRect\r
38952         POP       ECX\r
38953         POP       EDX          // EDX = top\r
38954         POP       ECX\r
38955         POP       EAX          // EAX = bottom\r
38956         SUB       EAX, EDX     // result = height\r
38957 end;\r
38958 {$ELSE ASM_VERSION} //Pascal\r
38959 function TControl.GetHeight: Integer;\r
38960 begin\r
38961   with BoundsRect do\r
38962    Result := Bottom - Top;\r
38963 end;\r
38964 {$ENDIF ASM_VERSION}\r
38966 {$IFDEF ASM_VERSION}\r
38967 //[procedure TControl.SetHeight]\r
38968 procedure TControl.SetHeight( Value: Integer );\r
38969 asm\r
38970         PUSH      EDX\r
38972         CALL      HelpGetBoundsRect\r
38973         MOV       EDX, [ESP].TRect.Top\r
38974         ADD       EDX, [ESP].size_TRect\r
38975         MOV       [ESP].TRect.Bottom, EDX\r
38977         MOV       EDX, ESP\r
38978         CALL      SetBoundsRect\r
38980         ADD       ESP, size_TRect + 4\r
38981 end;\r
38982 {$ELSE ASM_VERSION} //Pascal\r
38983 procedure TControl.SetHeight( Value: Integer );\r
38984 var R: TRect;\r
38985 begin\r
38986    R := BoundsRect;\r
38987    with R do\r
38988      Bottom := Top + Value;\r
38989    SetBoundsRect( R );\r
38990 end;\r
38991 {$ENDIF ASM_VERSION}\r
38993 {$IFDEF ASM_VERSION}\r
38994 //[function TControl.GetPosition]\r
38995 function TControl.GetPosition: TPoint;\r
38996 asm\r
38997         PUSH      EDX\r
38998         CALL      HelpGetBoundsRect\r
38999         POP       EAX         // EAX = left\r
39000         POP       ECX         // ECX = top\r
39001         POP       EDX\r
39002         POP       EDX\r
39003         POP       EDX         // EDX = @Result\r
39004         MOV       [EDX], EAX\r
39005         MOV       [EDX+4], ECX\r
39006 end;\r
39007 {$ELSE ASM_VERSION} //Pascal\r
39008 function TControl.GetPosition: TPoint;\r
39009 begin\r
39010   Result.x := BoundsRect.Left;\r
39011   Result.y := BoundsRect.Top;\r
39012 end;\r
39013 {$ENDIF ASM_VERSION}\r
39015 {$IFDEF ASM_VERSION}\r
39016 //[procedure TControl.Set_Position]\r
39017 procedure TControl.Set_Position( Value: TPoint );\r
39018 asm\r
39019         PUSH      ESI\r
39020         PUSH      EDI\r
39022         PUSH      EAX\r
39023         PUSH      EDX\r
39024         CALL      HelpGetBoundsRect\r
39025         POP       EDX           // left\r
39026         POP       EAX           // top\r
39027         POP       ECX           // right\r
39028         SUB       ECX, EDX      // ECX = width\r
39029         POP       EDX           // bottom\r
39030         SUB       EDX, EAX      // EDX = height\r
39031         POP       EAX           // EAX = @Value\r
39032         POP       ESI           // ESI = @Self\r
39034         MOV       EDI, [EAX+4]  // top'\r
39035         ADD       EDX, EDI\r
39036         PUSH      EDX           // bottom'\r
39038         MOV       EAX, [EAX]    // left'\r
39039         ADD       ECX, EAX\r
39040         PUSH      ECX           // right'\r
39042         PUSH      EDI           // top'\r
39043         PUSH      EAX           // left'\r
39045         MOV       EAX, ESI\r
39046         MOV       EDX, ESP\r
39047         CALL      SetBoundsRect\r
39049         ADD       ESP, size_TRect\r
39051         POP       EDI\r
39052         POP       ESI\r
39053 end;\r
39054 {$ELSE ASM_VERSION} //Pascal\r
39055 procedure TControl.Set_Position( Value: TPoint );\r
39056 var R: TRect;\r
39057 begin\r
39058    R.Top := Value.y;\r
39059    R.Left := Value.x;\r
39060    R.Right := R.Left + Width;\r
39061    R.Bottom := R.Top + Height;\r
39062    BoundsRect := R;\r
39063 end;\r
39064 {$ENDIF ASM_VERSION}\r
39066 //[function WndProcConstraints]\r
39067 function WndProcConstraints( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
39068 var MMI: PMinMaxInfo;\r
39069 begin\r
39070   Result := FALSE;\r
39071   if Msg.message = WM_GETMINMAXINFO then\r
39072   begin\r
39073     Rslt := Sender.CallDefWndProc( Msg );\r
39074     MMI := Pointer( Msg.lParam );\r
39075     if Sender.FMaxWidth > 0 then\r
39076     begin\r
39077       MMI.ptMaxSize.x := Sender.FMaxWidth;\r
39078       MMI.ptMaxTrackSize.x := Sender.FMaxWidth;\r
39079     end;\r
39080     if Sender.FMaxHeight > 0 then\r
39081     begin\r
39082       MMI.ptMaxSize.y := Sender.FMaxHeight;\r
39083       MMI.ptMaxTrackSize.y := Sender.FMaxHeight;\r
39084     end;\r
39085     MMI.ptMinTrackSize := MakePoint( Sender.FMinWidth, Sender.FMinHeight );\r
39086     Rslt := 0;\r
39087     Result := TRUE;\r
39088   end;\r
39089 end;\r
39091 {$IFDEF USE_MHTOOLTIP}\r
39092 {$DEFINE implementation}\r
39093 {$I KOLMHToolTip}\r
39094 {$UNDEF implementation}\r
39095 {$ENDIF}\r
39097 //[procedure TControl.SetConstraint]\r
39098 procedure TControl.SetConstraint(const Index, Value: Integer);\r
39099 begin\r
39100   AttachProc( WndProcConstraints );\r
39101   case Index of\r
39102   0: FMinWidth := Value;\r
39103   1: FMinHeight := Value;\r
39104   2: FMaxWidth := Value;\r
39105   3: FMaxHeight := Value;\r
39106   end;\r
39107 end;\r
39109 {$IFDEF F_P}\r
39110 //[function TControl.GetConstraint]\r
39111 function TControl.GetConstraint(const Index: Integer): Integer;\r
39112 begin\r
39113   CASE Index OF\r
39114   0: Result := FMinWidth;\r
39115   1: Result := FMinHeight;\r
39116   2: Result := FMaxWidth;\r
39117   3: Result := FMaxHeight;\r
39118   END;\r
39119 end;\r
39120 {$ENDIF F_P}\r
39122 //*\r
39123 //[function TControl.ControlRect]\r
39124 function TControl.ControlRect: TRect;\r
39125 var C: PControl;\r
39126     R: TRect;\r
39127 begin\r
39128    Result := BoundsRect;\r
39129    C := Parent;\r
39130    if C <> nil then\r
39131    begin\r
39132       //DoScrollOffset( @Result );\r
39134       if not C.fIsControl then Exit;\r
39136       R := C.ControlRect;\r
39137       OffsetRect( Result, R.Left, R.Top );\r
39139       if C.fChildren <> nil then\r
39140       if C.FChildren.IndexOf( @Self ) >= C.MembersCount then\r
39141       begin\r
39142          R := C.ClientRect;\r
39143          Dec( R.Top, C.fClientTop );\r
39144          Dec( R.Left, C.fClientLeft );\r
39145          OffsetRect( Result, R.Left, R.Top );\r
39146       end;\r
39147    end;\r
39148 end;\r
39150 //*\r
39151 //[function TControl.ControlAtPos]\r
39152 function TControl.ControlAtPos( X, Y: Integer;\r
39153                                    IgnoreDisabled: Boolean ): PControl;\r
39154 var I: Integer;\r
39155     C: PControl;\r
39156     CR, VR: TRect;\r
39157 begin\r
39158    Result := nil;\r
39159    CR := ControlRect;\r
39160    if Windowed then\r
39161       CR := MakeRect( 0, 0, 0, 0 );\r
39162    X := X + CR.Left; // - R.Left;\r
39163    Y := Y + CR.Top; // - R.Top;\r
39164    for I := ChildCount { + MembersCount } - 1 downto 0 do\r
39165    begin\r
39166       C := Children[ I ]; //Members[ I ];\r
39167       if C.Visible then\r
39168       if (not IgnoreDisabled) or IgnoreDisabled and C.Enabled then\r
39169       begin\r
39170          VR := C.ControlRect;\r
39171          if (X >= VR.Left) and (X < VR.Right) and\r
39172             (Y >= VR.Top) and (Y < VR.Bottom) then\r
39173          begin\r
39174             Result := C;\r
39175             Exit;\r
39176          end;\r
39177       end;\r
39178    end;\r
39179 end;\r
39181 //[PROCEDURE DefaultPaintBackground]\r
39182 {$IFDEF ASM_VERSION}\r
39183 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );\r
39184 asm\r
39185         PUSH      EDI\r
39187         PUSH      EDI\r
39188         MOV       EDI, ESP\r
39190         PUSH      ECX\r
39191         PUSH      EDX\r
39193         MOV       EAX, [EAX].TControl.fColor\r
39194         CALL      Color2RGB\r
39195         PUSH      EAX\r
39196         CALL      CreateSolidBrush\r
39197         STOSD\r
39198         MOV       EDI, EAX\r
39199         CALL      windows.FillRect\r
39200         PUSH      EDI\r
39201         CALL      DeleteObject\r
39202         POP       EDI\r
39203 end;\r
39204 {$ELSE ASM_VERSION} //Pascal\r
39205 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );\r
39206 var B: HBrush;\r
39207 begin\r
39208   B := CreateSolidBrush( Color2Rgb( Sender.Color ) );\r
39209   Windows.FillRect( DC, Rect^, B );\r
39210   DeleteObject( B );\r
39211 end;\r
39212 {$ENDIF ASM_VERSION}\r
39213 //[END DefaultPaintBackground]\r
39215 //[procedure TControl.PaintBackground]\r
39216 procedure TControl.PaintBackground( DC: HDC; Rect: PRect );\r
39217 begin\r
39218   Global_OnPaintBkgnd( @Self, DC, Rect );\r
39219 end;\r
39221 //[procedure TControl.SetCtlColor]\r
39222 {$IFDEF ASM_VERSION}\r
39223 procedure TControl.SetCtlColor( Value: TColor );\r
39224 asm\r
39225         PUSH     EBX\r
39226         MOV      EBX, EAX\r
39228         {$IFNDEF INPACKAGE}\r
39229         PUSH     EDX\r
39231         CALL     GetWindowHandle\r
39232         XCHG     ECX, EAX\r
39234         POP      EDX\r
39235         {$ELSE}\r
39236         MOV      ECX, [EBX].fHandle\r
39237         {$ENDIF}\r
39239         JECXZ    @@1\r
39241         MOVZX    ECX, [EBX].fCommandActions.aSetBkColor\r
39242         JECXZ    @@1\r
39244         PUSH     EDX\r
39246         XCHG     EAX, EDX\r
39247         PUSH     ECX\r
39248         CALL     Color2RGB\r
39249         POP      ECX\r
39251         PUSH     EAX        // Color2RGB( Value )\r
39252         PUSH     0          // 0\r
39253         PUSH     ECX        // fCommandActions.aSetBkColor\r
39254         PUSH     EBX        // @ Self\r
39255         CALL     TControl.Perform\r
39257         POP      EDX\r
39259 @@1:\r
39260         CMP      EDX, [EBX].fColor\r
39261         JZ       @@exit\r
39263         MOV      [EBX].fColor, EDX\r
39265         XOR      ECX, ECX\r
39266         XCHG     ECX, [EBX].fTmpBrush\r
39267         JECXZ    @@setbrushcolor\r
39269         PUSH     EDX\r
39270         PUSH     ECX\r
39271         CALL     DeleteObject\r
39272         POP      EDX\r
39274 @@setbrushcolor:\r
39275         MOV      ECX, [EBX].fBrush\r
39276         JECXZ    @@invldte\r
39278         XCHG     EAX, ECX\r
39279         MOV      ECX, EDX\r
39280         //MOV      EDX, go_Color\r
39281         XOR      EDX, EDX\r
39282         CALL     TGraphicTool.SetInt\r
39284 @@invldte:\r
39285         XCHG     EAX, EBX\r
39286         CALL     TControl.Invalidate\r
39287 @@exit:\r
39288         POP      EBX\r
39289 end;\r
39290 {$ELSE ASM_VERSION} //Pascal\r
39291 procedure TControl.SetCtlColor( Value: TColor );\r
39292 begin\r
39293   {$IFNDEF INPACKAGE}\r
39294   if GetWindowHandle <> 0 then\r
39295   {$ELSE}\r
39296   if fHandle <> 0 then\r
39297   {$ENDIF}\r
39298   if fCommandActions.aSetBkColor <> 0 then\r
39299     Perform( fCommandActions.aSetBkColor, 0, Color2RGB( Value ) );\r
39300   if fColor = Value then Exit;\r
39301   fColor := Value;\r
39302   if fTmpBrush <> 0 then\r
39303   begin\r
39304     DeleteObject( fTmpBrush );\r
39305     fTmpBrush := 0;\r
39306   end;\r
39307   if fBrush <> nil then\r
39308     fBrush.Color := Value;\r
39309   Invalidate;\r
39310 end;\r
39311 {$ENDIF ASM_VERSION}\r
39313 {$IFDEF ASM_VERSION}\r
39314 //[function TControl.GetParentWnd]\r
39315 function TControl.GetParentWnd( NeedHandle: Boolean ): HWnd;\r
39316 asm\r
39317         MOV       ECX, [EAX].fParent\r
39318         JECXZ     @@exit\r
39320         PUSH      ECX\r
39321         TEST      DL, DL\r
39322         JZ        @@load_handle\r
39324         XCHG      EAX, ECX\r
39325         CALL      GetWindowHandle\r
39327 @@load_handle:\r
39328         POP       ECX\r
39329         MOV       ECX, [ECX].fHandle\r
39331 @@exit: XCHG      EAX, ECX\r
39333 end;\r
39334 {$ELSE ASM_VERSION} //Pascal\r
39335 function TControl.GetParentWnd( NeedHandle: Boolean ): HWnd;\r
39336 var C: PControl;\r
39337 begin\r
39338    Result := 0;\r
39339    C := fParent; // WindowedParent;\r
39340    if C <> nil then\r
39341    begin\r
39342      if NeedHandle then\r
39343         C.GetWindowHandle;\r
39344      Result := C.fHandle;\r
39345    end;\r
39346 end;\r
39347 {$ENDIF ASM_VERSION}\r
39349 {$IFDEF ASM_VERSION}\r
39350 //[procedure TControl.CreateChildWindows]\r
39351 procedure TControl.CreateChildWindows;\r
39352 asm\r
39353         PUSH      ESI\r
39354         MOV       ESI, [EAX].TControl.fChildren\r
39355         MOV       ECX, [ESI].TList.fCount\r
39356         MOV       ESI, [ESI].TList.fItems\r
39357         JECXZ     @@exit\r
39359 @@loop: PUSH      ECX\r
39360         LODSD\r
39361         CALL      CallTControlCreateWindow\r
39362         //CALL      TControl.GetWindowHandle\r
39363         POP       ECX\r
39364         LOOP      @@loop\r
39366 @@exit: POP       ESI\r
39367 end;\r
39368 {$ELSE ASM_VERSION} //Pascal\r
39369 procedure TControl.CreateChildWindows;\r
39370 var I: Integer;\r
39371     C: PControl;\r
39372 begin\r
39373   for I := 0 to fChildren.Count - 1 do\r
39374   begin\r
39375      C := fChildren.fItems[ I ];\r
39376      //C.GetWindowHandle;\r
39377      C.CreateWindow; //virtual!!!\r
39378   end;\r
39379 end;\r
39380 {$ENDIF ASM_VERSION}\r
39382 //[function TControl.GetMembers]\r
39383 function TControl.GetMembers(Idx: Integer): PControl;\r
39384 begin\r
39385    Result := fChildren.fItems[ Idx ];\r
39386 end;\r
39388 {$IFDEF ASM_VERSION}\r
39389 //[procedure TControl.DestroyChildren]\r
39390 procedure TControl.DestroyChildren;\r
39391 asm\r
39392         PUSH      ESI\r
39394         MOV       EAX, [EAX].fChildren\r
39395         PUSH      EAX\r
39396         MOV       ECX, [EAX].TList.fCount\r
39397         JECXZ     @@clear\r
39398         MOV       ESI, [EAX].TList.fItems\r
39399         LEA       ESI, [ESI + ECX*4 - 4]  // is order really important ?\r
39401 @@loop: STD                               //\r
39402         LODSD\r
39403         CLD                               //\r
39405         PUSH      ECX\r
39406         CALL      TObj.Free\r
39407         POP       ECX\r
39409         LOOP      @@loop\r
39411 @@clear:\r
39412         POP       EAX\r
39413         CALL      TList.Clear\r
39415         POP       ESI\r
39416 end;\r
39417 {$ELSE ASM_VERSION} //Pascal\r
39418 procedure TControl.DestroyChildren;\r
39419 var I: Integer;\r
39420     W: PControl;\r
39421 begin\r
39422    for I := fChildren.fCount - 1 downto 0 do\r
39423    begin\r
39424       W := fChildren.fItems[ I ];\r
39425       W.Free;\r
39426    end;\r
39427    fChildren.Clear;\r
39428 end;\r
39429 {$ENDIF ASM_VERSION}\r
39431 {//-\r
39432 //[function TControl.WindowedParent]\r
39433 function TControl.WindowedParent: PControl;\r
39434 begin\r
39435   Result := fParent;\r
39436 end;}\r
39438 {$IFDEF ASM_VERSION}\r
39439 //[function TControl.ProcessMessage]\r
39440 function TControl.ProcessMessage: Boolean;\r
39441 const size_TMsg = sizeof( TMsg );\r
39442 asm\r
39443         PUSH      EBX\r
39444         XCHG      EBX, EAX\r
39446         ADD       ESP, -size_TMsg-4\r
39448         MOV       EDX, ESP\r
39449         PUSH      1\r
39450         XOR       ECX, ECX\r
39451         PUSH      ECX\r
39452         PUSH      ECX\r
39453         PUSH      ECX\r
39454         PUSH      EDX\r
39455         CALL      PeekMessage\r
39457         TEST      EAX, EAX\r
39458         JZ        @@exit\r
39460         MOV       EDX, [ESP].TMsg.message\r
39461         CMP       DX, WM_QUIT\r
39462         JNZ       @@tran_disp\r
39463         MOV       [AppletTerminated], 1\r
39464         JMP       @@fin\r
39466 @@tran_disp:\r
39467         MOV       ECX, [EBX].fExMsgProc\r
39468         JECXZ     @@do_tran_disp\r
39469         MOV       EAX, EBX\r
39470         MOV       EDX, ESP\r
39471         CALL      ECX\r
39472         TEST      AL, AL\r
39473         JNZ       @@fin\r
39475 @@do_tran_disp:\r
39476         MOV       EAX, ESP\r
39477         PUSH      EAX\r
39478         PUSH      EAX\r
39479         CALL      TranslateMessage\r
39480         CALL      DispatchMessage\r
39482 @@fin:\r
39483         MOV       AX, word ptr [ESP].TMsg.message\r
39484         TEST      AX, AX\r
39485         SETNZ     AL\r
39487 @@exit: ADD       ESP, size_TMsg+4\r
39488         POP       EBX\r
39489 end;\r
39490 {$ELSE ASM_VERSION} //Pascal\r
39491 function TControl.ProcessMessage: Boolean;\r
39492 var Msg: TMsg;\r
39493 begin\r
39494    Result := False;\r
39495    if PeekMessage( Msg, 0, 0, 0, PM_REMOVE ) then\r
39496    begin\r
39497       Result := Msg.message <> 0;\r
39498       if (Msg.message = WM_QUIT) then\r
39499         AppletTerminated := True\r
39500       else\r
39501       begin\r
39502         if not(Assigned( fExMsgProc ) and fExMsgProc( @Self, Msg )) then\r
39503         begin\r
39504           TranslateMessage( Msg );\r
39505           DispatchMessage( Msg );\r
39506         end;\r
39507       end;\r
39508    end;\r
39509 end;\r
39510 {$ENDIF ASM_VERSION}\r
39512 {$IFDEF ASM_VERSION}\r
39513 //[procedure TControl.ProcessMessages]\r
39514 procedure TControl.ProcessMessages;\r
39515 asm\r
39516 @@loo:  PUSH     EAX\r
39517         CALL     ProcessMessage\r
39518         DEC      AL\r
39519         POP      EAX\r
39520         JZ       @@loo\r
39521 end;\r
39522 {$ELSE ASM_VERSION} //Pascal\r
39523 procedure TControl.ProcessMessages;\r
39524 begin\r
39525   while ProcessMessage do ;\r
39526 end;\r
39527 {$ENDIF ASM_VERSION}\r
39529 //[procedure TControl.ProcessMessagesEx]\r
39530 procedure TControl.ProcessMessagesEx;\r
39531 begin\r
39532   PostMessage( GetWindowHandle, CM_PROCESS, 0, 0 );\r
39533   ProcessMessages;\r
39534 end;\r
39536 //[FUNCTION WndProcForm]\r
39537 {$IFDEF ASM_VERSION}\r
39538 function WndProcForm(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
39539 const szPaintStruct = sizeof(TPaintStruct);\r
39540 asm     //cmd    //opd\r
39541         CMP      word ptr [EDX].TMsg.message, WM_ENDSESSION\r
39542         JNE      @@chk_WM_SETFOCUS\r
39544         CMP      [EDX].TMsg.wParam, 0\r
39545         JZ       @@ret_false\r
39547         CALL     TObj.RefDec\r
39548         XOR      EAX, EAX\r
39549         MOV      [AppletRunning], AL\r
39550         XCHG     EAX, [Applet]\r
39551         INC      [AppletTerminated]\r
39553         CALL     TObj.Free\r
39554         CALL     System.@Halt0\r
39555         //-------\r
39557 @@chk_WM_SETFOCUS:\r
39558         CMP      word ptr [EDX].TMsg.message, WM_SETFOCUS\r
39559         JNE      @@ret_false\r
39561         PUSH     EBX\r
39562         PUSH     ESI\r
39563         XOR      EBX, EBX\r
39564         XCHG     ESI, EAX\r
39565       {$IFDEF FIX_MODAL_SETFOCUS}\r
39566         MOV      ECX, [ESI].TControl.fModalForm\r
39567         JECXZ    @@no_fix_modal_setfocus\r
39568         PUSH     [ECX].TControl.fHandle\r
39569         CALL     SetFocus\r
39570 @@no_fix_modal_setfocus:\r
39571       {$ENDIF}\r
39573         MOV      ECX, [ESI].TControl.FCurrentControl\r
39574         JECXZ    @@1\r
39575         INC      EBX\r
39576         XCHG     EAX, ECX\r
39578         // or CreateForm?\r
39579         PUSH     EAX\r
39580         CALL     CallTControlCreateWindow\r
39581         POP      EAX\r
39582         PUSH     [EAX].TControl.fHandle\r
39584         CALL     SetFocus\r
39585 @@1:    MOV      ECX, [Applet]\r
39586         JECXZ    @@ret_EBX\r
39587         CMP      ECX, ESI\r
39588         JE       @@ret_EBX\r
39589         MOV      [ECX].TControl.FCurrentControl, ESI\r
39590 @@ret_EBX:\r
39591         XCHG     EAX, EBX\r
39592         POP      ESI\r
39593         POP      EBX\r
39594         RET\r
39596 @@ret_false:\r
39597         XOR      EAX, EAX\r
39598 end;\r
39599 {$ELSE ASM_VERSION} //Pascal\r
39600 function WndProcForm(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
39601 var App: PControl;\r
39602 begin\r
39603   Result := True;\r
39604   with Self_{-}^{+} do\r
39605   case Msg.message of\r
39606   WM_ENDSESSION:\r
39607     begin\r
39608       if Msg.wParam <> 0 then\r
39609       begin\r
39610         Self_.RefDec;\r
39611         { Normally, WM_ENDSESSION is sent to a main form, not to Applet.\r
39612           Since we do not plan further working after handling this message,\r
39613           we decrease RefCount for the form (in was increased in EnumDynHandlers\r
39614           to prevent object destroying while its message processing is not\r
39615           finished). }\r
39616         App := Applet;\r
39617         //Rslt := 0; { We will not return any result at all. }\r
39618         {$IFDEF DEBUG_ENDSESSION}\r
39619         EndSession_Initiated := TRUE;\r
39620         LogFileOutput( GetStartDir + 'es_debug.txt',\r
39621                        'Self_=' + Int2Hex( DWORD( Self_ ), 8 ) +\r
39622                        ' Self_.Handle=' + Int2Str( Self_.FHandle ) );\r
39623         {$ENDIF}\r
39624         AppletTerminated := TRUE;\r
39625         AppletRunning := FALSE;\r
39626         Applet := nil;\r
39627         App.Free; { We provide OnDestroy handlers to be called for any objects here }\r
39628         Halt; { Stop further executing. }\r
39629       end else Result := FALSE;\r
39630     end;\r
39631   WM_SETFOCUS:\r
39632     begin\r
39633       {$IFDEF NEW_MODAL}\r
39634       if fModalForm <> nil then\r
39635         SetFocus( fModalForm.fHandle )\r
39636       else if ( FCurrentControl <> nil ) and not ( fCurrentControl.IsForm xor fIsApplet ) then\r
39637       {$ELSE not NEW_MODAL}\r
39638       if FCurrentControl <> nil then\r
39639       {$ENDIF}\r
39640       begin\r
39641         FCurrentControl.CreateWindow; //virtual!!!\r
39642         SetFocus( FCurrentControl.fHandle );\r
39643       end\r
39644       else\r
39645         Result := False;\r
39646       if assigned( Applet ) and (Applet <> Self_) then\r
39647          Applet.FCurrentControl := Self_;\r
39648     end;\r
39649   else Result := False;\r
39650   end;\r
39651 end;\r
39652 {$ENDIF ASM_VERSION}\r
39653 //[END WndProcForm]\r
39655 //[FUNCTION GetPrevCtrlBoundsRect]\r
39656 {$IFDEF ASM_VERSION}\r
39657 function GetPrevCtrlBoundsRect( P: PControl; var R: TRect ): Boolean;\r
39658 asm\r
39659         MOV       EDX, EBX\r
39660         MOV       EAX, [EBX].TControl.fParent\r
39661         TEST      EAX, EAX\r
39662         JZ        @@exit\r
39663           PUSH      EAX\r
39664         CALL      TControl.ChildIndex\r
39665         TEST      EAX, EAX\r
39666         XCHG      EDX, EAX\r
39667           POP       EAX\r
39668         JZ        @@exit\r
39669         DEC       EDX\r
39670         CALL      TControl.GetMembers\r
39672         POP       ECX  // retaddr\r
39673         ADD       ESP, -size_TRect\r
39674         MOV       EDX, ESP\r
39675         PUSH      ECX\r
39676         CALL      TControl.GetBoundsRect\r
39677         STC       // return CARRY\r
39678 @@exit:\r
39679 end;\r
39680 {$ELSE ASM_VERSION} //Pascal\r
39681 function GetPrevCtrlBoundsRect( P: PControl; var R: TRect ): Boolean;\r
39682 var Idx: Integer;\r
39683 begin\r
39684   Result := False;\r
39685   if P.FParent = nil then Exit;\r
39686   Idx := P.FParent.ChildIndex( P ) - 1;\r
39687   if Idx < 0 then Exit;\r
39688   Result := True;\r
39689   R := P.FParent.Children[ Idx ].BoundsRect;\r
39690 end;\r
39691 {$ENDIF ASM_VERSION}\r
39692 //[END GetPrevCtrlBoundsRect]\r
39694 {$IFDEF ASM_VERSION}\r
39695 //[function TControl.PlaceUnder]\r
39696 function TControl.PlaceUnder: PControl;\r
39697 asm\r
39698         PUSH      EBX\r
39699         XCHG      EBX, EAX\r
39700         CALL      GetPrevCtrlBoundsRect\r
39701         JNC       @@exit\r
39702         POP       EDX  // EDX = Left\r
39703         MOV       EAX, EBX\r
39704         CALL      TControl.SetLeft\r
39706         POP       EDX\r
39707         POP       EDX\r
39708         POP       EDX  // EDX = Bottom\r
39710         MOV       EAX, [EBX].fParent\r
39711         ADD       EDX, [EAX].fMargin\r
39713         MOV       EAX, EBX\r
39714         CALL      TControl.SetTop\r
39715 @@exit:\r
39716         XCHG      EAX, EBX\r
39717         POP       EBX\r
39718 end;\r
39719 {$ELSE ASM_VERSION} //Pascal\r
39720 function TControl.PlaceUnder: PControl;\r
39721 var R: TRect;\r
39722 begin\r
39723   Result := @Self;\r
39724   if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;\r
39725   Top := R.Bottom + fParent.fMargin;\r
39726   Left := R.Left;\r
39727 end;\r
39728 {$ENDIF ASM_VERSION}\r
39730 {$IFDEF ASM_VERSION}\r
39731 //[function TControl.PlaceDown]\r
39732 function TControl.PlaceDown: PControl;\r
39733 asm\r
39734         PUSH      EBX\r
39735         XCHG      EBX, EAX\r
39736         CALL      GetPrevCtrlBoundsRect\r
39737         JNC       @@exit\r
39738         POP       EDX\r
39739         POP       EDX\r
39740         POP       EDX\r
39741         POP       EDX  // EDX = Bottom\r
39743         MOV       EAX, [EBX].fParent\r
39744         ADD       EDX, [EAX].fMargin\r
39746         MOV       EAX, EBX\r
39747         CALL      TControl.SetTop\r
39748 @@exit:\r
39749         XCHG       EAX, EBX\r
39750         POP       EBX\r
39751 end;\r
39752 {$ELSE ASM_VERSION} //Pascal\r
39753 function TControl.PlaceDown: PControl;\r
39754 var R: TRect;\r
39755 begin\r
39756   Result := @Self;\r
39757   if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;\r
39758   Top := R.Bottom + fParent.fMargin;\r
39759 end;\r
39760 {$ENDIF ASM_VERSION}\r
39762 {$IFDEF ASM_VERSION}\r
39763 //[function TControl.PlaceRight]\r
39764 function TControl.PlaceRight: PControl;\r
39765 asm\r
39766         PUSH      EBX\r
39767         XCHG      EBX, EAX\r
39768         CALL      GetPrevCtrlBoundsRect\r
39769         JNC       @@exit\r
39770         POP       EDX\r
39771         POP       EDX  // EDX = Top\r
39772         MOV       EAX, EBX\r
39773         CALL      TControl.SetTop\r
39774         POP       EDX  // EDX = Right\r
39776         MOV       EAX, [EBX].fParent\r
39777         ADD       EDX, [EAX].fMargin\r
39779         POP       ECX\r
39780         MOV       EAX, EBX\r
39781         CALL      TControl.SetLeft\r
39782 @@exit:\r
39783         XCHG      EAX, EBX\r
39784         POP       EBX\r
39785 end;\r
39786 {$ELSE ASM_VERSION} //Pascal\r
39787 function TControl.PlaceRight: PControl;\r
39788 var R: TRect;\r
39789 begin\r
39790   Result := @Self;\r
39791   if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;\r
39792   Top := R.Top;\r
39793   Left := R.Right + fParent.fMargin;\r
39794 end;\r
39795 {$ENDIF ASM_VERSION}\r
39797 {$IFDEF ASM_VERSION}\r
39798 //[function TControl.SetSize]\r
39799 function TControl.SetSize(W, H: Integer): PControl;\r
39800 asm\r
39801         PUSH      EBX\r
39802         XCHG      EBX, EAX\r
39803         SUB  ESP, 16\r
39804         XCHG      EAX, EDX\r
39805         MOV  EDX, ESP\r
39806         PUSH      ECX // save H\r
39807         PUSH      EAX // save W\r
39808         MOV  EAX, EBX\r
39809         CALL GetBoundsRect\r
39810         POP       ECX // pop W\r
39811         JECXZ     @@nochg_W\r
39812         ADD       ECX, [ESP+4].TRect.Left\r
39813         MOV       [ESP+4].TRect.Right, ECX\r
39814 @@nochg_W:\r
39815         POP       ECX // pop H\r
39816         JECXZ     @@nochg_H\r
39817         ADD       ECX, [ESP].TRect.Top\r
39818         MOV       [ESP].TRect.Bottom, ECX\r
39819 @@nochg_H:\r
39820         MOV       EAX, EBX\r
39821         MOV       EDX, ESP\r
39822         CALL      TControl.SetBoundsRect\r
39823         ADD  ESP, 16\r
39824         XCHG      EAX, EBX\r
39825         POP       EBX\r
39826 end;\r
39827 {$ELSE ASM_VERSION} //Pascal\r
39828 function TControl.SetSize(W, H: Integer): PControl;\r
39829 var R: TRect;\r
39830 begin\r
39831   R := BoundsRect;\r
39832   if W > 0 then R.Right := R.Left + W;\r
39833   if H > 0 then R.Bottom := R.Top + H;\r
39834   SetBoundsRect( R );\r
39835   Result := @Self;\r
39836 end;\r
39837 {$ENDIF ASM_VERSION}\r
39839 //[function TControl.SetClientSize]\r
39840 function TControl.SetClientSize(W, H: Integer): PControl;\r
39841 begin\r
39842   if W > 0 then ClientWidth := W;\r
39843   if H > 0 then ClientHeight := H;\r
39844   Result := @Self;\r
39845 end;\r
39847 {$IFDEF ASM_VERSION}\r
39848 //[function TControl.AlignLeft]\r
39849 function TControl.AlignLeft(P: PControl): PControl;\r
39850 asm\r
39851         PUSH     EAX\r
39852         MOV      EAX, EDX\r
39853         CALL     TControl.GetLeft\r
39854         MOV      EDX, EAX\r
39855         POP      EAX\r
39856         PUSH     EAX\r
39857         CALL     TControl.SetLeft\r
39858         POP      EAX\r
39859 end;\r
39860 {$ELSE ASM_VERSION} //Pascal\r
39861 function TControl.AlignLeft(P: PControl): PControl;\r
39862 begin\r
39863   Result := @Self;\r
39864   Left := P.Left;\r
39865 end;\r
39866 {$ENDIF ASM_VERSION}\r
39868 {$IFDEF ASM_VERSION}\r
39869 //[function TControl.AlignTop]\r
39870 function TControl.AlignTop(P: PControl): PControl;\r
39871 asm\r
39872         PUSH     EAX\r
39873         MOV      EAX, EDX\r
39874         CALL     TControl.GetTop\r
39875         MOV      EDX, EAX\r
39876         POP      EAX\r
39877         PUSH     EAX\r
39878         CALL     TControl.SetTop\r
39879         POP      EAX\r
39880 end;\r
39881 {$ELSE ASM_VERSION} //Pascal\r
39882 function TControl.AlignTop(P: PControl): PControl;\r
39883 begin\r
39884   Result := @Self;\r
39885   Top := P.Top;\r
39886 end;\r
39887 {$ENDIF ASM_VERSION}\r
39889 //[FUNCTION WndProcCtrl]\r
39890 {$IFDEF ASM_VERSION} // see addition for combobox in pas version\r
39891 function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
39892 asm     //cmd    //opd\r
39893         PUSH     EBX\r
39894         XCHG     EBX, EAX\r
39895         PUSH     ESI\r
39896         PUSH     EDI\r
39897         MOV      EDI, EDX\r
39898         MOV      EDX, [EDI].TMsg.message\r
39900         SUB      DX, CN_CTLCOLORMSGBOX\r
39901         CMP      DX, CN_CTLCOLORSTATIC-CN_CTLCOLORMSGBOX\r
39902         JA       @@chk_CM_COMMAND\r
39903 @@2:\r
39904         PUSH     ECX\r
39905         MOV      EAX, [EBX].TControl.fTextColor\r
39906         CALL     Color2RGB\r
39907         XCHG     ESI, EAX\r
39908         PUSH     ESI\r
39909         PUSH     [EDI].TMsg.wParam\r
39910         CALL     SetTextColor\r
39911         CMP      [EBX].TControl.fTransparent, 0\r
39912         JZ       @@opaque\r
39914         PUSH     Windows.TRANSPARENT\r
39915         PUSH     [EDI].TMsg.wParam\r
39916         CALL     SetBkMode\r
39917         PUSH     NULL_BRUSH\r
39918         CALL     GetStockObject\r
39919         JMP      @@ret_rslt\r
39921 @@opaque:\r
39922         MOV      EAX, [EBX].TControl.fColor\r
39923         CALL     Color2RGB\r
39924         XCHG     ESI, EAX\r
39925         PUSH     OPAQUE\r
39926         PUSH     [EDI].TMsg.wParam\r
39927         CALL     SetBkMode\r
39928         PUSH     ESI\r
39929         PUSH     [EDI].TMsg.wParam\r
39930         CALL     SetBkColor\r
39932         MOV      EAX, EBX\r
39933         CALL     Global_GetCtlBrushHandle\r
39934 @@ret_rslt:\r
39935         XCHG     ECX, EAX\r
39936 @@tmpbrushready:\r
39937         POP      EAX\r
39938         MOV      [EAX], ECX\r
39939 @@ret_true:\r
39940         MOV      AL, 1\r
39942         JMP      @@ret_EAX\r
39944 @@chk_CM_COMMAND:\r
39945         CMP      word ptr [EDI].TMsg.message, CM_COMMAND\r
39946         JNE      @@chk_WM_SETFOCUS\r
39948         PUSH     ECX\r
39950         MOVZX    ECX, word ptr [EDI].TMsg.wParam+2\r
39951         CMP      CX, [EBX].TControl.fCommandActions.aClick\r
39952         JNE      @@chk_aEnter\r
39954         CMP      [EBX].TControl.fClickDisabled, 0\r
39955         JG       @@calldef\r
39956         MOV      EAX, EBX\r
39957         CALL     TControl.DoClick\r
39958         JMP      @@calldef\r
39960 @@chk_aEnter:\r
39961         LEA      EAX, [EBX].TControl.fOnEnter\r
39962         CMP      CX, [EBX].TControl.fCommandActions.aEnter\r
39963         JE       @@goEvent\r
39964         LEA      EAX, [EBX].TControl.fOnLeave\r
39965         CMP      CX, [EBX].TControl.fCommandActions.aLeave\r
39966         JE       @@goEvent\r
39967         LEA      EAX, [EBX].TControl.fOnChange\r
39968         CMP      CX, [EBX].TControl.fCommandActions.aChange\r
39969         JNE      @@chk_aSelChange\r
39970 @@goEvent:\r
39971         MOV      ECX, [EAX].TMethod.Code\r
39972         JECXZ    @@2calldef\r
39973         MOV      EAX, [EAX].TMethod.Data\r
39974         MOV      EDX, EBX\r
39975         CALL     ECX\r
39976 @@2calldef:\r
39977         JMP      @@calldef\r
39979 @@chk_aSelChange:\r
39980         CMP      CX, [EBX].TControl.fCommandActions.aSelChange\r
39981         JNE      @@chk_WM_SETFOCUS_1\r
39982         MOV      EAX, EBX\r
39983         CALL     TControl.DoSelChange\r
39985 @@calldef:\r
39986         XCHG     EAX, EBX\r
39987         MOV      EDX, EDI\r
39988         CALL     TControl.CallDefWndProc\r
39989         JMP      @@ret_rslt\r
39991 @@chk_WM_SETFOCUS_1:\r
39992         POP      ECX\r
39993 @@chk_WM_SETFOCUS:\r
39994         XOR      EAX, EAX\r
39995         CMP      word ptr [EDI].TMsg.message, WM_SETFOCUS\r
39996         JNE      @@ret_EAX\r
39998         MOV      [ECX], EAX\r
39999         MOV      EAX, EBX\r
40000         CALL     TControl.ParentForm\r
40001         TEST     EAX, EAX\r
40002         JZ       @@ret_true\r
40004         MOV      [EAX].TControl.FCurrentControl, EBX\r
40005         XOR      EAX, EAX\r
40007         PUSH     EDX\r
40008 @@2ret_EAX:\r
40009         POP      EDX\r
40011 @@ret_EAX:\r
40012         POP      EDI\r
40013         POP      ESI\r
40014         POP      EBX\r
40015 end;\r
40016 {$ELSE ASM_VERSION} //Pascal\r
40017 function WndProcCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;\r
40018 var F: PControl;\r
40019     Cmd : DWORD;\r
40020 begin\r
40021   //Result := FALSE;\r
40022   with Self_{-}^{+} do\r
40023   case Msg.message of\r
40024   CN_CTLCOLORMSGBOX..CN_CTLCOLORSTATIC:\r
40025        begin\r
40026          SetTextColor(Msg.WParam, Color2RGB(fTextColor));\r
40027          if fTransparent {AND (fPaintDC = Msg.wParam)} then\r
40028          begin\r
40029             SetBkMode( Msg.wParam, Windows.TRANSPARENT );\r
40030             Rslt := GetStockObject( NULL_BRUSH );\r
40031          end\r
40032             else\r
40033          begin\r
40034             SetBkMode( Msg.wParam, Windows.OPAQUE );\r
40035             SetBkColor(Msg.WParam, Color2RGB( fColor ) );\r
40036             Rslt := Global_GetCtlBrushHandle( Self_ );\r
40037          end;\r
40038          Result := TRUE;\r
40039        end;\r
40040   CM_COMMAND:\r
40041        begin\r
40042          Result := True;\r
40043          Cmd := HiWord( Msg.wParam );\r
40044          if Cmd = fCommandActions.aClick then\r
40045          begin\r
40046             if Integer( fClickDisabled ) <= 0 then\r
40047               DoClick;\r
40048          end else\r
40049          if Cmd = fCommandActions.aEnter then\r
40050          begin\r
40051             if Assigned( fOnEnter ) then fOnEnter( Self_ );\r
40052          end else\r
40053          if Cmd = fCommandActions.aLeave then\r
40054          begin\r
40055             if Assigned( fOnLeave ) then fOnLeave( Self_ );\r
40056          end else\r
40057          if Integer(Cmd) = fCommandActions.aChange then\r
40058          begin\r
40059             if Assigned( fOnChange ) then fOnChange( Self_ );\r
40060             //if fTransparent then Invalidate;\r
40061          end else\r
40062          if Integer(Cmd) = fCommandActions.aSelChange then\r
40063          begin\r
40064            DoSelChange;\r
40065            // if fTransparent then Invalidate;\r
40066          end\r
40067          else Result := False;\r
40069          if Result then\r
40070            Rslt := CallDefWndProc( Msg );\r
40072        end;\r
40074   WM_SETFOCUS:\r
40075        begin\r
40076          Rslt := 0;\r
40077          Result := TRUE;\r
40078          F := ParentForm;\r
40079          if F <> nil then\r
40080          begin\r
40081            F.fCurrentControl := Self_;\r
40082            Result := False; // go further handling\r
40083          end;\r
40084        end;\r
40085   {$IFDEF ESC_CLOSE_DIALOGS}\r
40086   //---------------------------------Babenko Alexey--------------------------\r
40087   WM_KEYDOWN:\r
40088          begin\r
40089            if (Self_.ParentForm.ExStyle and WS_EX_DLGMODALFRAME) <> 0 then\r
40090             if Msg.wParam = 27 then SendMessage(Self_.ParentForm.Handle, WM_CLOSE, 0, 0);\r
40091             result:=false;\r
40092          end;\r
40093   //---------------------------------Babenko Alexey-------------------------- \r
40094   {$ENDIF ESC_CLOSE_DIALOGS}\r
40095   else Result := False;\r
40096   end;\r
40097 end;\r
40098 {$ENDIF ASM_VERSION}\r
40099 //[END WndProcCtrl]\r
40101 //[FUNCTION WndProcPaint]\r
40102 {$IFDEF ASM_noVERSION}\r
40103 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
40104 const szPaintStruct = sizeof(TPaintStruct);\r
40105 asm     //cmd    //opd\r
40106         CMP      word ptr [EDX].TMsg.message, WM_PRINT\r
40107         JE       @@print\r
40108         CMP      word ptr [EDX].TMsg.message, WM_PAINT\r
40109         JNE      @@ret_false\r
40110 @@print:\r
40111         CMP      word ptr [EAX].TControl.fOnPaint.TMethod.Code+2, 0\r
40112         JE       @@ret_false\r
40113         PUSH     EBX\r
40114         PUSH     ESI\r
40116         XCHG     EBX, EAX\r
40117         MOV      ESI, EDX\r
40118         XOR      EAX, EAX\r
40119         PUSH     ECX\r
40120         PUSH     EAX\r
40121         PUSH     EAX\r
40122         PUSH     EAX\r
40123         PUSH     EAX\r
40124         CALL     CreateRectRgn\r
40125         MOV      [EBX].TControl.fUpdRgn, EAX\r
40127         MOVSX    EDX, [EBX].TControl.fEraseUpdRgn\r
40128         PUSH     EDX\r
40129         PUSH     EAX\r
40130         PUSH     [EBX].TControl.fHandle\r
40131         CALL     GetUpdateRgn\r
40133         CMP      EAX, 1\r
40134         JA       @@collectUpdRgn\r
40136         XOR      EAX, EAX\r
40137         XCHG     EAX, [EBX].TControl.fUpdRgn\r
40138         PUSH     EAX\r
40139         CALL     DeleteObject\r
40141 @@collectUpdRgn:\r
40142         MOV      ECX, [EBX].TControl.fCollectUpdRgn\r
40143         JECXZ    @@asg_fPaintDC\r
40144         XCHG     EAX, ECX\r
40145         MOV      ECX, [EBX].TControl.fUpdRgn\r
40146         JECXZ    @@asg_fPaintDC\r
40148         PUSH     RGN_OR\r
40149         PUSH     ECX\r
40150         PUSH     EAX\r
40151         PUSH     EAX\r
40152         CALL     CombineRgn\r
40154         DEC      EAX\r
40155         JNZ      @@invalidateRgn\r
40157         ADD      ESP, -16\r
40158         PUSH     ESP\r
40159         PUSH     [EBX].TControl.fHandle\r
40160         CALL     Windows.GetClientRect\r
40162         PUSH     [EBX].TControl.fCollectUpdRgn\r
40163         CALL     DeleteObject\r
40164         CALL     CreateRectRgn\r
40165         MOV      [EBX].TControl.fCollectUpdRgn, EAX\r
40167 @@invalidateRgn:\r
40168         MOVSX    EDX, [EBX].TControl.fEraseUpdRgn\r
40169         PUSH     EDX\r
40170         PUSH     [EBX].TControl.fCollectUpdRgn\r
40171         PUSH     [EBX].TControl.fHandle\r
40172         CALL     InvalidateRgn\r
40175 @@asg_fPaintDC:\r
40176         MOV      ECX, [ESI].TMsg.wParam\r
40177         INC      ECX\r
40178         LOOP     @@storePaintDC\r
40180         ADD      ESP, -szPaintStruct\r
40181         PUSH     ESP\r
40182         PUSH     [EBX].TControl.fHandle\r
40183         CALL     BeginPaint\r
40184         XCHG     ECX, EAX\r
40185 @@storePaintDC:\r
40186         MOV      [EBX].TControl.fPaintDC, ECX\r
40187         XCHG     EAX, ECX\r
40189         MOV      ECX, [EBX].TControl.fCollectUpdRgn\r
40190         JECXZ    @@doOnPaint\r
40192         PUSH     ECX\r
40193         PUSH     EAX\r
40194         CALL     SelectClipRgn\r
40196 @@doOnPaint:\r
40197         MOV      ECX, [EBX].TControl.fPaintDC\r
40198         MOV      EDX, EBX\r
40199         MOV      EAX, [EBX].TControl.fOnPaint.TMethod.Data\r
40200         CALL     dword ptr [EBX].TControl.fOnPaint.TMethod.Code\r
40202         MOV      ECX, [EBX].TControl.fCanvas\r
40203         JECXZ    @@e_paint\r
40205         XCHG     EAX, ECX\r
40206         XOR      EDX, EDX\r
40207         CALL     TCanvas.SetHandle\r
40209 @@e_paint:\r
40210         MOV      ECX, [ESI].TMsg.wParam\r
40211         INC      ECX\r
40212         LOOP     @@zero_fPaintDC\r
40214         PUSH     ESP\r
40215         PUSH     [EBX].TControl.fHandle\r
40216         CALL     EndPaint\r
40217         ADD      ESP, szPaintStruct\r
40219 @@zero_fPaintDC:\r
40220         XOR      ECX, ECX\r
40221         MOV      [EBX].TControl.fPaintDC, ECX\r
40223         POP      EAX\r
40224         MOV      [EAX], ECX\r
40226         XCHG     ECX, [EBX].TControl.fUpdRgn\r
40227         JECXZ    @@exit_True\r
40229         PUSH     ECX\r
40230         CALL     DeleteObject\r
40232 @@exit_True:\r
40233         POP      ESI\r
40234         POP      EBX\r
40235         MOV      AL, 1\r
40236         RET\r
40238 @@ret_false:\r
40239         XOR      EAX, EAX\r
40240 end;\r
40241 {$ELSE ASM_VERSION} //Pascal\r
40242 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
40243 var PaintStruct: TPaintStruct;\r
40244     CR: TRect;\r
40245     Cplxity: Integer;\r
40246     OldPaintDC: HDC;\r
40247 begin\r
40248   with Self_{-}^{+} do\r
40249   case Msg.message of\r
40250   WM_PRINT,\r
40251   WM_PAINT: if assigned( fOnPaint ) then\r
40252             begin\r
40253                fUpdRgn := CreateRectRgn( 0, 0, 0, 0 );\r
40254                Cplxity := Integer( GetUpdateRgn( fHandle, fUpdRgn, fEraseUpdRgn ) );\r
40255                if (Cplxity = NULLREGION) or (Cplxity = ERROR) then\r
40256                begin\r
40257                  DeleteObject( fUpdRgn );\r
40258                  fUpdRgn := 0;\r
40259                end;\r
40261                if (fCollectUpdRgn <> 0) and (fUpdRgn <> 0) then\r
40262                begin\r
40263                  if CombineRgn( fCollectUpdRgn, fCollectUpdRgn, fUpdRgn, RGN_OR )\r
40264                     = COMPLEXREGION then\r
40265                  begin\r
40266                    windows.GetClientRect( Self_.fHandle, CR );\r
40267                    DeleteObject( fCollectUpdRgn );\r
40268                    fCollectUpdRgn := CreateRectRgnIndirect( CR );\r
40269                  end;\r
40270                  InvalidateRgn( fHandle, fCollectUpdRgn, fEraseUpdRgn );\r
40271                end;\r
40273                OldPaintDC := fPaintDC;\r
40274                fPaintDC := Msg.wParam;\r
40275                if fPaintDC = 0 then\r
40276                  fPaintDC := BeginPaint( fHandle, PaintStruct );\r
40278                if fCollectUpdRgn <> 0 then\r
40279                  SelectClipRgn( fPaintDC, fCollectUpdRgn );\r
40281                fOnPaint( Self_, fPaintDC );\r
40283                if assigned( Self_.fCanvas ) then\r
40284                  Self_.fCanvas.SetHandle( 0 );\r
40286                if Msg.wParam = 0 then\r
40287                  EndPaint( fHandle, PaintStruct );\r
40288                fPaintDC := OldPaintDC;\r
40290                Rslt := 0;\r
40292                Result := True;\r
40293                if fUpdRgn <> 0 then\r
40294                  DeleteObject( fUpdRgn );\r
40295                fUpdRgn := 0;\r
40296                Exit;\r
40297             end;\r
40298   end;\r
40299   Result := FALSE;\r
40300 end;\r
40301 {$ENDIF ASM_VERSION}\r
40302 //[END WndProcPaint]\r
40304 //[procedure TControl.SetOnPaint]\r
40305 procedure TControl.SetOnPaint( const Value: TOnPaint );\r
40306 begin\r
40307   fOnPaint := Value;\r
40308   AttachProc( WndProcPaint );\r
40309 end;\r
40311 //*\r
40312 //[function WndProcEraseBkgnd]\r
40313 function WndProcEraseBkgnd( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
40314 var PaintStruct: TPaintStruct;\r
40315     OldPaintDC: HDC;\r
40316 begin\r
40317   Result := FALSE;\r
40318   if Msg.message = WM_ERASEBKGND then\r
40319   begin\r
40320     if Assigned( Sender.OnEraseBkgnd ) then\r
40321     begin\r
40322       OldPaintDC := Sender.fPaintDC;\r
40323       Sender.fPaintDC := Msg.wParam;\r
40324       if Sender.fPaintDC = 0 then\r
40325         Sender.fPaintDC := BeginPaint( Sender.fHandle, PaintStruct );\r
40326       Sender.OnEraseBkgnd( Sender, Msg.wParam );\r
40327       if Msg.wParam = 0 then\r
40328         EndPaint( Sender.fHandle, PaintStruct );\r
40329       if Assigned( Sender.fCanvas ) then\r
40330         Sender.fCanvas.SetHandle( 0 );\r
40331       Sender.fPaintDC := OldPaintDC;\r
40332       Rslt := 0;\r
40333       Result := TRUE;\r
40334     end\r
40335       else\r
40336       Rslt := 0;\r
40337   end;\r
40338 end;\r
40340 //[procedure TControl.SetOnEraseBkgnd]\r
40341 procedure TControl.SetOnEraseBkgnd(const Value: TOnPaint);\r
40342 begin\r
40343   fOnEraseBkgnd := Value;\r
40344   AttachProc( WndProcEraseBkgnd );\r
40345 end;\r
40347 //[FUNCTION WndProcGradient]\r
40348 {$IFDEF ASM_noVERSION}\r
40349 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
40350 const szPaintStruct = sizeof( TPaintStruct );\r
40351 asm     //cmd    //opd\r
40352         CMP      word ptr [EDX].TMsg.message, WM_PRINTCLIENT\r
40353         JE       @@print\r
40354         CMP      word ptr [EDX].TMsg.message, WM_PAINT\r
40355         JNE      @@ret_false\r
40356 @@print:\r
40357         PUSHAD\r
40358         XCHG     EDI, EAX\r
40359         MOV      ESI, EDX\r
40360         XOR      EAX, EAX\r
40361         MOV      [ECX], EAX\r
40362         OR       EAX, [ESI].TMsg.wParam\r
40363         JNZ      @@1\r
40364         ADD      ESP, -szPaintStruct\r
40365         PUSH     ESP\r
40366         PUSH     [EDI].TControl.fHandle\r
40367         CALL     BeginPaint\r
40368 @@1:    MOV      [EDI].TControl.fPaintDC, EAX\r
40369         ADD      ESP, -16\r
40370         MOV      EDX, ESP\r
40371         MOV      EAX, EDI\r
40372         CALL     TControl.ClientRect\r
40373         MOV      EAX, [EDI].TControl.fColor1\r
40374         CALL     Color2RGB\r
40375         XCHG     EBX, EAX\r
40376         MOV      EAX, [EDI].TControl.fColor2\r
40377         CALL     Color2RGB\r
40378         MOV      EBP, [ESP].TRect.Bottom\r
40379 @@loo:\r
40380         MOV      EDX, [ESP].TRect.Top\r
40381         CMP      EBP, EDX\r
40382         JLE      @@e_loo\r
40383         INC      EDX\r
40384         MOV      [ESP].TRect.Bottom, EDX\r
40386         INC      EBP\r
40387         PUSH     EAX\r
40389         PUSH     EAX\r
40390         {SUB      AL, BL\r
40391         MOV      AH, 0\r
40393         CWDE}\r
40394         AND      EAX, $FF\r
40395         MOV      EDX, EBX\r
40396         AND      EDX, $FF\r
40397         SUB      EAX, EDX\r
40400         MOV      ECX, [ESP+8].TRect.Top\r
40401         IMUL     ECX\r
40402         IDIV     EBP\r
40403         XOR      EDX, EDX\r
40404         ADD      AL, BL\r
40405         MOV      AH, 0\r
40406         CWDE\r
40407         XCHG     [ESP], EAX\r
40409         PUSH     EAX\r
40410         {SUB      AH, BH\r
40411         MOV      AL, AH\r
40412         MOV      AH, 0\r
40414         CWDE}\r
40415         SHR      EAX, 8\r
40416         AND      EAX, $FF\r
40417         MOV      EDX, EBX\r
40418         SHR      EDX, 8\r
40419         AND      EDX, $FF\r
40420         SUB      EAX, EDX\r
40422         IMUL     ECX\r
40423         IDIV     EBP\r
40424         ADD      AL, BH\r
40425         AND      EAX, $FF\r
40426         SHL      EAX, 8\r
40427         XCHG     [ESP], EAX\r
40429         SHR      EAX, 16\r
40430         MOV      EDX, EBX\r
40431         SHR      EDX, 16\r
40432         PUSH     EDX\r
40433         SUB      EAX, EDX\r
40434         IMUL     ECX\r
40435         IDIV     EBP\r
40436         POP      EDX\r
40437         //AND      EAX, $FF00\r
40438         ADD      EAX, EDX\r
40439         SHL      EAX, 16\r
40441         POP      EDX\r
40442         MOV      AH, DH\r
40443         POP      EDX\r
40444         MOV      AL, DL\r
40446         PUSH     EAX\r
40447         CALL     CreateSolidBrush\r
40449         PUSH     EAX\r
40451         PUSH     EAX\r
40452         LEA      EDX, [ESP+12]\r
40453         PUSH     EDX\r
40454         PUSH     [EDI].TControl.fPaintDC\r
40455         CALL     Windows.FillRect\r
40457         CALL     DeleteObject\r
40459         POP      EAX\r
40460         DEC      EBP\r
40461         INC      [ESP].TRect.Top\r
40462         JMP      @@loo\r
40463 @@e_loo:\r
40464         ADD      ESP, 16\r
40465         MOV      ECX, [ESI].TMsg.wParam\r
40466         INC      ECX\r
40467         LOOP     @@2\r
40468         PUSH     ESP\r
40469         PUSH     [EDI].TControl.fHandle\r
40470         CALL     EndPaint\r
40471         ADD      ESP, szPaintStruct\r
40472 @@2:    XOR      EAX, EAX\r
40473         MOV      [EDI].TControl.fPaintDC, EAX\r
40474         POPAD\r
40475         MOV      Al, 1\r
40476         RET\r
40477 @@ret_false:\r
40478         XOR      EAX, EAX\r
40479 end;\r
40480 {$ELSE ASM_VERSION} //Pascal\r
40481 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
40482 var PaintStruct: TPaintStruct;\r
40483     Bmp: PBitmap;\r
40484     CR: TRect;\r
40485     I: Integer;\r
40486     R, G, B: Integer;\r
40487     R1, G1, B1: Integer;\r
40488     C: TColor;\r
40489     W, H, WH: Integer;\r
40490     W9x: Boolean;\r
40491     Br: HBrush;\r
40492     //Save: Integer;\r
40493     OldPaintDC: HDC;\r
40494 begin\r
40495   case Msg.message of\r
40496   WM_PAINT, WM_PRINTCLIENT:\r
40497             begin\r
40498                OldPaintDC := Self_.fPaintDC;\r
40499                Self_.fPaintDC := Msg.wParam;\r
40500                if Self_.fPaintDC = 0 then\r
40501                   Self_.fPaintDC := BeginPaint( Self_.fHandle, PaintStruct );\r
40502                CR := Self_.ClientRect;\r
40503                W9x := WinVer < wvNT;\r
40504                W := 1;\r
40505                H := CR.Bottom;\r
40506                WH := H;\r
40507                Bmp := nil;\r
40508                if Self_.fGradientStyle = gsHorizontal then\r
40509                begin\r
40510                  W := CR.Right;\r
40511                  H := 1;\r
40512                  WH := W;\r
40513                end;\r
40514                if not W9x then\r
40515                  Bmp := NewDIBBitmap( W, H, pf32bit );\r
40516                C := Color2RGB( Self_.fColor1 );\r
40517                R := C shr 16;\r
40518                G := (C shr 8) and $FF;\r
40519                B := C and $FF;\r
40520                C := Color2RGB( Self_.fColor2 );\r
40521                R1 := C shr 16;\r
40522                G1 := (C shr 8) and $FF;\r
40523                B1 := C and $FF;\r
40524                for I := 0 to WH-1 do\r
40525                begin\r
40526                  C := ((( R + (R1 - R) * I div WH ) and $FF) shl 16) or\r
40527                       ((( G + (G1 - G) * I div WH ) and $FF) shl 8) or\r
40528                       ( B + (B1 - B) * I div WH ) and $FF;\r
40529                  if W9x then\r
40530                  begin\r
40531                    if Self_.fGradientStyle = gsVertical then\r
40532                      CR.Bottom := CR.Top + 1\r
40533                    else\r
40534                      CR.Right := CR.Left + 1;\r
40535                    Br := CreateSolidBrush( C );\r
40536                    Windows.FillRect( Self_.fPaintDC, CR, Br );\r
40537                    DeleteObject( Br );\r
40538                    if Self_.fGradientStyle = gsVertical then\r
40539                      Inc( CR.Top )\r
40540                    else\r
40541                      Inc( CR.Left );\r
40542                  end\r
40543                    else\r
40544                  begin\r
40545                    if Self_.fGradientStyle = gsVertical then\r
40546                      Bmp.DIBPixels[ 0, I ] := C\r
40547                    else\r
40548                      Bmp.DIBPixels[ I, 0 ] := C;\r
40549                  end;\r
40550                end;\r
40551                if not W9x then\r
40552                begin\r
40553                  SetStretchBltMode( Self_.fPaintDC, HALFTONE );\r
40554                  SetBrushOrgEx( Self_.fPaintDC, 0, 0, nil );\r
40555                  StretchBlt( Self_.fPaintDC, 0, 0, CR.Right, CR.Bottom, Bmp.Canvas.Handle,\r
40556                              0, 0, W, H, SRCCOPY );\r
40557                  Bmp.Free;\r
40558                end;\r
40559                if Msg.wParam = 0 then\r
40560                  EndPaint( Self_.fHandle, PaintStruct );\r
40561                Self_.fPaintDC := OldPaintDC;\r
40562                Rslt := 0;\r
40563                Result := True;\r
40564                Exit;\r
40565             end;\r
40566   end;\r
40567   Result := False;\r
40568 end;\r
40569 {$ENDIF ASM_VERSION}\r
40570 //[END WndProcGradient]\r
40572 //[function WndProcGradientEx]\r
40573 function WndProcGradientEx( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
40574   function Ceil( X: Double ): Integer;\r
40575   begin\r
40576     Result := Round( X ) + 1;\r
40577   end;\r
40578 const\r
40579   SQRT2 = 1.4142135623730950488016887242097;\r
40580 var\r
40581   RC, R0: TRect;\r
40582   C, C2: TColor;\r
40583   R1, G1, B1: Integer;\r
40584   R2, G2, B2: Integer;\r
40585   DX1, DX2, DY1, DY2, DR, DG, DB, K: Double;\r
40586   PaintStruct: TPaintStruct;\r
40587   I: Integer;\r
40588   Br: HBrush;\r
40589   Rgn: HRgn;\r
40590   Poly: array[ 0..3 ] of TPoint;\r
40591   OldPaintDC: HDC;\r
40592   fX1, fX2, fY1, fY2: Double;\r
40594   procedure OffsetF( DX, DY: Double );\r
40595   begin\r
40596     fX1 := fX1 + DX;\r
40597     fX2 := fX2 + DX;\r
40598     fY1 := fY1 + DY;\r
40599     fY2 := fY2 + DY;\r
40600   end;\r
40601 begin\r
40602   Result := FALSE;\r
40603   if (Msg.message <> WM_PAINT) and (Msg.message <> WM_PRINTCLIENT) then Exit;\r
40604   if Self_.fGradientStyle in [ gsHorizontal, gsVertical ] then\r
40605   begin\r
40606     Result := WndProcGradient( Self_, Msg, Rslt );\r
40607     Exit;\r
40608   end;\r
40609   C := Color2RGB( Self_.fColor2 );\r
40610   R2 := C and $FF;\r
40611   G2 := (C shr 8) and $FF;\r
40612   B2 := (C shr 16) and $FF;\r
40613   C := Color2RGB( Self_.fColor1 );\r
40614   R1 := C and $FF;\r
40615   G1 := (C shr 8) and $FF;\r
40616   B1 := (C shr 16) and $FF;\r
40617   DR := (R2 - R1) / 256;\r
40618   DG := (G2 - G1) / 256;\r
40619   DB := (B2 - B1) / 256;\r
40620   OldPaintDC := Self_.fPaintDC;\r
40621   Self_.fPaintDC := Msg.wParam;\r
40622   if Self_.fPaintDC = 0 then\r
40623     Self_.fPaintDC := BeginPaint( Self_.fHandle, PaintStruct );\r
40624   RC := Self_.ClientRect;\r
40625   fX1 := 0;\r
40626   fY1 := 0;\r
40627   case Self_.fGradientStyle of\r
40628   gsRombic:\r
40629     //RF := MakeRect( 0, 0, RC.Right div 128, RC.Bottom div 128 );\r
40630     begin\r
40631       fX2 := RC.Right / 128;\r
40632       fY2 := RC.Bottom / 128;\r
40633     end;\r
40634   gsElliptic:\r
40635     //RF := MakeRect( 0, 0, Ceil( RC.Right / 256 * SQRT2 ), Ceil( RC.Bottom / 256 * SQRT2 ) );\r
40636     begin\r
40637       fX2 := RC.Right / 256 * SQRT2;\r
40638       fY2 := RC.Bottom / 256 * SQRT2;\r
40639     end;\r
40640   else\r
40641     //RF := MakeRect( 0, 0, RC.Right div 256, RC.Bottom div 256 );\r
40642     begin\r
40643       fX2 := RC.Right / 256;\r
40644       fY2 := RC.Bottom / 256;\r
40645     end;\r
40646   end;\r
40647   case Self_.fGradientStyle of\r
40648   gsRectangle, gsRombic, gsElliptic:\r
40649     begin\r
40650       case Self_.FGradientLayout of\r
40651       glCenter, glTop, glBottom:\r
40652         //OffsetRect( RF, (RC.Right - RF.Right) div 2, 0 );\r
40653         OffsetF( (RC.Right - fX2) / 2, 0 );\r
40654       glTopRight, glBottomRight, glRight:\r
40655         //OffsetRect( RF, RC.Right - RF.Right div 2, 0 );\r
40656         OffsetF( RC.Right - fX2 / 2, 0 );\r
40657       glTopLeft, glBottomLeft, glLeft:\r
40658         //OffsetRect( RF, -RF.Right div 2, 0 );\r
40659         OffsetF( -fX2 / 2, 0 );\r
40660       end;\r
40661       case Self_.FGradientLayout of\r
40662       glCenter, glLeft, glRight:\r
40663         //OffsetRect( RF, 0, (RC.Bottom - RF.Bottom) div 2 );\r
40664         OffsetF( 0, (RC.Bottom - fY2) / 2 );\r
40665       glBottom, glBottomLeft, glBottomRight:\r
40666         //OffsetRect( RF, 0, RC.Bottom - RF.Bottom div 2 );\r
40667         OffsetF( 0, RC.Bottom - fY2 / 2 );\r
40668       glTop, glTopLeft, glTopRight:\r
40669         //OffsetRect( RF, 0, -RF.Bottom div 2 );\r
40670         OffsetF( 0, -fY2 / 2 )\r
40671       end;\r
40672     end;\r
40673   end;\r
40674   DX1 := -fX1 / 255; //(-RF.Left) / 255;\r
40675   DY1 := -fY1 / 255; // (-RF.Top) / 255;\r
40676   DX2 := (RC.Right - fX2) / 255; //(RC.Right - RF.Right) / 255;\r
40677   DY2 := (RC.Bottom - fY2) / 255;\r
40678   case Self_.fGradientStyle of\r
40679   gsRombic, gsElliptic:\r
40680     begin\r
40681       if DX2 < -DX1 then DX2 := -DX1;\r
40682       if DY2 < -DY1 then DY2 := -DY1;\r
40683       K := 2;\r
40684       if Self_.fGradientStyle = gsElliptic then K := SQRT2;\r
40685       DX2 := DX2 * K;\r
40686       DY2 := DY2 * K;\r
40687       DX1 := -DX2;\r
40688       DY1 := -DY2;\r
40689     end;\r
40690   end;\r
40691   C2 := C;\r
40692   for I := 0 to 255 do\r
40693   begin\r
40694     if (I < 255) then\r
40695     begin\r
40696       C2 := TColor( (( Ceil( B1 + DB * (I+1) ) and $FF) shl 16) or\r
40697           (( Ceil( G1 + DG * (I+1) ) and $FF) shl 8) or\r
40698            Ceil( R1 + DR * (I+1) ) and $FF );\r
40699       if (Self_.fGradientStyle in [gsRombic,gsElliptic,gsRectangle]) and\r
40700          (C2 = C) then continue;\r
40701     end;\r
40702     Br := CreateSolidBrush( C );\r
40703     R0 := MakeRect( Ceil( fX1 + DX1 * I ),\r
40704                     Ceil( fY1 + DY1 * I ),\r
40705                     Ceil( fX2 + DX2 * I ) + 1,\r
40706                     Ceil( fY2 + DY2 * I ) + 1 );\r
40707     Rgn := 0;\r
40708     case Self_.fGradientStyle of\r
40709     gsRectangle:\r
40710       Rgn := CreateRectRgnIndirect( R0 );\r
40711     gsRombic:\r
40712       begin\r
40713         Poly[ 0 ].x := R0.Left;\r
40714         Poly[ 0 ].y := R0.Top + (R0.Bottom - R0.Top) div 2;\r
40715         Poly[ 1 ].x := R0.Left + (R0.Right - R0.Left) div 2;\r
40716         Poly[ 1 ].y := R0.Top;\r
40717         Poly[ 2 ].x := R0.Right;\r
40718         Poly[ 2 ].y := Poly[ 0 ].y;\r
40719         Poly[ 3 ].x := Poly[ 1 ].x;\r
40720         Poly[ 3 ].y := R0.Bottom;\r
40721         Rgn := CreatePolygonRgn( Poly[ 0 ].x, 4, ALTERNATE );\r
40722       end;\r
40723     gsElliptic:\r
40724       Rgn := CreateEllipticRgnIndirect( R0 );\r
40725     end;\r
40726     if Rgn <> 0 then\r
40727     begin\r
40728       if Rgn <> NULLREGION then\r
40729       begin\r
40730         Windows.FillRgn( Self_.fPaintDC, Rgn, Br );\r
40731         ExtSelectClipRgn( Self_.fPaintDC, Rgn, RGN_DIFF );\r
40732       end;\r
40733       DeleteObject( Rgn );\r
40734     end;\r
40735     DeleteObject( Br );\r
40736     C := C2;\r
40737   end;\r
40738   if Self_.fPaintDC <> HDC( Msg.wParam ) then\r
40739     EndPaint( Self_.fHandle, PaintStruct );\r
40740   Self_.fPaintDC := OldPaintDC;\r
40741   Rslt := 0;\r
40742   Result := True;\r
40743 end;\r
40745 //*\r
40746 //[function WndProcLabelEffect]\r
40747 function WndProcLabelEffect( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
40748 var\r
40749     Sz: TSize;\r
40750     P0: TPoint;\r
40751     CR: TRect;\r
40752     B : Boolean;\r
40753     CShadow: TColor;\r
40754     Target: PCanvas;\r
40755     Txt: String;\r
40756     LCaption: PChar;\r
40757     OldPaintDC: HDC;\r
40759     procedure doTextOut( shfx, shfy: Integer; col: TColor );\r
40760     begin\r
40761         SetTextColor( Target.fHandle, col );\r
40762         Windows.ExtTextOut( Target.fHandle, P0.x + shfx, P0.y + shfy,\r
40763                             ETO_CLIPPED, @CR,\r
40764                             PChar(Txt), Length(Txt), nil );\r
40765         //GDIFlush; // for test only\r
40766     end;\r
40768 var I, J, Istp : Integer;\r
40769     PS: TPaintStruct;\r
40770     //DoEndPaint: Boolean;\r
40771 begin\r
40772   Result := False;\r
40774   case Msg.message of\r
40776   WM_SETTEXT:\r
40777     begin\r
40778       LCaption := PChar( Msg.lParam );\r
40779       if LCaption <> Self_.fCaption then\r
40780       begin\r
40781         if Self_.fCaption <> nil then\r
40782            FreeMem( Self_.fCaption );\r
40783         GetMem( Self_.fCaption, StrLen( LCaption ) + 1 );\r
40784         StrCopy( Self_.fCaption, LCaption );\r
40785       end;\r
40786       Result := True;\r
40787       Rslt := 1;\r
40788       Exit;\r
40789     end;\r
40791   WM_PRINTCLIENT, WM_PAINT:\r
40792   begin\r
40793     OldPaintDC := Self_.fPaintDC;\r
40794     Self_.fPaintDC := Msg.wParam;\r
40795     if Self_.fPaintDC = 0 then\r
40796       Self_.fPaintDC := BeginPaint( Self_.fHandle, PS );\r
40797     begin\r
40798        Target := Self_.Canvas;\r
40799        Txt := Self_.fCaption;\r
40800        Target.TextArea( Txt, Sz, P0 );\r
40801        if Self_.fShadowDeep <> 0 then\r
40802        begin\r
40803          for B := False to Self_.fCtl3D do\r
40804          begin\r
40805            Inc( Sz.cx, Abs( Self_.fShadowDeep ) );\r
40806            Inc( Sz.cy, Abs( Self_.fShadowDeep ) );\r
40807          end;\r
40808        end;\r
40809        CR := Self_.ClientRect;\r
40810        case Self_.fTextAlign of\r
40811        taCenter: P0.x := P0.x + (CR.Right - Sz.cx) div 2;\r
40812        taRight:  P0.x := P0.x + (CR.Right - Sz.cx);\r
40813        end;\r
40814        case Self_.fVerticalAlign of\r
40815        vaCenter: P0.y := P0.y + (CR.Bottom - Sz.cy) div 2;\r
40816        vaBottom: P0.y := P0.y + (CR.Bottom - Sz.cy);\r
40817        end;\r
40818        if Self_.fShadowDeep <> 0 then\r
40819        begin\r
40820          if Self_.fColor2 = clNone then\r
40821            CShadow := ColorsMix(Color2RGB(Self_.fTextColor),Color2RGB(Self_.fColor2))\r
40822          else\r
40823            CShadow := Color2RGB( Self_.fColor2 );\r
40824          if not Self_.fTransparent then\r
40825            Target.FillRect( CR ); // GDIFlush; for test only\r
40826          //Target.DeselectHandles;\r
40827          Target.RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
40828          SetBkMode( Target.fHandle, Windows.TRANSPARENT );\r
40829          if Self_.fCtl3D then\r
40830          begin\r
40831            I := - Self_.fShadowDeep;\r
40832            Istp := 1;\r
40833            if Self_.ShadowDeep > 0 then Istp := -1;\r
40834            repeat\r
40835              J := - Self_.fShadowDeep;\r
40836              repeat\r
40837                if not ( (I=0) and (J=0) ) then\r
40838                begin\r
40839                  if (I * Istp < 0) and (J * Istp < 0) then\r
40840                  begin\r
40841                     doTextOut( I, J, CShadow );\r
40842                  end;\r
40843                end;\r
40844                J := J - Istp;\r
40845              until J = Self_.fShadowDeep - IStp;\r
40846              I := I - Istp;\r
40847            until I = Self_.fShadowDeep - IStp;\r
40848          end\r
40849             else\r
40850          doTextout( Self_.fShadowDeep, Self_.fShadowdeep, CShadow );\r
40851          doTextout( 0, 0, Color2RGB(Self_.fTextColor) );\r
40852        end\r
40853           else\r
40854        begin\r
40855          //Target.DeselectHandles;\r
40856          Target.RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );\r
40857          SetBkMode( Target.fHandle, Windows.TRANSPARENT );\r
40858          //Target.TextRect( CR, P0.x, P0.y, Txt );\r
40859          doTextout( 0, 0, Color2RGB(Self_.fTextColor) );\r
40860        end;\r
40861     end;\r
40862     if assigned( Self_.fCanvas ) then\r
40863       Self_.fCanvas.SetHandle( 0 );\r
40864     if MSg.wParam = 0 then\r
40865       EndPaint( Self_.fHandle, PS );\r
40866     Self_.fPaintDC := OldPaintDC;\r
40867     Rslt := 0;\r
40868     Result := True;\r
40869     Exit;\r
40870     end;\r
40871   end;\r
40872 end;\r
40874 {$IFDEF ASM_VERSION}\r
40875 //[procedure TControl.DoClick]\r
40876 procedure TControl.DoClick;\r
40877 asm\r
40878         PUSH     EAX\r
40879         CALL     [EAX].fControlClick\r
40880         POP      EDX\r
40882         MOV      ECX, [EDX].fOnClick.TMethod.Code\r
40883         JECXZ    @@exit\r
40884         MOV      EAX, [EDX].fOnClick.TMethod.Data\r
40885         CALL     ECX\r
40886 @@exit:\r
40887 end;\r
40888 {$ELSE ASM_VERSION} //Pascal\r
40889 procedure TControl.DoClick;\r
40890 begin\r
40891   fControlClick( @Self );\r
40892   if Assigned( fOnClick ) then\r
40893      fOnClick( @Self );\r
40894 end;\r
40895 {$ENDIF ASM_VERSION}\r
40897 {$IFDEF ASM_VERSION}\r
40898 //[function TControl.ParentForm]\r
40899 function TControl.ParentForm: PControl;\r
40900 asm\r
40901 @@1:    CMP      [EAX].fIsControl, 0\r
40902         JZ       @@exit\r
40903         MOV      EAX, [EAX].fParent\r
40904         TEST     EAX, EAX\r
40905         JNZ      @@1\r
40906 @@exit:\r
40907 end;\r
40908 {$ELSE ASM_VERSION} //Pascal\r
40909 function TControl.ParentForm: PControl;\r
40910 begin\r
40911   Result := @Self;\r
40912   if Result.fIsControl then\r
40913   repeat\r
40914     Result := Result.fParent;\r
40915   until (Result = nil) or not Result.fIsControl;\r
40916 end;\r
40917 {$ENDIF ASM_VERSION}\r
40919 {$IFDEF ASM_VERSION}\r
40920 //[procedure TControl.SetProgressColor]\r
40921 procedure TControl.SetProgressColor(const Value: TColor);\r
40922 asm\r
40923         PUSH     EDX\r
40924         PUSH     EAX\r
40925         MOV      EAX, EDX\r
40926         CALL     Color2RGB\r
40927         POP      EDX\r
40928         PUSH     EDX\r
40929         PUSH     EAX\r
40930         PUSH     0\r
40931         PUSH     PBM_SETBARCOLOR\r
40932         PUSH     EDX\r
40933         CALL     Perform\r
40934         TEST     EAX, EAX\r
40935         POP      EAX\r
40936         POP      EDX\r
40937         JZ       @@exit\r
40938         MOV      [EAX].fTextColor, EDX\r
40939 @@exit:\r
40940 end;\r
40941 {$ELSE ASM_VERSION} //Pascal\r
40942 procedure TControl.SetProgressColor(const Value: TColor);\r
40943 begin\r
40944   if Perform( PBM_SETBARCOLOR, 0, Color2RGB(Value) ) <> 0 then\r
40945     fTextColor := Value;\r
40946 end;\r
40947 {$ENDIF ASM_VERSION}\r
40949 //[procedure TControl.SetShadowDeep]\r
40950 procedure TControl.SetShadowDeep(const Value: Integer);\r
40951 begin\r
40952   fShadowDeep := Value;\r
40953   Invalidate;\r
40954 end;\r
40956 {$IFDEF ASM_VERSION}\r
40957 //[function TControl.GetFont]\r
40958 function TControl.GetFont: PGraphicTool;\r
40959 asm\r
40960         MOV      ECX, [EAX].FFont\r
40961         INC      ECX\r
40962         LOOP     @@exit\r
40963         PUSH     EAX\r
40964         CALL     NewFont\r
40965         POP      EDX\r
40966         MOV      [EDX].FFont, EAX\r
40967         MOV      ECX, [EDX].fTextColor\r
40968         MOV      [EAX].TGraphicTool.fData.Color, ECX\r
40969         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[FontChanged]\r
40970         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX\r
40971         RET\r
40972 @@exit: XCHG     EAX, ECX\r
40973 end;\r
40974 {$ELSE ASM_VERSION} //Pascal\r
40975 function TControl.GetFont: PGraphicTool;\r
40976 begin\r
40977   if FFont = nil then\r
40978   begin\r
40979      FFont := NewFont;\r
40980      FFont.fData.Color := fTextColor;\r
40981      FFont.OnChange := FontChanged;\r
40982   end;\r
40983   Result := FFont;\r
40984 end;\r
40985 {$ENDIF ASM_VERSION}\r
40987 {$IFDEF ASM_VERSION}\r
40988 //[function TControl.GetBrush]\r
40989 function TControl.GetBrush: PGraphicTool;\r
40990 asm\r
40991         MOV      ECX, [EAX].FBrush\r
40992         INC      ECX\r
40993         LOOP     @@exit\r
40994         PUSH     EAX\r
40995         CALL     NewBrush\r
40996         POP      EDX\r
40997         MOV      [EDX].FBrush, EAX\r
40998         MOV      ECX, [EDX].fColor\r
40999         MOV      [EAX].TGraphicTool.fData.Color, ECX\r
41000         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[BrushChanged]\r
41001         MOV      [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX\r
41002         RET\r
41003 @@exit: XCHG     EAX, ECX\r
41004 end;\r
41005 {$ELSE ASM_VERSION} //Pascal\r
41006 function TControl.GetBrush: PGraphicTool;\r
41007 begin\r
41008   if FBrush = nil then\r
41009   begin\r
41010     FBrush := NewBrush;\r
41011     FBrush.fData.Color := fColor;\r
41012     FBrush.OnChange := BrushChanged;\r
41013   end;\r
41014   Result := FBrush;\r
41015 end;\r
41016 {$ENDIF ASM_VERSION}\r
41018 {$IFDEF ASM_VERSION}\r
41019 //[procedure TControl.FontChanged]\r
41020 procedure TControl.FontChanged(Sender: PGraphicTool);\r
41021 asm\r
41022         MOV      ECX, [EDX].TGraphicTool.fData.Color\r
41023         MOV      [EAX].fTextColor, ECX\r
41024         PUSH     EAX\r
41025         CALL     ApplyFont2Wnd\r
41026         POP      EAX\r
41027         CALL     Invalidate\r
41028 end;\r
41029 {$ELSE ASM_VERSION} //Pascal\r
41030 procedure TControl.FontChanged(Sender: PGraphicTool);\r
41031 begin\r
41032   fTextColor := Sender.fData.Color;\r
41033   ApplyFont2Wnd;\r
41034   Invalidate;\r
41035 end;\r
41036 {$ENDIF ASM_VERSION}\r
41038 {$IFDEF ASM_VERSION}\r
41039 //[procedure TControl.BrushChanged]\r
41040 procedure TControl.BrushChanged(Sender: PGraphicTool);\r
41041 asm\r
41042         MOV      ECX, [EDX].TGraphicTool.fData.Color\r
41043         MOV      [EAX].fColor, ECX\r
41044         XOR      ECX, ECX\r
41045         XCHG     ECX, [EAX].fTmpBrush\r
41046         JECXZ    @@inv\r
41047         PUSH     EAX\r
41048         PUSH     ECX\r
41049         CALL     DeleteObject\r
41050         POP      EAX\r
41051 @@inv:  CALL     Invalidate\r
41052 end;\r
41053 {$ELSE ASM_VERSION} //Pascal\r
41054 procedure TControl.BrushChanged(Sender: PGraphicTool);\r
41055 begin\r
41056   fColor := Sender.fData.Color;\r
41057   if fTmpBrush <> 0 then\r
41058   begin\r
41059     DeleteObject( fTmpBrush );\r
41060     fTmpBrush := 0;\r
41061   end;\r
41062   if fPaintDC = 0 then\r
41063   // only if not in painting already :\r
41064     Invalidate;\r
41065 end;\r
41066 {$ENDIF ASM_VERSION}\r
41068 {$IFDEF ASM_VERSION}\r
41069 //[procedure TControl.ApplyFont2Wnd]\r
41070 procedure TControl.ApplyFont2Wnd;\r
41071 asm\r
41072         PUSH       EBX\r
41073         XCHG       EBX, EAX\r
41075         MOV        ECX, [EBX].fFont\r
41076         JECXZ      @@exit\r
41077         XCHG       EAX, ECX\r
41079         MOV        ECX, [EBX].fHandle\r
41080         JECXZ      @@0\r
41082         MOV        EDX, [EAX].TGraphicTool.fData.Color\r
41083         MOV        [EBX].fTextColor, EDX\r
41085         PUSH       $FFFF\r
41086         CALL       TGraphicTool.GetHandle\r
41087         PUSH       EAX\r
41088         PUSH       WM_SETFONT\r
41089         PUSH       EBX\r
41090         CALL       Perform\r
41092 @@0:\r
41093         XOR        ECX, ECX\r
41094         XCHG       ECX, [EBX].fCanvas\r
41095         JECXZ      @@1\r
41097         XCHG       EAX, ECX\r
41098         CALL       TObj.Free\r
41099 @@1:\r
41100         MOV        ECX, [EBX].fAutoSize\r
41101         JECXZ      @@exit\r
41102         XCHG       EAX, EBX\r
41103         CALL       ECX\r
41104 @@exit:\r
41105         POP        EBX\r
41106 end;\r
41107 {$ELSE ASM_VERSION} //Pascal\r
41108 procedure TControl.ApplyFont2Wnd;\r
41109 begin\r
41110   if fFont <> nil then\r
41111   begin\r
41112     if fHandle <> 0 then\r
41113     begin\r
41114       fTextColor := fFont.fData.Color;\r
41115       Perform( WM_SETFONT, FFont.Handle, 1 );\r
41116     end;\r
41118     if fCanvas <> nil then\r
41119     begin\r
41120       fCanvas.Free;\r
41121       fCanvas := nil;\r
41122     end;\r
41124     if Assigned( fAutoSize ) then\r
41125       fAutoSize( @Self );\r
41126     //if assigned( fCanvas ) then\r
41127     //   {fCanvas.fFont :=} fCanvas.fFont.Assign( fFont );\r
41128   end;\r
41129 end;\r
41130 {$ENDIF ASM_VERSION}\r
41132 {$IFDEF ASM_VERSION}\r
41133 //[function TControl.ResizeParent]\r
41134 function TControl.ResizeParent: PControl;\r
41135 asm\r
41136         LEA       EDX, [TControl.ResizeParentRight]\r
41137         PUSH      EDX\r
41138         CALL      EDX\r
41139         CALL      TControl.ResizeParentBottom\r
41140 end;\r
41141 {$ELSE ASM_VERSION} //Pascal\r
41142 function TControl.ResizeParent: PControl;\r
41143 begin\r
41144             ResizeParentBottom;\r
41145             ResizeParentRight;\r
41146             // Once again, to fix Windows (or my???) bug with\r
41147             // incorrect calculating of GetClientRect after\r
41148             // SetWindowLong( GWL_[EX}STYLE,... )\r
41149   Result := ResizeParentBottom;\r
41150 end;\r
41151 {$ENDIF ASM_VERSION}\r
41153 {$IFDEF ASM_VERSION}\r
41154 //[function TControl.ResizeParentBottom]\r
41155 function TControl.ResizeParentBottom: PControl;\r
41156 asm\r
41157         PUSH      EAX\r
41158         PUSH      EBX\r
41159         MOV       EBX, [EAX].fParent\r
41160         TEST      EBX, EBX\r
41161         JZ        @@exit\r
41163         MOV       EDX, [EAX].fBoundsRect.Bottom\r
41164         ADD       EDX, [EBX].fMargin\r
41166         TEST      [EBX].fChangedPosSz, 20h\r
41167         JZ        @@1\r
41169         PUSH      EDX\r
41170         MOV       EAX, EBX\r
41171         CALL      GetClientHeight\r
41172         POP       EDX\r
41174         CMP       EDX, EAX\r
41175         JLE       @@exit\r
41176 @@1:\r
41177         MOV       EAX, EBX\r
41178         CALL      TControl.SetClientHeight\r
41179         OR        [EBX].fChangedPosSz, 20h\r
41180 @@exit:\r
41181         POP       EBX\r
41182         POP       EAX\r
41183 end;\r
41184 {$ELSE ASM_VERSION} //Pascal\r
41185 function TControl.ResizeParentBottom: PControl;\r
41186 var NewCH: Integer;\r
41187 begin\r
41188   Result := @Self;\r
41189   if fParent <> nil then\r
41190   begin\r
41191     NewCH := BoundsRect.Bottom + fParent.fMargin;\r
41192     if (fParent.fChangedPosSz and $20) <> 0 then\r
41193        if NewCH < fParent.ClientHeight then Exit;\r
41194     fParent.ClientHeight := NewCH;\r
41195     fParent.fChangedPosSz := fParent.fChangedPosSz or $20;\r
41196   end;\r
41197 end;\r
41198 {$ENDIF ASM_VERSION}\r
41200 {$IFDEF ASM_VERSION}\r
41201 //[function TControl.ResizeParentRight]\r
41202 function TControl.ResizeParentRight: PControl;\r
41203 asm\r
41204         PUSH      EAX\r
41205         PUSH      EBX\r
41206         MOV       EBX, [EAX].fParent\r
41207         TEST      EBX, EBX\r
41208         JZ        @@exit\r
41210         MOV       EDX, [EAX].fBoundsRect.Right\r
41211         ADD       EDX, [EBX].fMargin\r
41213         TEST      [EBX].fChangedPosSz, 10h\r
41214         JZ        @@1\r
41216         PUSH      EDX\r
41217         MOV       EAX, EBX\r
41218         CALL      GetClientWidth\r
41219         POP       EDX\r
41221         CMP       EDX, EAX\r
41222         JLE       @@exit\r
41223 @@1:\r
41224         MOV       EAX, EBX\r
41225         CALL      TControl.SetClientWidth\r
41226         OR        [EBX].fChangedPosSz, 10h\r
41227 @@exit:\r
41228         POP       EBX\r
41229         POP       EAX\r
41230 end;\r
41231 {$ELSE ASM_VERSION} //Pascal\r
41232 function TControl.ResizeParentRight: PControl;\r
41233 var NewCW: Integer;\r
41234 begin\r
41235   Result := @Self;\r
41236   if fParent <> nil then\r
41237   begin\r
41238     NewCW := fBoundsRect.Right + fParent.fMargin;\r
41239     if (fParent.fChangedPosSz and $10) <> 0 then\r
41240        if NewCW < fParent.ClientWidth then Exit;\r
41241     fParent.ClientWidth := NewCW;\r
41242     fParent.fChangedPosSz := fParent.fChangedPosSz or $10;\r
41243   end;\r
41244 end;\r
41245 {$ENDIF ASM_VERSION}\r
41247 {$IFDEF ASM_VERSION}\r
41248 //[function TControl.GetClientHeight]\r
41249 function TControl.GetClientHeight: Integer;\r
41250 asm\r
41251         ADD       ESP, -size_TRect\r
41252         MOV       EDX, ESP\r
41253         CALL      TControl.ClientRect\r
41254         POP       EDX\r
41255         POP       ECX            // Top\r
41256         POP       EDX\r
41257         POP       EAX            // Bottom\r
41258         SUB       EAX, ECX       // Result = Bottom - Top\r
41259 end;\r
41260 {$ELSE ASM_VERSION} //Pascal\r
41261 function TControl.GetClientHeight: Integer;\r
41262 begin\r
41263   with ClientRect do\r
41264     Result := Bottom - Top;\r
41265 end;\r
41266 {$ENDIF ASM_VERSION}\r
41268 {$IFDEF ASM_VERSION}\r
41269 //[function TControl.GetClientWidth]\r
41270 function TControl.GetClientWidth: Integer;\r
41271 asm\r
41272         ADD       ESP, -size_TRect\r
41273         MOV       EDX, ESP\r
41274         CALL      TControl.ClientRect\r
41275         POP       ECX            // Left\r
41276         POP       EDX\r
41277         POP       EAX            // Right\r
41278         SUB       EAX, ECX       // Result = Right - Left\r
41279         POP       EDX\r
41280 end;\r
41281 {$ELSE ASM_VERSION} //Pascal\r
41282 function TControl.GetClientWidth: Integer;\r
41283 begin\r
41284   with ClientRect do\r
41285     Result := Right - Left;\r
41286 end;\r
41287 {$ENDIF ASM_VERSION}\r
41289 {$IFDEF ASM_VERSION}\r
41290 //[procedure TControl.SetClientHeight]\r
41291 procedure TControl.SetClientHeight(const Value: Integer);\r
41292 asm\r
41293         PUSH      EBX\r
41294          PUSH      EDX\r
41296         MOV       EBX, EAX\r
41297         CALL      TControl.GetClientHeight\r
41298           PUSH      EAX\r
41299         MOV       EAX, EBX\r
41300         CALL      TControl.GetHeight // EAX = Height\r
41302           POP       EDX              // EDX = ClientHeight\r
41303         SUB       EAX, EDX           // EAX = Delta\r
41304          POP       EDX               // EDX = Value\r
41305         ADD       EDX, EAX           // EDX = Value + Delta\r
41306         XCHG      EAX, EBX           // EAX = @Self\r
41307         CALL      TControl.SetHeight\r
41308         POP       EBX\r
41309 end;\r
41310 {$ELSE ASM_VERSION} //Pascal\r
41311 procedure TControl.SetClientHeight(const Value: Integer);\r
41312 var Delta: Integer;\r
41313 begin\r
41314   Delta := ClientHeight;\r
41315   Delta := Height - Delta;\r
41316   Height := Value + Delta;\r
41317 end;\r
41318 {$ENDIF ASM_VERSION}\r
41320 {$IFDEF ASM_VERSION}\r
41321 //[procedure TControl.SetClientWidth]\r
41322 procedure TControl.SetClientWidth(const Value: Integer);\r
41323 asm\r
41324         PUSH      EBX\r
41325          PUSH      EDX\r
41327         MOV       EBX, EAX\r
41328         CALL      TControl.GetClientWidth\r
41329           PUSH      EAX\r
41330         MOV       EAX, EBX\r
41331         CALL      TControl.GetWidth  // EAX = Width\r
41333           POP       EDX              // EDX = ClientWidth\r
41334         SUB       EAX, EDX           // EAX = Width - ClientWidth\r
41335          POP       EDX               // EDX = Value\r
41336         ADD       EDX, EAX           // EDX = Value + Delta\r
41337         XCHG      EAX, EBX           // EAX = @Self\r
41338         CALL      TControl.SetWidth\r
41339         POP       EBX\r
41340 end;\r
41341 {$ELSE ASM_VERSION} //Pascal\r
41342 procedure TControl.SetClientWidth(const Value: Integer);\r
41343 var Delta: Integer;\r
41344 begin\r
41345   Delta := ClientWidth;\r
41346   Delta := Width - Delta;\r
41347   Width := Value + Delta;\r
41348 end;\r
41349 {$ENDIF ASM_VERSION}\r
41351 {$IFDEF ASM_VERSION}\r
41352 //[function TControl.CenterOnParent]\r
41353 function TControl.CenterOnParent: PControl;\r
41354 asm\r
41355         PUSHAD\r
41357         XCHG     ESI, EAX\r
41358         MOV      ECX, [ESI].fParent\r
41359         JECXZ    @@1\r
41360         CMP      [ESI].fIsControl, 0\r
41361         JNZ      @@2\r
41363 @@1:\r
41364         PUSH     SM_CYSCREEN\r
41365         CALL     GetSystemMetrics\r
41366         PUSH     EAX\r
41368         PUSH     SM_CXSCREEN\r
41369         CALL     GetSystemMetrics\r
41370         PUSH     EAX\r
41372         PUSH     0\r
41373         PUSH     0               // ESP -> Rect( 0, 0, CX, CY )\r
41375         JMP      @@3\r
41377 @@2:    ADD      ESP, -size_TRect\r
41378         MOV      EDX, ESP\r
41379         XCHG     EAX, ECX\r
41380         CALL     TControl.ClientRect\r
41381                                  // ESP -> ClientRect\r
41382 @@3:    MOV      EAX, ESI\r
41383         CALL     GetWindowHandle\r
41385         MOV      EAX, ESI\r
41386         CALL     GetWidth\r
41388         POP      EDX       // left\r
41389         ADD      EAX, EDX          // + width\r
41391         POP      EDI       // top\r
41392         POP      EDX       // right\r
41394         SUB      EDX, EAX\r
41395         SAR      EDX, 1\r
41397         MOV      EAX, ESI\r
41398         CALL     SetLeft\r
41400         MOV      EAX, ESI\r
41401         CALL     GetHeight\r
41403         ADD      EAX, EDI  // height + top\r
41405         POP      EDX       // bottom\r
41406         SUB      EDX, EAX\r
41407         SAR      EDX, 1\r
41409         XCHG     EAX, ESI\r
41410         CALL     SetTop\r
41412         POPAD\r
41413 end;\r
41414 {$ELSE ASM_VERSION} //Pascal\r
41415 function TControl.CenterOnParent: PControl;\r
41416 var PCR: TRect;\r
41417 begin\r
41418   Result := @Self;\r
41419   if (fParent = nil) or not fIsControl then\r
41420     PCR := MakeRect( 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) )\r
41421   else\r
41422     PCR := fParent.ClientRect;\r
41423   GetWindowHandle;\r
41424   Left := (PCR.Right - PCR.Left - Width) div 2;\r
41425   Top := (PCR.Bottom - PCR.Top - Height) div 2;\r
41426 end;\r
41427 {$ENDIF ASM_VERSION}\r
41429 {$IFDEF ASM_noVERSION}\r
41430 //[function TControl.GetHasBorder]\r
41431 function TControl.GetHasBorder: Boolean;\r
41432 const style_mask = WS_BORDER or WS_THICKFRAME or WS_DLGFRAME;\r
41433 asm\r
41434         CALL     UpdateWndStyles\r
41435         MOV      EAX, [EAX].fStyle\r
41436         AND      EAX, style_mask\r
41437         SETNZ    AL\r
41438 end;\r
41439 {$ELSE ASM_VERSION} //Pascal\r
41440 function TControl.GetHasBorder: Boolean;\r
41441 begin\r
41442   UpdateWndStyles;\r
41443   Result := LongBool( fStyle and (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME))\r
41444          or LongBool( fExStyle and WS_EX_CLIENTEDGE );\r
41445 end;\r
41446 {$ENDIF ASM_VERSION}\r
41448 {$IFDEF ASM_noVERSION} // YS\r
41449 //[procedure TControl.SetHasBorder]\r
41450 procedure TControl.SetHasBorder(const Value: Boolean);\r
41451 const style_mask = WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION\r
41452                              or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU;\r
41453       exstyle_mask = not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME\r
41454                                 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);\r
41455 asm\r
41457         PUSH     EAX\r
41458           PUSH     EDX\r
41460             CALL     GetHasBorder\r
41461           POP      ECX\r
41462           CMP      AL, CL\r
41464         POP      EAX\r
41465         JZ       @@exit\r
41467         MOV      EDX, [EAX].fStyle\r
41468         DEC      CL\r
41469         MOVZX    ECX, [EAX].fIsControl\r
41470         JNZ      @@1\r
41472         OR       EDX, WS_THICKFRAME\r
41473         INC      ECX\r
41474         LOOP     @@set_style\r
41475         OR       EDX, style_mask\r
41476         JMP      @@set_style\r
41478 @@1:    AND      EDX, not style_mask\r
41479         INC      ECX\r
41480         LOOP     @@2\r
41481         OR       EDX, WS_POPUP\r
41483 @@2:    PUSH     EDX\r
41485         MOV      EDX, [EAX].fExStyle\r
41486         AND      EDX, exstyle_mask\r
41488         PUSH     EAX\r
41489         CALL     SetExStyle\r
41490         POP      EAX\r
41492         POP      EDX\r
41493 @@set_style:\r
41494         CALL     SetStyle\r
41495 @@exit:\r
41496 end;\r
41497 {$ELSE ASM_VERSION} //Pascal\r
41498 procedure TControl.SetHasBorder(const Value: Boolean);\r
41499 var NewStyle: DWORD;\r
41500 begin\r
41501   if Value = GetHasBorder then Exit;\r
41502   {if Value then\r
41503   begin\r
41504     NewStyle := fStyle or WS_THICKFRAME;\r
41505     if not fIsControl then\r
41506       NewStyle := NewStyle or WS_BORDER or\r
41507                WS_DLGFRAME or WS_CAPTION or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or\r
41508                WS_SYSMENU;\r
41509     Style := NewStyle;\r
41510   end}\r
41511   if Value then\r
41512   begin\r
41513     if not fIsControl then\r
41514       Style := fStyle or WS_THICKFRAME or WS_BORDER or\r
41515                WS_DLGFRAME or WS_CAPTION or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or\r
41516                WS_SYSMENU\r
41517     else\r
41518       if fCtl3D then\r
41519         ExStyle := fExStyle or WS_EX_CLIENTEDGE\r
41520       else\r
41521         Style := fStyle or WS_BORDER;\r
41522   end\r
41523     else\r
41524   begin\r
41525     NewStyle := fStyle and not (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION\r
41526                              or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU);\r
41527     if not fIsControl then NewStyle := NewStyle or WS_POPUP;\r
41528     Style := NewStyle;\r
41529     ExStyle := fExStyle and not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME\r
41530                                 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);\r
41531   end;\r
41532 end;\r
41533 {$ENDIF ASM_VERSION}\r
41535 {$IFDEF ASM_VERSION}\r
41536 //[function TControl.GetHasCaption]\r
41537 function TControl.GetHasCaption: Boolean;\r
41538 const style_mask1 = (WS_POPUP or WS_DLGFRAME) shr 16;\r
41539       style_mask2 = WS_CAPTION shr 16;\r
41540 asm\r
41541         CALL     UpdateWndStyles\r
41542         MOV      ECX, [EAX].fStyle + 2\r
41543         MOV      EDX, ECX\r
41544         MOV      AL, 1\r
41545         AND      DX, style_mask1\r
41546         JZ       @@1\r
41547         AND      CX, style_mask2\r
41548         JNZ      @@1\r
41549         XOR      EAX, EAX\r
41550 @@1:\r
41551 end;\r
41552 {$ELSE ASM_VERSION} //Pascal\r
41553 function TControl.GetHasCaption: Boolean;\r
41554 begin\r
41555   UpdateWndStyles;\r
41556   Result := not LongBool( fStyle and (WS_POPUP or WS_DLGFRAME))\r
41557             or LongBool( fStyle and WS_CAPTION);\r
41558 end;\r
41559 {$ENDIF ASM_VERSION}\r
41561 {$IFDEF ASM_VERSION}\r
41562 //[procedure TControl.SetHasCaption]\r
41563 procedure TControl.SetHasCaption(const Value: Boolean);\r
41564 const style_mask = not (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION\r
41565                              or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU);\r
41566       exstyle_mask = not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME\r
41567                                 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);\r
41568 asm\r
41569         PUSH     EAX\r
41570           PUSH     EDX\r
41572             CALL     GetHasCaption\r
41573           POP      ECX\r
41574           CMP      AL, CL\r
41576         POP      EAX\r
41577         JZ       @@exit   // Value = HasCaption\r
41579         MOV      EDX, [EAX].fStyle\r
41580         DEC      CL\r
41581         JNZ      @@1      // if not Value -> @@1\r
41583         AND      EDX, not WS_POPUP\r
41584         OR       EDX, WS_CAPTION\r
41585         JMP      @@set_style\r
41587 @@1:\r
41588         CMP      [EAX].fIsControl, 0\r
41589         JNZ      @@2               // if fIsControl -> @@2\r
41591         AND      EDX, not (WS_CAPTION or WS_SYSMENU)\r
41592         OR       EDX, WS_POPUP\r
41593         JMP      @@3\r
41595 @@2:\r
41596         AND      EDX, not WS_CAPTION\r
41597         OR       EDX, WS_DLGFRAME\r
41599 @@3:\r
41600         PUSH     EDX\r
41602         MOV      EDX, [EAX].fExStyle\r
41603         OR       EDX, WS_EX_DLGMODALFRAME\r
41605         PUSH     EAX\r
41606         CALL     SetExStyle\r
41607         POP      EAX\r
41609         POP      EDX\r
41610 @@set_style:\r
41611         CALL     SetStyle\r
41612 @@exit:\r
41613 end;\r
41614 {$ELSE ASM_VERSION} //Pascal\r
41615 procedure TControl.SetHasCaption(const Value: Boolean);\r
41616 begin\r
41617   if Value = GetHasCaption then Exit;\r
41618   if Value then\r
41619   begin\r
41620      Style := fStyle and not (WS_POPUP or WS_DLGFRAME) or WS_CAPTION;\r
41621   end\r
41622     else\r
41623   begin\r
41624     if fIsControl then\r
41625        Style := fStyle and not WS_CAPTION or WS_DLGFRAME\r
41626     else\r
41627        Style := fStyle and not (WS_CAPTION or WS_SYSMENU) or WS_POPUP;\r
41628     ExStyle := fExStyle or WS_EX_DLGMODALFRAME;\r
41629   end;\r
41630 end;\r
41631 {$ENDIF ASM_VERSION}\r
41633 {$IFDEF ASM_VERSION}\r
41634 //[function TControl.GetCanResize]\r
41635 function TControl.GetCanResize: Boolean;\r
41636 asm\r
41637         MOV      AL, [EAX].fPreventResize\r
41638         {$IFDEF PARANOIA}\r
41639         DB $34,$01\r
41640         {$ELSE}\r
41641         XOR      AL, 1\r
41642         {$ENDIF}\r
41643 end;\r
41644 {$ELSE ASM_VERSION} //Pascal\r
41645 function TControl.GetCanResize: Boolean;\r
41646 begin\r
41647   //UpdateWndStyles;\r
41648   //Result := LongBool( fStyle and WS_THICKFRAME);\r
41649   Result := not fPreventResize;\r
41650 end;\r
41651 {$ENDIF ASM_VERSION}\r
41653 //[function WndProcCanResize]\r
41654 function WndProcCanResize( Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;\r
41655 var W, H: Integer;\r
41656     P: PMinMaxInfo;\r
41657 begin\r
41658   if not Sender.CanResize then\r
41659   if M.message = WM_GETMINMAXINFO then\r
41660   begin\r
41661     Rslt := Sender.CallDefWndProc( M );\r
41662     W := Sender.FFixWidth;\r
41663     H := Sender.FFixHeight;\r
41664     P := Pointer( M.lParam );\r
41665     P.ptMinTrackSize.x := W;\r
41666     P.ptMinTrackSize.y := H;\r
41667     P.ptMaxTrackSize := P.ptMinTrackSize;\r
41668     Result := True; // stop further processing (prevent resizing)\r
41669     Exit;\r
41670   end\r
41671     else\r
41672   if M.message = WM_NCHITTEST then\r
41673   begin\r
41674     Rslt := Sender.CallDefWndProc( M );\r
41675     if (Rslt >= 10) and (Rslt <= 17) then\r
41676     begin\r
41677       Rslt := {-}HTBORDER{+}{++}(*18{HTBORDER}*){--};\r
41678       Result := True;\r
41679       exit;\r
41680     end;\r
41681   end;\r
41682   Result := False; // continue message processing\r
41683 end;\r
41685 {$IFDEF ASM_VERSION}\r
41686 //[procedure TControl.SetCanResize]\r
41687 procedure TControl.SetCanResize( const Value: Boolean );\r
41688 asm\r
41689         PUSH     EBX\r
41690         MOV      EBX, EAX\r
41692             CALL     GetCanResize\r
41693         CMP      AL, DL\r
41695         JZ       @@exit   // Value = CanResize\r
41696         MOV      [EBX].fPreventResize, AL\r
41697         TEST     DL, DL\r
41699         MOV      EDX, [EBX].fStyle\r
41700         JZ       @@set_thick\r
41702         OR       EDX, WS_THICKFRAME\r
41703         JMP      @@set_style\r
41705 @@set_thick:\r
41706         AND      EDX, not WS_THICKFRAME\r
41708 @@set_style:\r
41709         MOV      EAX, EBX\r
41710         CALL     SetStyle\r
41712         MOV      EAX, EBX\r
41713         CALL     GetWindowHandle\r
41715         MOV      EAX, EBX\r
41716         CALL     GetWidth\r
41717         MOV      [EBX].FFixWidth, EAX\r
41719         MOV      EAX, EBX\r
41720         CALL     GetHeight\r
41721         MOV      [EBX].FFixHeight, EAX\r
41723         XCHG     EAX, EBX\r
41724         MOV      EDX, offset[WndProcCanResize]\r
41725         CALL     TControl.AttachProc\r
41726 @@exit:\r
41727         POP      EBX\r
41728 end;\r
41729 {$ELSE ASM_VERSION} //Pascal\r
41730 procedure TControl.SetCanResize( const Value: Boolean );\r
41731 begin\r
41732   if Value = CanResize then Exit;\r
41733   fPreventResize := not Value;\r
41734   if Value then\r
41735     Style := Style or WS_THICKFRAME\r
41736   else\r
41737     Style := Style and not WS_THICKFRAME;\r
41738   GetWindowHandle;\r
41739   FFixWidth := Width;\r
41740   FFixHeight := Height;\r
41741   AttachProc( WndProcCanResize );\r
41742 end;\r
41743 {$ENDIF ASM_VERSION}\r
41745 {$IFDEF ASM_VERSION}\r
41746 //[function TControl.GetStayOnTop]\r
41747 function TControl.GetStayOnTop: Boolean;\r
41748 asm\r
41749         CALL     UpdateWndStyles\r
41750         TEST     byte ptr [EAX].fExStyle, WS_EX_TOPMOST\r
41751         SETNZ    AL\r
41752 end;\r
41753 {$ELSE ASM_VERSION} //Pascal\r
41754 function TControl.GetStayOnTop: Boolean;\r
41755 begin\r
41756   UpdateWndStyles;\r
41757   Result := LongBool( fExStyle and WS_EX_TOPMOST);\r
41758 end;\r
41759 {$ENDIF ASM_VERSION}\r
41761 {$IFDEF ASM_VERSION}\r
41762 //[procedure TControl.SetStayOnTop]\r
41763 procedure TControl.SetStayOnTop(const Value: Boolean);\r
41764 asm\r
41765         PUSH     EAX\r
41766           PUSH     EDX\r
41768             CALL     GetStayOnTop\r
41769           POP      ECX\r
41770           MOVZX    ECX, CL\r
41771           CMP      AL, CL\r
41773         POP      EAX\r
41774         JZ       @@exit   // Value = StayOnTop\r
41776         MOV      EDX, [EAX].fHandle\r
41777         TEST     EDX, EDX\r
41778         JZ       @@1\r
41780         PUSH     SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE\r
41781         XOR      EAX, EAX\r
41782         PUSH     EAX\r
41783         PUSH     EAX\r
41784         PUSH     EAX\r
41785         PUSH     EAX\r
41786         DEC      ECX\r
41787         DEC      ECX\r
41788         PUSH     ECX\r
41790         PUSH     EDX\r
41791         CALL     SetWindowPos\r
41792         RET\r
41794 @@1:\r
41795         JECXZ    @@1and\r
41797         OR       byte ptr [EAX].fExStyle, WS_EX_TOPMOST\r
41798         RET\r
41800 @@1and: AND      byte ptr [EAX].fExStyle, not WS_EX_TOPMOST\r
41802 @@exit:\r
41803 end;\r
41804 {$ELSE ASM_VERSION} //Pascal\r
41805 procedure TControl.SetStayOnTop(const Value: Boolean);\r
41806 begin\r
41807   if Value = GetStayOnTop then Exit;\r
41808   if fHandle <> 0 then\r
41809   if Value then\r
41810      SetWindowPos( fHandle, HWND_TOPMOST, 0,0,0,0,\r
41811                    SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE )\r
41812   else\r
41813      SetWindowPos( fHandle, HWND_NOTOPMOST, 0,0,0,0,\r
41814                    SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE )\r
41815            else\r
41816   if Value then fExStyle := fExStyle or WS_EX_TOPMOST\r
41817            else fExStyle := fExStyle and not WS_EX_TOPMOST;\r
41818 end;\r
41819 {$ENDIF ASM_VERSION}\r
41821 {$IFDEF ASM_VERSION}\r
41822 //[function TControl.UpdateWndStyles]\r
41823 function TControl.UpdateWndStyles: PControl;\r
41824 asm\r
41825         MOV      ECX, [EAX].fHandle\r
41826         JECXZ    @@exit\r
41828         PUSH     EBX\r
41830         XCHG     EBX, EAX\r
41831           PUSH     GCL_STYLE\r
41832           PUSH     ECX\r
41834           PUSH     GWL_EXSTYLE\r
41835           PUSH     ECX\r
41837           PUSH     GWL_STYLE\r
41838           PUSH     ECX\r
41840           CALL     GetWindowLong\r
41841           MOV      [EBX].fStyle, EAX\r
41843           CALL     GetWindowLong\r
41844           MOV      [EBX].fExStyle, EAX\r
41846           CALL     GetClassLong\r
41847           MOV      [EBX].fClsStyle, EAX\r
41848         XCHG     EAX, EBX\r
41849         POP      EBX\r
41850 @@exit:\r
41851 end;\r
41852 {$ELSE ASM_VERSION} //Pascal\r
41853 function TControl.UpdateWndStyles: PControl;\r
41854 begin\r
41855   Result := @Self;\r
41856   if fHandle = 0 then Exit;\r
41857   fStyle := GetWindowLong( fHandle, GWL_STYLE );\r
41858   fExStyle := GetWindowLong( fHandle, GWL_EXSTYLE );\r
41859   fClsStyle := GetClassLong( fHandle, GCL_STYLE );\r
41860 end;\r
41861 {$ENDIF ASM_VERSION}\r
41863 {$IFDEF ASM_VERSION}\r
41864 //[function TControl.GetChecked]\r
41865 function TControl.GetChecked: Boolean;\r
41866 asm\r
41867         TEST     [EAX].fBitBtnOptions, 8 //1 shl Ord(bboFixed)\r
41868         JZ       @@1\r
41869         MOV      AL, [EAX].fChecked\r
41870         RET\r
41871 @@1:\r
41872         PUSH     0\r
41873         PUSH     0\r
41874         PUSH     BM_GETCHECK\r
41875         PUSH     EAX\r
41876         CALL     Perform\r
41877 @@exit:\r
41878 end;\r
41879 {$ELSE ASM_VERSION} //Pascal\r
41880 function TControl.GetChecked: Boolean;\r
41881 begin\r
41882   if bboFixed in fBitBtnOptions then\r
41883     Result := fChecked\r
41884   else\r
41885     Result := LongBool( Perform( BM_GETCHECK, 0, 0 ) ) ; //= BST_CHECKED;\r
41886 end;\r
41887 {$ENDIF ASM_VERSION}\r
41889 {$IFDEF ASM_VERSION}\r
41890 //[procedure TControl.Set_Checked]\r
41891 procedure TControl.Set_Checked(const Value: Boolean);\r
41892 asm\r
41893         TEST     [EAX].fBitBtnOptions, 8 //1 shl Ord(bboFixed)\r
41894         JZ       @@1\r
41895         MOV      [EAX].fChecked, DL\r
41896         JMP      Invalidate\r
41897 @@1:\r
41898         PUSH     0\r
41899         MOVZX    EDX, DL\r
41900         PUSH     EDX\r
41901         PUSH     BM_SETCHECK\r
41902         PUSH     EAX\r
41903         Call     Perform\r
41904 end;\r
41905 {$ELSE ASM_VERSION} //Pascal\r
41906 procedure TControl.Set_Checked(const Value: Boolean);\r
41907 begin\r
41908   if bboFixed in fBitBtnOptions then\r
41909   begin\r
41910     fChecked := //not fChecked;\r
41911                 Value;\r
41912     Invalidate;\r
41913   end\r
41914   else\r
41915     Perform( BM_SETCHECK, Integer( Value ), 0 );\r
41916 end;\r
41917 {$ENDIF ASM_VERSION}\r
41919 //[function TControl.SetChecked]\r
41920 function TControl.SetChecked(const Value: Boolean): PControl;\r
41921 begin\r
41922   Perform( BM_SETCHECK, Integer( Value ), 0 );\r
41923   Result := @Self;\r
41924 end;\r
41926 {$IFDEF ASM_VERSION}\r
41927 //[function TControl.SetRadioCheckedOld]\r
41928 function TControl.SetRadioCheckedOld: PControl;\r
41929 asm\r
41930         PUSH     EAX\r
41931         MOV      ECX, [EAX].fParent\r
41932         JECXZ    @@exit\r
41934         PUSH     [EAX].fMenu\r
41935         PUSH     [ECX].fRadioLast\r
41936         PUSH     [ECX].fRadio1st\r
41937         MOV      EAX, ECX\r
41938         CALL     GetWindowHandle\r
41939         PUSH     EAX\r
41940         CALL     CheckRadioButton\r
41941 @@exit:\r
41942         POP      EAX\r
41943 end;\r
41944 {$ELSE ASM_VERSION} //Pascal\r
41945 function TControl.SetRadioCheckedOld: PControl;\r
41946 begin\r
41947   Result := @Self;\r
41948   if fParent = nil then Exit;\r
41949   CheckRadioButton( fParent.GetWindowHandle,\r
41950                     fParent.fRadio1st,\r
41951                     fParent.fRadioLast,\r
41952                     fMenu );\r
41953 end;\r
41954 {$ENDIF ASM_VERSION}\r
41956 //*\r
41957 //[function TControl.SetRadioChecked]\r
41958 function TControl.SetRadioChecked: PControl;\r
41959 begin\r
41960   Click;\r
41961   Result := @Self;\r
41962 end;\r
41964 //*\r
41965 //[procedure TControl.Click]\r
41966 procedure TControl.Click;\r
41967 begin\r
41968   if (fCommandActions.aClick <> 0) or\r
41969      (fCommandActions.aEnter = BN_SETFOCUS) then\r
41970     Perform( WM_COMMAND, (fCommandActions.aClick shl 16) or fMenu,\r
41971              GetWindowHandle )\r
41972   else\r
41973   begin\r
41974     Perform( WM_LBUTTONDOWN, MK_LBUTTON, 0 );\r
41975     Perform( WM_LBUTTONUP, MK_LBUTTON, 0 );\r
41976   end;\r
41977 end;\r
41979 {$IFDEF ASM_VERSION}\r
41980 //[function TControl.GetSelStart]\r
41981 function TControl.GetSelStart: Integer;\r
41982 asm\r
41983          MOVZX    ECX, [EAX].fCommandActions.aGetSelRange\r
41984          JECXZ    @@1\r
41986          XOR      EDX, EDX\r
41987          PUSH     EDX\r
41988          PUSH     EDX\r
41989          PUSH     ECX\r
41990          PUSH     EAX\r
41991          CALL     Perform\r
41992          CWDE\r
41993          RET\r
41995 @@1:\r
41996          MOVZX    ECX, [EAX].fCommandActions.aExGetSelRange\r
41997          JECXZ    @@exit\r
41998          XCHG     EAX, ECX\r
41999          CDQ\r
42000          PUSH     EDX\r
42001          PUSH     EDX\r
42002          PUSH     ESP\r
42003          PUSH     EDX\r
42004          PUSH     EAX\r
42005          PUSH     ECX\r
42006          CALL     Perform\r
42007          POP      ECX\r
42008          POP      EDX\r
42010 @@exit:\r
42011          XCHG     EAX, ECX\r
42012 end;\r
42013 {$ELSE ASM_VERSION} //Pascal\r
42014 function TControl.GetSelStart: Integer;\r
42015 var SR: TCharRange;\r
42016 begin\r
42017   Result := 0;\r
42018   if fCommandActions.aGetSelRange <> 0 then\r
42019     Result := LoWord( Perform( fCommandActions.aGetSelRange, 0, 0 ) )\r
42020   else\r
42021   if fCommandActions.aExGetSelRange <> 0 then\r
42022   begin\r
42023     Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );\r
42024     Result := SR.cpMin;\r
42025   end;\r
42026 end;\r
42027 {$ENDIF ASM_VERSION}\r
42029 //[procedure TControl.SetSelStart]\r
42030 procedure TControl.SetSelStart(const Value: Integer);\r
42031 begin\r
42032   ItemSelected[ Value ] := True;\r
42033 end;\r
42035 {$IFDEF ASM_VERSION}\r
42036 //[function TControl.GetSelLength]\r
42037 function TControl.GetSelLength: Integer;\r
42038 asm\r
42039         XOR       EDX, EDX\r
42040         MOVZX     ECX, word ptr[EAX].fCommandActions.aGetSelCount\r
42041         JECXZ     @@check_ex\r
42043         PUSH      ECX\r
42044         AND       CH, $7F\r
42045         PUSH      EDX\r
42046         PUSH      EDX\r
42047         PUSH      ECX\r
42048         PUSH      EAX\r
42049         CALL      Perform\r
42050         POP       ECX\r
42051         SHL       CH, 1\r
42052         JC        @@fin_EAX\r
42054         CMP       EAX, 32768\r
42055         JL        @@2\r
42057         PUSH      EAX\r
42058         POP       DX\r
42059         POP       AX\r
42060         SUB       AX, DX\r
42061         MOVZX     EAX, AX\r
42062 @@fin_EAX:\r
42063         RET\r
42065 @@check_ex:\r
42066         MOVZX     ECX, [EAX].fCommandActions.aExGetSelRange\r
42067         JECXZ     @@ret_0\r
42068         PUSH      EDX\r
42069         PUSH      EDX\r
42070         PUSH      ESP\r
42071         PUSH      EDX\r
42072         PUSH      ECX\r
42073         PUSH      EAX\r
42074         CALL      Perform\r
42075         POP       EDX\r
42076         POP       EAX\r
42077         SUB       EAX, EDX\r
42078         RET\r
42080 @@ret_0:\r
42081         XOR       EAX, EAX\r
42082         //RET\r
42084 @@2:    TEST      EAX, EAX\r
42085         JL        @@ret_0\r
42086 end;\r
42087 {$ELSE ASM_VERSION} //Pascal\r
42088 function TControl.GetSelLength: Integer;\r
42089 var SR: TCharRange;\r
42090 begin\r
42091   Result := 0;\r
42092   if fCommandActions.aGetSelCount <> 0 then\r
42093   begin\r
42094     Result := Perform( fCommandActions.aGetSelCount and $7FFF, 0, 0 );\r
42095     if (fCommandActions.aGetSelCount and $8000) = 0 then\r
42096       if Result >= 32768 then\r
42097         Result := HiWord( Result ) - LoWord( Result )\r
42098       else\r
42099       if Result < 0 then\r
42100         Result := 0;\r
42101   end\r
42102      else\r
42103   if fCommandActions.aExGetSelRange <> 0 then\r
42104   begin\r
42105     Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );\r
42106     Result := SR.cpMax - SR.cpMin;\r
42107   end;\r
42108 end;\r
42109 {$ENDIF ASM_VERSION}\r
42111 {$IFDEF ASM_VERSION}\r
42112 //[procedure TControl.SetSelLength]\r
42113 procedure TControl.SetSelLength(const Value: Integer);\r
42114 asm\r
42115         PUSH     EBP\r
42116         MOV      EBP, ESP\r
42117         PUSH     EAX\r
42118         PUSH     EDX\r
42119         CALL     GetSelStart\r
42120         POP      ECX\r
42121         POP      EDX\r
42122         ADD      ECX, EAX\r
42123         PUSH     ECX\r
42124         MOVZX    ECX, [EDX].fCommandActions.aSetSelRange\r
42125         JECXZ    @@check_ex\r
42126         PUSH     EAX\r
42127         JMP      @@perform\r
42129 @@check_ex:\r
42130         MOVZX    ECX, [EDX].fCommandActions.aExSetSelRange\r
42131         JECXZ    @@exit\r
42132         PUSH     EAX\r
42133         PUSH     ESP\r
42134         PUSH     0\r
42135 @@perform:\r
42136         PUSH     ECX\r
42137         PUSH     EDX\r
42138         CALL     Perform\r
42139 @@exit: MOV      ESP, EBP\r
42140         POP      EBP\r
42141 end;\r
42142 {$ELSE ASM_VERSION} //Pascal\r
42143 procedure TControl.SetSelLength(const Value: Integer);\r
42144 var\r
42145     SR: TCharRange;\r
42146 begin\r
42147   SR.cpMin := GetSelStart;\r
42148   SR.cpMax := SR.cpMin + Value;\r
42149   if Value < 0 then\r
42150     SR.cpMax := -1;\r
42151   if fCommandActions.aSetSelRange <> 0 then\r
42152      Perform( fCommandActions.aSetSelRange, SR.cpMin, SR.cpMax )\r
42153   else\r
42154   if fCommandActions.aExSetSelRange <> 0 then\r
42155      Perform( fCommandActions.aExSetSelRange, 0, Integer( @SR ) );\r
42156   // Preform( EM_SCROLLCARET, 0, 0 );\r
42157 end;\r
42158 {$ENDIF ASM_VERSION}\r
42160 {$IFDEF ASM_VERSION}\r
42161 //[function TControl.GetItems]\r
42162 function TControl.GetItems(Idx: Integer): String;\r
42163 asm\r
42164         PUSH     ESI\r
42165         PUSH     EDI\r
42166         PUSH     EBX\r
42167         PUSH     EBP\r
42168         MOV      EBP, ESP\r
42170         MOV      EBX, EAX       // @Self\r
42171         MOV      ESI, EDX       // Idx\r
42172         MOV      EDI, ECX       // @Result\r
42174         CALL     Item2Pos\r
42175         PUSH     0              // push  0\r
42176         PUSH     EAX            // store Pos\r
42178         XCHG     EDX, EAX\r
42179         MOV      EAX, EBX\r
42180         CALL     Pos2Item       // EAX = Idx'\r
42181         XCHG     ESI, EAX       // ESI = Idx'\r
42183         XOR      EAX, EAX\r
42184         MOVZX    ECX, [EBX].fCommandActions.aGetItemLength\r
42185         JECXZ    @@ret_empty\r
42187         PUSH     ECX            // push aGetItemLength\r
42189         PUSH     EBX\r
42190         CALL     Perform\r
42192         TEST     EAX, EAX\r
42193         JZ       @@ret_empty\r
42195         PUSH     EAX              // save L\r
42196         ADD      EAX, 4\r
42198         CALL     System.@GetMem   // GetMem( L+4 )\r
42199         POP      EDX              // restore L\r
42200         MOV      byte ptr [EAX], 0\r
42201         MOVZX    ECX, [EBX].fCommandActions.aGetItemText\r
42202         JECXZ    @@ret_buf\r
42204         PUSH     EDX              // save L\r
42205         MOV      word ptr [EAX], DX\r
42207         PUSH     EAX\r
42208           PUSH     EAX            // push Buf\r
42209           PUSH     ESI            // push Idx\r
42211           PUSH     ECX            // push aGetItemText\r
42212           PUSH     EBX\r
42213           CALL     Perform\r
42214         POP      EAX\r
42216         POP      EDX\r
42217 @@ret_buf:\r
42218         MOV      byte ptr [EAX + EDX], 0   // Buf[ L ] := #0\r
42220 @@ret_empty:     // EAX = 0\r
42221         XCHG     EDX, EAX\r
42222         MOV      EAX, EDI\r
42223         PUSH     EDX\r
42224         CALL     System.@LStrFromPChar\r
42225         POP      ECX\r
42226         JECXZ    @@exit\r
42227         XCHG     EAX, ECX\r
42228         CALL     System.@FreeMem\r
42230 @@exit:\r
42231         MOV      ESP, EBP\r
42232         POP      EBP\r
42233         POP      EBX\r
42234         POP      EDI\r
42235         POP      ESI\r
42236 end;\r
42237 {$ELSE ASM_VERSION} //Pascal\r
42238 function TControl.GetItems(Idx: Integer): String;\r
42239 var L, Pos: Integer;\r
42240     Buf: PChar;\r
42241 begin\r
42242   Result := '';\r
42243   Pos := Item2Pos( Idx );\r
42244   Idx := Pos2Item( Pos );\r
42245   if fCommandActions.aGetItemLength <> 0 then\r
42246     L := Perform( fCommandActions.aGetItemLength, Pos, 0 )\r
42247   else\r
42248     Exit;\r
42249   if L = 0 then Exit;\r
42250   GetMem( Buf, L + 4 );\r
42251   PWORD( Buf )^ := L + 1;\r
42252   if fCommandActions.aGetItemText <> 0 then\r
42253     Perform( fCommandActions.aGetItemText, Idx, Integer( Buf ) );\r
42254   Buf[ L ] := #0;\r
42255   Result := Buf;\r
42256   FreeMem( Buf );\r
42257 end;\r
42258 {$ENDIF ASM_VERSION}\r
42260 {$IFDEF ASM_VERSION}\r
42261 //[procedure TControl.SetItems]\r
42262 procedure TControl.SetItems(Idx: Integer; const Value: String);\r
42263 asm\r
42264         PUSH     EDI\r
42265         PUSH     EBX\r
42266         XCHG     EBX, EAX\r
42267         XCHG     EDI, EDX       // EDI = Idx\r
42268         CALL     ECX2PChar\r
42269         PUSH     ECX       // @Value[1]\r
42271         MOVZX    ECX, [EBX].fCommandActions.aSetItemText\r
42272         JECXZ    @@1\r
42274         PUSH     0\r
42275         PUSH     ECX\r
42277         MOV      EDX, EDI\r
42278         MOV      EAX, EBX\r
42279         CALL     Item2Pos\r
42280         PUSH     EAX            // store Strt\r
42282         MOV      EDX, EDI\r
42283         INC      EDX\r
42284         MOV      EAX, EBX\r
42285         CALL     Item2Pos\r
42286         POP      EDX            // EDX = Strt\r
42288         SUB      EAX, EDX\r
42289         PUSH     EAX            // store L\r
42291         MOV      EAX, EBX\r
42292         CALL     SetSelStart\r
42294         POP      EDX            // EDX = L\r
42295         PUSH     EBX            // prepare @Self for Perform\r
42296         XCHG     EAX, EBX\r
42297         CALL     SetSelLength\r
42299         // @Value[1] already in stack,\r
42300         // 0 already in stack\r
42301         // aSetItemText already in stack\r
42302         // @Self already in stack\r
42304         CALL     Perform\r
42305         JMP      @@exit\r
42307 @@1:    // @Value[1] in stack already\r
42308         POP      EDX\r
42309         MOVZX    ECX, [EBX].fCommandActions.aDeleteItem\r
42310         JECXZ    @@exit\r
42312         {$IFNDEF  NOT_FIX_CURINDEX}\r
42313         PUSH     ESI\r
42314         PUSH     EBP\r
42316         PUSH     EDX\r
42318         MOV      EAX, EBX               // +AK\r
42319         CALL     GetCurIndex            // +AK\r
42320         XCHG     ESI, EAX    // ESI = TmpCurIdx\r
42322         MOV      EAX, EBX\r
42323         MOV      EDX, EDI\r
42324         CALL     GetItemData\r
42325         XCHG     EBP, EAX   // EBP = TmpData\r
42327         MOV      EDX, EDI\r
42328         MOV      EAX, EBX\r
42329         CALL     Delete\r
42331         MOV      EAX, EBX               // *AK\r
42332         MOV      EDX, EDI\r
42333         POP      ECX\r
42334         CALL     Insert\r
42336         MOV      ECX, EBP // ECX = TmpData\r
42337         MOV      EDX, EDI\r
42338         MOV      EAX, EBX\r
42339         CALL     SetItemData\r
42341         XCHG     EAX, EBX               // +AK\r
42342         MOV      EDX, ESI               // +AK\r
42343         CALL     SetCurIndex            // +AK\r
42345         POP      EBP\r
42346         POP      ESI\r
42347         {$ELSE NOT_FIX_CURINDEX}\r
42348         PUSH     EDX\r
42350         MOV      EDX, EDI\r
42351         MOV      EAX, EBX\r
42352         CALL     Delete\r
42354         XCHG     EAX, EBX\r
42355         XCHG     EDX, EDI\r
42357         POP      ECX\r
42358         CALL     Insert\r
42359         {$ENDIF NOT_FIX_CURINDEX}\r
42361 @@exit:\r
42362         POP      EBX\r
42363         POP      EDI\r
42364 end;\r
42365 {$ELSE ASM_VERSION} //Pascal\r
42366 procedure TControl.SetItems(Idx: Integer; const Value: String);\r
42367 var Strt, L : Integer;\r
42368     {$IFNDEF NOT_FIX_CURINDEX}\r
42369     TmpCurIdx: Integer; // AK - Andrzey Kubasek\r
42370     TmpData: DWORD;\r
42371     {$ENDIF NOT_FIX_CURINDEX}\r
42372 begin\r
42373   if fCommandActions.aSetItemText <> 0 then\r
42374   begin\r
42375     Strt := Item2Pos( Idx );\r
42376     L := Item2Pos( Idx + 1 ) - Strt;\r
42377     SelStart := Strt;\r
42378     SelLength := L;\r
42379     Perform( fCommandActions.aSetItemText, 0, Integer( PChar( Value ) ) );\r
42380   end\r
42381      else\r
42382   if fCommandActions.aDeleteItem <> 0 then\r
42383   begin\r
42384     {$IFNDEF NOT_FIX_CURINDEX}\r
42385     TmpCurIdx := CurIndex; // +AK\r
42386     TmpData := ItemData[ Idx ];\r
42387     {$ENDIF}\r
42388     Delete( Idx );\r
42389     Insert( Idx, Value );\r
42390     {$IFNDEF NOT_FIX_CURINDEX}\r
42391     CurIndex := TmpCurIdx; //+AK\r
42392     ItemData[ Idx ] := TmpData;\r
42393     {$ENDIF}\r
42394   end;\r
42395 end;\r
42396 {$ENDIF ASM_VERSION}\r
42398 {$IFDEF ASM_VERSION}\r
42399 //[function TControl.GetItemsCount]\r
42400 function TControl.GetItemsCount: Integer;\r
42401 asm\r
42402         PUSH     0\r
42403         MOVZX    ECX, [EAX].fCommandActions.aGetCount\r
42404         JECXZ    @@ret_0\r
42405         PUSH     0\r
42406         PUSH     ECX\r
42407         PUSH     EAX\r
42408         CALL     Perform\r
42409         PUSH     EAX\r
42411 @@ret_0:\r
42412         POP      EAX\r
42413 end;\r
42414 {$ELSE ASM_VERSION} //Pascal\r
42415 function TControl.GetItemsCount: Integer;\r
42416 begin\r
42417   Result := 0;\r
42418   {$IFDEF DEBUG}\r
42419   try\r
42420   {$ENDIF}\r
42421   if fCommandActions.aGetCount = 0 then Exit;\r
42422   Result := Perform( fCommandActions.aGetCount, 0, 0 );\r
42423   {$IFDEF DEBUG}\r
42424   except\r
42425     asm\r
42426       int 3\r
42427     end;\r
42428   end;\r
42429   {$ENDIF}\r
42430 end;\r
42431 {$ENDIF ASM_VERSION}\r
42433 //*\r
42434 //[procedure TControl.SetItemsCount]\r
42435 procedure TControl.SetItemsCount(const Value: Integer);\r
42436 begin\r
42437   if fCommandActions.aSetCount = 0 then Exit;\r
42438   Perform( fCommandActions.aSetCount, Value, 0 );\r
42439 end;\r
42441 //[PROCEDURE HelpConvertItem2Pos]\r
42442 {$IFDEF ASM_VERSION}\r
42443 procedure HelpConvertItem2Pos;\r
42444 asm\r
42445         JECXZ     @@exit\r
42446         PUSH      0\r
42447         PUSH      EDX\r
42448         PUSH      ECX\r
42449         PUSH      EAX\r
42450         CALL      TControl.Perform\r
42451         XOR       EDX, EDX\r
42452         TEST      EAX, EAX\r
42453         JL        @@exit\r
42454         RET\r
42455 @@exit:\r
42456         MOV       EAX, EDX\r
42457 end;\r
42458 {$ENDIF ASM_VERSION}\r
42459 //[END HelpConvertItem2Pos]\r
42461 {$IFDEF ASM_VERSION}\r
42462 //[function TControl.Item2Pos]\r
42463 function TControl.Item2Pos(ItemIdx: Integer): Integer;\r
42464 asm\r
42465         MOVZX     ECX, [EAX].fCommandActions.aItem2Pos\r
42466         JMP       HelpConvertItem2Pos\r
42467 end;\r
42468 {$ELSE ASM_VERSION} //Pascal\r
42469 function TControl.Item2Pos(ItemIdx: Integer): Integer;\r
42470 begin\r
42471   Result := ItemIdx;\r
42472   if fCommandActions.aItem2Pos <> 0 then\r
42473   begin\r
42474     Result := Perform( fCommandActions.aItem2Pos, ItemIdx, 0 );\r
42475     if Result < 0 then Result := 0;\r
42476   end;\r
42477 end;\r
42478 {$ENDIF ASM_VERSION}\r
42480 {$IFDEF ASM_VERSION}\r
42481 //[function TControl.Pos2Item]\r
42482 function TControl.Pos2Item(Pos: Integer): Integer;\r
42483 asm\r
42484         MOVZX     ECX, [EAX].fCommandActions.aPos2Item\r
42485         JMP       HelpConvertItem2Pos\r
42486 end;\r
42487 {$ELSE ASM_VERSION} //Pascal\r
42488 function TControl.Pos2Item(Pos: Integer): Integer;\r
42489 begin\r
42490   Result := Pos;\r
42491   if fCommandActions.aPos2Item <> 0 then\r
42492   Result := Perform( fCommandActions.aPos2Item, Pos, 0 );\r
42493 end;\r
42494 {$ENDIF ASM_VERSION}\r
42496 //[function WndProcTabChar]\r
42497 function WndProcTabChar( Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;\r
42498 begin\r
42499   if M.message = WM_CHAR then\r
42500   begin\r
42501     if M.wParam = 9 then\r
42502     begin\r
42503       //M.wParam := 0;\r
42504       Sender.ReplaceSelection( #9, TRUE );\r
42505     end;\r
42506   end;\r
42507   Result := FALSE;\r
42508 end;\r
42510 //[function TControl.EditTabChar]\r
42511 function TControl.EditTabChar: PControl;\r
42512 begin\r
42513   AttachProc( WndProcTabChar );\r
42514   Result := @Self;\r
42515 end;\r
42517 {$IFDEF ASM_VERSION}\r
42518 //[function TControl.Add]\r
42519 function TControl.Add(const S: String): Integer;\r
42520 asm\r
42521         PUSH     EBX\r
42522         MOV      EBX, EAX               // EBX = @Self\r
42524         MOVZX    ECX, [EBX].fCommandActions.aAddItem   // ECX = aAddItem\r
42525         JECXZ    @@chk_addtext\r
42527         CALL     EDX2PChar\r
42528         PUSH     EDX\r
42529         PUSH     0\r
42530         PUSH     ECX\r
42531         PUSH     EBX\r
42532         CALL     Perform\r
42533         PUSH     EAX\r
42535         MOV      EAX, EBX\r
42536         CALL     TControl.GetItemsCount\r
42537         XCHG     EAX, ECX\r
42538         LOOP     @@ret_EAX\r
42540         XCHG     EAX, EBX\r
42541         INC      ECX\r
42542         XOR      EDX, EDX\r
42543         CALL     TControl.SetItemSelected\r
42544 @@ret_EAX:\r
42545         POP      EAX\r
42546         JMP      @@exit\r
42548 @@chk_addtext:\r
42549         MOV      ECX, [EBX].fCommandActions.aAddText\r
42550         JECXZ    @@add_text_simple\r
42552         CALL     ECX\r
42553         JMP      @@exit_0\r
42555 @@add_text_simple:\r
42556         PUSH     EDX\r
42557         PUSH     0\r
42558         MOV      EDX, ESP\r
42559         CALL     GetCaption\r
42560         POP      EAX\r
42561         POP      EDX\r
42562         PUSH     EAX\r
42563         MOV      EAX, ESP\r
42564         CALL     System.@LStrCat\r
42565         MOV      EAX, EBX\r
42566         POP      EDX\r
42567         PUSH     EDX\r
42568         CALL     SetCaption\r
42569         CALL     RemoveStr\r
42570 @@exit_0:\r
42571         XOR      EAX, EAX\r
42572 @@exit:\r
42573         POP      EBX\r
42574 end;\r
42575 {$ELSE ASM_VERSION} //Pascal\r
42576 function TControl.Add(const S: String): Integer;\r
42577 begin\r
42578   if fCommandActions.aAddItem <> 0 then\r
42579   begin\r
42580     Result := Perform( fCommandActions.aAddItem, 0, Integer( PChar( S ) ) );\r
42581     if Count = 1 then\r
42582       ItemSelected[ 0 ] := True;\r
42583   end\r
42584     else\r
42585   begin\r
42586     if assigned( fCommandActions.aAddText ) then\r
42587       fCommandActions.aAddText( @Self, S )\r
42588     else\r
42589       Text := Text + S;\r
42590     Result := 0;\r
42591   end;\r
42592 end;\r
42593 {$ENDIF ASM_VERSION}\r
42595 {$IFDEF ASM_VERSION}\r
42596 //[procedure TControl.Delete]\r
42597 procedure TControl.Delete(Idx: Integer);\r
42598 asm\r
42599         MOVZX    ECX, [EAX].fCommandActions.aDeleteItem\r
42600         JECXZ    @@exit\r
42602         PUSH     0\r
42603         PUSH     EDX\r
42604         PUSH     ECX\r
42605         PUSH     EAX\r
42606         CALL     Perform\r
42607 @@exit:\r
42608 end;\r
42609 {$ELSE ASM_VERSION} //Pascal\r
42610 procedure TControl.Delete(Idx: Integer);\r
42611 begin\r
42612   if fCommandActions.aDeleteItem <> 0 then\r
42613     Perform( fCommandActions.aDeleteItem, Idx, 0 );\r
42614 end;\r
42615 {$ENDIF ASM_VERSION}\r
42617 {$IFDEF ASM_VERSION}\r
42618 //[function TControl.Insert]\r
42619 function TControl.Insert(Idx: Integer; const S: String): Integer;\r
42620 asm\r
42621          CALL    ECX2PChar\r
42622          PUSH    ECX\r
42623          MOVZX   ECX, [EAX].fCommandActions.aInsertItem\r
42624          JECXZ   @@exit_1\r
42626          PUSH    EDX\r
42627          PUSH    ECX\r
42628          PUSH    EAX\r
42629          CALL    Perform\r
42630          RET\r
42632 @@exit_1:OR      EAX, -1\r
42633          POP     ECX\r
42634 end;\r
42635 {$ELSE ASM_VERSION} //Pascal\r
42636 function TControl.Insert(Idx: Integer; const S: String): Integer;\r
42637 begin\r
42638   if fCommandActions.aInsertItem <> 0 then\r
42639     Result := Perform( fCommandActions.aInsertItem, Idx, Integer( PChar( S ) ) )\r
42640   else\r
42641     Result := -1;\r
42642 end;\r
42643 {$ENDIF ASM_VERSION}\r
42645 {$IFDEF ASM_VERSION}\r
42646 //[function TControl.GetItemSelected]\r
42647 function TControl.GetItemSelected(ItemIdx: Integer): Boolean;\r
42648 asm\r
42649         MOVZX    ECX, [EAX].fCommandActions.aGetSelected\r
42650         JECXZ    @@check_range\r
42652         PUSH     0\r
42653         PUSH     EDX\r
42654         PUSH     ECX\r
42655         PUSH     EAX\r
42656         CALL     Perform\r
42657         TEST     EAX, EAX\r
42658         SETG     AL\r
42659         RET\r
42661 @@check_range:\r
42662         MOVZX    ECX, [EAX].fCommandActions.aGetSelRange\r
42663         JECXZ    @@check_ex\r
42665           PUSH     EDX\r
42666         PUSH     0\r
42667         PUSH     0\r
42668         PUSH     ECX\r
42669         PUSH     EAX\r
42670         CALL     Perform\r
42671           POP      EDX\r
42672         TEST     EAX, EAX\r
42673         JL       @@ret_false\r
42675         CMP      DX, AX\r
42676         JL       @@ret_false\r
42678         SHR      EAX, 16\r
42679         SUB      EDX, EAX\r
42680         SETL     AL\r
42681         RET\r
42683 @@check_ex:\r
42684         MOVZX    ECX, [EAX].fCommandActions.aExGetSelRange\r
42685         JECXZ    @@ret_false\r
42686           PUSH     EDX\r
42687         PUSH     EDX\r
42688         PUSH     EDX\r
42689         PUSH     ESP\r
42690         PUSH     0\r
42691         PUSH     ECX\r
42692         PUSH     EAX\r
42693         CALL     Perform\r
42694         POP      ECX\r
42695         POP      EDX\r
42696           POP      EAX\r
42698         SUB      EAX, EDX\r
42699         CMP      EAX, ECX\r
42700         SETB     AL\r
42701         RET\r
42703 @@ret_false:\r
42704         XOR      EAX, EAX\r
42705 end;\r
42706 {$ELSE ASM_VERSION} //Pascal\r
42707 function TControl.GetItemSelected(ItemIdx: Integer): Boolean;\r
42708 var SR: TCharRange;\r
42709 begin\r
42710   Result := False;\r
42711   if fCommandActions.aGetSelected <> 0 then\r
42712     Result := 0 < Perform( fCommandActions.aGetSelected, ItemIdx, 0 )\r
42713   else if fCommandActions.aGetSelRange <> 0 then\r
42714   begin\r
42715     Perform( fCommandActions.aGetSelRange, Integer( @SR.cpMin ), Integer( @SR.cpMax ) );\r
42716     Result := (SR.cpMin <= ItemIdx) and (ItemIdx < SR.cpMax);\r
42717   end\r
42718   else if fCommandActions.aExGetSelRange <> 0 then\r
42719   begin\r
42720     Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );\r
42721     Result := (SR.cpMin <= ItemIdx) and (ItemIdx < SR.cpMax);\r
42722   end;\r
42723 end;\r
42724 {$ENDIF ASM_VERSION}\r
42726 {$IFDEF ASM_VERSION}\r
42727 //[procedure TControl.SetItemSelected]\r
42728 procedure TControl.SetItemSelected(ItemIdx: Integer; const Value: Boolean);\r
42729 asm\r
42730         PUSH     EDX\r
42731         PUSH     ECX\r
42732         MOVZX    ECX, [EAX].fCommandActions.aSetSelected\r
42733         JECXZ    @@chk_aSetCurrent\r
42735 @@0:\r
42736         PUSH     ECX\r
42737         PUSH     EAX\r
42738         CALL     Perform\r
42739         RET\r
42741 @@chk_aSetCurrent:\r
42742         POP      ECX\r
42743         MOVZX    ECX, [EAX].fCommandActions.aSetCurrent\r
42744         JECXZ    @@chk_aSetSelRange\r
42746         POP      EDX\r
42747         PUSH     0\r
42748         JMP      @@3\r
42750 @@chk_aSetSelRange:\r
42751         MOVZX    ECX, [EAX].fCommandActions.aSetSelRange\r
42752         JECXZ    @@chk_aExSetSelRange\r
42753 @@3:\r
42754         PUSH     EDX\r
42755         JMP      @@0\r
42757 @@else: MOV      [EAX].FCurIndex, EDX\r
42758         CALL     Invalidate\r
42759         JMP      @@exit\r
42761 @@chk_aExSetSelRange:\r
42762         MOVZX    ECX, [EAX].fCommandActions.aExSetSelRange\r
42763         JECXZ    @@else\r
42765         PUSH     EDX\r
42766         PUSH     ESP\r
42767         PUSH     0\r
42768         PUSH     ECX\r
42769         PUSH     EAX\r
42770         CALL     Perform\r
42771         POP      ECX\r
42773 @@exit:\r
42774         POP      ECX\r
42775 end;\r
42776 {$ELSE ASM_VERSION} //Pascal\r
42777 procedure TControl.SetItemSelected(ItemIdx: Integer; const Value: Boolean);\r
42778 var SR: TCharRange;\r
42779 begin\r
42780   if fCommandActions.aSetSelected <> 0 then\r
42781     Perform( fCommandActions.aSetSelected, Integer( Value ), ItemIdx )\r
42782   else\r
42783   if fCommandActions.aSetCurrent <> 0 then\r
42784     Perform( fCommandActions.aSetCurrent, ItemIdx, 0 )\r
42785   else\r
42786   if fCommandActions.aSetSelRange <> 0 then\r
42787     Perform( fCommandActions.aSetSelRange, ItemIdx, ItemIdx )\r
42788   else\r
42789   if fCommandActions.aExSetSelRange <> 0 then\r
42790   begin\r
42791     SR.cpMin := ItemIdx;\r
42792     SR.cpMax := ItemIdx;\r
42793     Perform( fCommandActions.aExSetSelRange, 0, Integer( @SR ) );\r
42794   end\r
42795     else\r
42796   begin // for ImageShow: set the index and invalidate the control\r
42797     FCurIndex := ItemIdx;\r
42798     Invalidate;\r
42799   end;\r
42800 end;\r
42801 {$ENDIF ASM_VERSION}\r
42803 {$IFDEF ASM_VERSION}\r
42804 //[procedure TControl.SetCtl3D]\r
42805 procedure TControl.SetCtl3D(const Value: Boolean);\r
42806 asm\r
42807         MOV      [EAX].fCtl3Dchild, DL\r
42808         CMP      [EAX].fCtl3D, DL\r
42809         JE       @@exit\r
42810         MOV      [EAX].fCtl3D, DL\r
42811         PUSHAD\r
42812         CALL     UpdateWndStyles\r
42813         POPAD\r
42814         MOV      ECX, [EAX].fExStyle\r
42815         DEC      DL\r
42816         MOV      EDX, [EAX].fStyle\r
42817         JNZ      @@1\r
42818         AND      EDX, not WS_BORDER\r
42819         OR       CH, WS_EX_CLIENTEDGE shr 8\r
42820         JMP      @@2\r
42821 @@1:\r
42822         OR       EDX, WS_BORDER\r
42823         AND      CH, not(WS_EX_CLIENTEDGE shr 8)\r
42824 @@2:\r
42825         PUSH     ECX\r
42826         PUSH     EAX\r
42827         CALL     SetStyle\r
42828         POP      EAX\r
42829         POP      EDX\r
42830         JMP      SetExStyle\r
42831 @@exit:\r
42832 end;\r
42833 {$ELSE ASM_VERSION} //Pascal\r
42834 procedure TControl.SetCtl3D(const Value: Boolean);\r
42835 begin\r
42836   fCtl3Dchild := Value;\r
42837   if fCtl3D = Value then Exit;\r
42838   fCtl3D := Value;\r
42839   UpdateWndStyles;\r
42840   if Value then\r
42841   begin\r
42842     ExStyle := fExStyle or WS_EX_CLIENTEDGE;\r
42843     Style := fStyle and not WS_BORDER;\r
42844   end\r
42845      else\r
42846   begin\r
42847     ExStyle := fExStyle and not WS_EX_CLIENTEDGE;\r
42848     Style := fStyle or WS_BORDER;\r
42849   end;\r
42850 end;\r
42851 {$ENDIF ASM_VERSION}\r
42853 {$IFDEF ASM_VERSION}\r
42854 //[function TControl.Shift]\r
42855 function TControl.Shift(dX, dY: Integer): PControl;\r
42856 asm\r
42857         PUSHAD\r
42858         ADD      EDX, [EAX].fBoundsRect.TRect.Left\r
42859         CALL     SetLeft\r
42860         POPAD\r
42861         PUSH     EAX\r
42862         MOV      EDX, [EAX].fBoundsRect.TRect.Top\r
42863         ADD      EDX, ECX\r
42864         CALL     SetTop\r
42865         POP      EAX\r
42866 end;\r
42867 {$ELSE ASM_VERSION} //Pascal\r
42868 function TControl.Shift(dX, dY: Integer): PControl;\r
42869 begin\r
42870   Left := fBoundsRect.Left + dX;\r
42871   Top := fBoundsRect.Top + dY;\r
42872   Result := @Self;\r
42873 end;\r
42874 {$ENDIF ASM_VERSION}\r
42876 //[procedure SetKeyEvent]\r
42877 procedure SetKeyEvent( Self_: PControl );\r
42878 begin\r
42879   Self_.fWndProcKeybd := WndProcKeybd;\r
42880   //Self_.AttachProc( WndProcKeyBd );\r
42881 end;\r
42883 //[procedure TControl.SetOnChar]\r
42884 procedure TControl.SetOnChar(const Value: TOnChar);\r
42885 begin\r
42886   fOnChar := Value;\r
42887   SetKeyEvent( @Self );\r
42888 end;\r
42890 //[procedure TControl.SetOnKeyDown]\r
42891 procedure TControl.SetOnKeyDown(const Value: TOnKey);\r
42892 begin\r
42893   fOnKeyDown := Value;\r
42894   SetKeyEvent( @Self );\r
42895 end;\r
42897 //[procedure TControl.SetOnKeyUp]\r
42898 procedure TControl.SetOnKeyUp(const Value: TOnKey);\r
42899 begin\r
42900   fOnKeyUp := Value;\r
42901   SetKeyEvent( @Self );\r
42902 end;\r
42904 //[FUNCTION CollectTabControls]\r
42905 {$IFDEF ASM_VERSION}\r
42906 function CollectTabControls( Form: PControl ): PList;\r
42907 asm\r
42908         PUSH     EDI\r
42909         PUSH     EAX\r
42910         CALL     NewList\r
42911         XCHG     EDI, EAX\r
42912         POP      EAX\r
42913         CALL     @@collecttab\r
42914         XCHG     EAX, EDI\r
42915         POP      EDI\r
42916         RET\r
42917 @@collecttab:\r
42918         { <- EDI = Result:PList\r
42919              EAX = Form (or Control)\r
42920         }\r
42921         PUSH     ESI\r
42922         PUSH     EBX\r
42923         MOV      EDX, [EAX].TControl.fChildren\r
42924         MOV      ECX, [EDX].TList.fCount\r
42925         MOV      ESI, [EDX].TList.fItems\r
42926         JECXZ    @@e_loop\r
42927 @@loo:  PUSH     ECX\r
42928         LODSD\r
42930           PUSH     EAX\r
42932         TEST     byte ptr [EAX].TControl.fStyle+2, WS_TABSTOP shr 16\r
42933         JZ       @@call_recur\r
42935         MOV      DL, [EAX].TControl.fTabStop\r
42936         AND      DL, [EAX].TControl.fEnabled\r
42937         JZ       @@call_recur\r
42939         CALL     TControl.GetToBeVisible\r
42940         TEST     AL, AL\r
42941         POP      EAX\r
42942         JZ       @@next\r
42943         PUSH     EAX\r
42945           XCHG     EDX, EAX\r
42946           PUSH     ESI\r
42947           MOV      ECX, [EDI].TList.fCount\r
42948           MOV      ESI, [EDI].TList.fItems\r
42949           XOR      EBX, EBX\r
42950           JECXZ    @@e_loo2\r
42951 @@loo2:   LODSD\r
42952           MOV      EAX, [EAX].TControl.fTabOrder\r
42953           CMP      EAX, [EDX].TControl.fTabOrder\r
42954           JLE      @@next2\r
42955           POP      ESI\r
42956           MOV      ECX, EDX\r
42957           MOV      EDX, EBX\r
42958           MOV      EAX, EDI\r
42959           CALL     TList.Insert\r
42960           JMP      @@call_recur\r
42962 @@next2:  INC      EBX\r
42963           LOOP     @@loo2\r
42964 @@e_loo2:\r
42965           POP      ESI\r
42966           MOV      EAX, EDI\r
42967           CALL     TList.Add\r
42969 @@call_recur:\r
42970           POP      EAX\r
42971           MOVZX    ECX, [EAX].TControl.fEnabled\r
42972           JECXZ    @@next\r
42973           CALL     @@collecttab\r
42975 @@next: POP      ECX\r
42976         LOOP     @@loo\r
42978 @@e_loop:\r
42979         POP      EBX\r
42980         POP      ESI\r
42981 end;\r
42982 {$ELSE ASM_VERSION} //Pascal\r
42983 function CollectTabControls( Form: PControl ): PList;\r
42984 var R: PList;\r
42985   procedure CollectTab( P: PControl );\r
42986   var I, J: Integer;\r
42987       C, D: PControl;\r
42988   begin\r
42989     for I := 0 to P.fChildren.fCount - 1 do\r
42990     begin\r
42991       C := P.fChildren.fItems[ I ];\r
42992       if C.fTabstop and C.fEnabled and C.ToBeVisible and\r
42993          (C.fStyle and WS_TABSTOP <> 0) then\r
42994       begin\r
42995         D := nil;\r
42996         for J := 0 to R.fCount - 1 do\r
42997         begin\r
42998           D := R.fItems[ J ];\r
42999           if D.fTabOrder > C.fTabOrder then\r
43000           begin\r
43001             R.Insert( J, C );\r
43002             break;\r
43003           end\r
43004              else\r
43005             D := nil;\r
43006         end;\r
43007         if D = nil then\r
43008            R.Add( C );\r
43009       end;\r
43010       if C.fEnabled then\r
43011         CollectTab( C );\r
43012     end;\r
43013   end;\r
43014 begin\r
43015   R := NewList;\r
43016   CollectTab( Form );\r
43017   Result := R;\r
43018 end;\r
43019 {$ENDIF ASM_VERSION}\r
43020 //[END CollectTabControls]\r
43022 //[PROCEDURE Tabulate2Next]\r
43023 {$IFDEF ASM_VERSION}\r
43024 procedure Tabulate2Next( Form: PControl; Dir: Integer );\r
43025 asm\r
43026         PUSHAD\r
43027         PUSH     EAX      // save Form\r
43028         MOV      EBX, EAX\r
43029         MOV      EBP, EDX // EBP = Dir (direction <0 or >0)\r
43030         CALL     CollectTabControls\r
43031         XCHG     EDI, EAX // EDI = CL (list of controls)\r
43033         MOV      ECX, [EBX].TControl.fCurrentControl // C := Form.fCurrentControl\r
43034         XOR      EBX, EBX // I = 0\r
43035         JECXZ    @@1\r
43036         MOV      EBX, [ECX].TControl.fTabOrder // I = C.fTabOrder\r
43037 @@1:\r
43038         MOV      ECX, [EDI].TList.fCount\r
43039         MOV      ESI, [EDI].TList.fItems\r
43040         XOR      EDX, EDX\r
43041         PUSH     EDX      // Ctrl1 = nil\r
43042         PUSH     EDX      // Ctrl2 = nil\r
43043         //JECXZ    @@e_loop\r
43044         TEST     ECX, ECX\r
43045         JZ       @@e_loop\r
43047 @@loop: PUSH     ECX\r
43048         LODSD\r
43049         CMP      [EAX].TControl.fTabOrder, EBX\r
43050         JZ       @@next\r
43052         MOV      ECX, [ESP+8] // ECX = Ctrl1\r
43053         JECXZ    @@c1nil\r
43054         MOV      ECX, [ECX].TControl.fTabOrder // ECX = Ctrl1.fTabOrder\r
43055         TEST     EBP, EBP\r
43056         JGE      @@c1ge\r
43058         CMP      [EAX].TControl.fTabOrder, EBX\r
43059         JGE      @@2\r
43060         CMP      [EAX].TControl.fTabOrder, ECX\r
43061         JLE      @@2\r
43063 @@c1new:\r
43064         MOV      [ESP+8], EAX // Ctrl1 := C\r
43065         JMP      @@2\r
43067 @@c1ge: CMP      [EAX].TControl.fTabOrder, EBX\r
43068         JLE      @@2\r
43069         CMP      [EAX].TControl.fTabOrder, ECX\r
43070         JL       @@c1new\r
43071         JMP      @@2\r
43073 @@c1nil:\r
43074         TEST     EBP, EBP\r
43075         JL       @@c1nil_dirL\r
43076         CMP      [EAX].TControl.fTabOrder, EBX\r
43077         JG       @@c1new\r
43078         JMP      @@2\r
43080 @@c1nil_dirL:\r
43081         CMP      [EAX].TControl.fTabOrder, EBX\r
43082         JL       @@c1new\r
43084 @@2:\r
43085         MOV      ECX, [ESP+4] // ECX = Ctrl2\r
43086         JECXZ    @@c2new\r
43087         MOV      ECX, [ECX].TControl.fTabOrder\r
43089         TEST     EBP, EBP\r
43090         JL       @@c2dirL\r
43091         CMP      [EAX].TControl.fTabOrder, ECX\r
43092         JGE      @@next\r
43093         JMP      @@c2new\r
43095 @@c2dirL:\r
43096         CMP      [EAX].TControl.fTabOrder, ECX\r
43097         JLE      @@next\r
43098 @@c2new:\r
43099         MOV      [ESP+4], EAX\r
43101 @@next: POP      ECX\r
43102         DEC      ECX\r
43103         JNZ      @@loop\r
43104         //LOOP     @@loop\r
43105 @@e_loop:\r
43107         POP      EDX // Ctrl2\r
43108         POP      ECX // Ctrl1\r
43109         INC      ECX\r
43110         LOOP     @@3\r
43111         MOV      ECX, EDX\r
43112 @@3:\r
43113         POP      EBX // EBX = Form\r
43114         JECXZ    @@exit\r
43116         XCHG     EAX, ECX\r
43117         MOV      ECX, [EAX].TControl.fHandle\r
43118         JECXZ    @@no_handle\r
43120         INC      [EAX].TControl.fClickDisabled\r
43121         PUSH     EAX\r
43122         PUSH     ECX\r
43123         CALL     Windows.SetFocus\r
43124         POP      EAX\r
43125         DEC      [EAX].TControl.fClickDisabled\r
43127 @@no_handle:\r
43128         MOV      [EBX].TControl.fCurrentControl, EAX\r
43130 @@exit:\r
43131         XCHG     EAX, EDI\r
43132         CALL     TObj.Free\r
43133         POPAD\r
43134 end;\r
43135 {$ELSE ASM_VERSION} //Pascal\r
43136 procedure Tabulate2Next( Form: PControl; Dir: Integer );\r
43137 var CL : PList;\r
43138     I, J : Integer;\r
43139     Ctrl1, Ctrl2, C : PControl;\r
43140 begin\r
43141   CL := CollectTabControls( Form );\r
43143   I := 0;\r
43144   C := Form.fCurrentControl;\r
43145   if C <> nil then\r
43146     I := C.fTabOrder;\r
43147   Ctrl2 := nil;\r
43148   Ctrl1 := nil;\r
43149   for J := 0 to CL.fCount - 1 do\r
43150   begin\r
43151     C := CL.fItems[ J ];\r
43152     if C.fTabOrder = I then continue;\r
43153     if (Ctrl1 = nil)\r
43154        and (    (Dir >= 0) and (C.fTabOrder > I)\r
43155              or (Dir < 0) and (C.fTabOrder < I)  )\r
43156     or (Dir >= 0)\r
43157        and (C.fTabOrder > I) and (C.fTabOrder < Ctrl1.fTabOrder)\r
43158     or (Dir < 0)\r
43159        and (C.fTabOrder < I) and (C.fTabOrder > Ctrl1.fTabOrder)\r
43160     then Ctrl1 := C;\r
43161     if (Ctrl2 = nil)\r
43162     or (Dir >= 0) and (C.fTabOrder < Ctrl2.fTabOrder)\r
43163     or (Dir < 0) and (C.fTabOrder > Ctrl2.fTabOrder)\r
43164     then Ctrl2 := C;\r
43165   end;\r
43166   if Ctrl1 = nil then\r
43167     Ctrl1 := Ctrl2;\r
43168   if Ctrl1 <> nil then\r
43169   begin\r
43170     if Ctrl1.fHandle <> 0 then\r
43171     begin\r
43172       Inc( Ctrl1.fClickDisabled );\r
43173       SetFocus( Ctrl1.fHandle );\r
43174       Dec( Ctrl1.fClickDisabled );\r
43175     end;\r
43176     Form.fCurrentControl := Ctrl1;\r
43177   end;\r
43178   CL.Free;\r
43179 end;\r
43180 {$ENDIF ASM_VERSION}\r
43181 //[END Tabulate2Next]\r
43183 //[FUNCTION Tabulate2Control]\r
43184 {$IFDEF ASM_VERSION}\r
43185 function Tabulate2Control( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;\r
43186 const tk_Tab = 1;\r
43187       tk_LR  = 2;\r
43188       tk_UD  = 4;\r
43189       tk_PuPd= 8;\r
43190 asm\r
43191         PUSH     ESI\r
43192         MOV      ESI, offset[@@data]\r
43193         PUSH     EAX\r
43194         MOV      AH, 9\r
43195 @@loop:\r
43196         LODSB\r
43197         CMP      DL, AL\r
43198         JE       @@1\r
43199         LODSB\r
43200         CMP      DL, AL\r
43201         JE       @@2\r
43202         ADD      AH, AH\r
43203         JNB      @@loop\r
43204         POP      EAX\r
43205 @@exit0:\r
43206         XOR      EAX, EAX\r
43207         JMP      @@exit\r
43209 @@data:\r
43210         DB       -1, VK_TAB, VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT\r
43212 @@1:\r
43213         OR       EDX, -1\r
43214         JMP      @@3\r
43215 @@2:\r
43216         XOR      EDX, EDX\r
43217         TEST     AH, 1\r
43218         JZ       @@3\r
43220           PUSH     ECX\r
43221         PUSH     EAX\r
43222         PUSH     VK_SHIFT\r
43223         CALL     GetAsyncKeyState\r
43224         CDQ\r
43225         POP      EAX\r
43226           POP      ECX\r
43227 @@3:\r
43228         POP      ESI\r
43229         //////////////////////////////////////////////////\r
43230         MOV      AL, AH\r
43231         {$IFDEF PARANOIA}\r
43232         DB $24, 1\r
43233         {$ELSE}\r
43234         AND      AL, 1\r
43235         {$ENDIF}\r
43236         TEST     byte ptr [ESI].TControl.fLookTabKeys, AL\r
43237         //////////////////////////////////////////////////\r
43238         JZ       @@exit0\r
43240         TEST     CL, CL\r
43241         JNZ      @@exit\r
43243         PUSH     EDX\r
43244         MOV      EAX, ESI\r
43245         CALL     TControl.ParentForm\r
43246         POP      EDX\r
43247         CALL     Tabulate2Next\r
43248 @@exit:\r
43249         POP      ESI\r
43250 end;\r
43251 {$ELSE ASM_VERSION} //Pascal\r
43252 function Tabulate2Control( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;\r
43253 var Form: PControl;\r
43254 begin\r
43255   Result := False;\r
43256   case Key of\r
43257   VK_TAB: if not (tkTab in Self_.fLookTabKeys) then exit;\r
43258   VK_LEFT, VK_RIGHT: if not (tkLeftRight in Self_.fLookTabKeys) then exit;\r
43259   VK_UP, VK_DOWN: if not (tkUpDown in Self_.fLookTabKeys) then exit;\r
43260   VK_NEXT, VK_PRIOR: if not (tkPageUpPageDn in Self_.fLookTabKeys) then exit;\r
43261   else Exit;\r
43262   end;\r
43264   Result := True;\r
43265   if checkOnly then Exit;\r
43267   Form := Self_.ParentForm;\r
43268   case Key of\r
43269   VK_TAB:\r
43270     if GetKeyState( VK_SHIFT ) < 0 then\r
43271       Tabulate2Next( Form, -1 )\r
43272     else\r
43273       Tabulate2Next( Form, 1 );\r
43274   VK_RIGHT, VK_DOWN, VK_NEXT: Tabulate2Next( Form, 1 );\r
43275   VK_LEFT, VK_UP, VK_PRIOR:   Tabulate2Next( Form, -1 );\r
43276   end;\r
43277 end;\r
43278 {$ENDIF ASM_VERSION}\r
43279 //[END Tabulate2Control]\r
43281 //[FUNCTION Tabulate2ControlEx]\r
43282 {$IFDEF ASM_VERSION}\r
43283 function Tabulate2ControlEx( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;\r
43284 asm\r
43285         PUSH     EDI\r
43286         MOVZX    EDI, CL\r
43287         TEST     byte ptr [EAX].TControl.fLookTabKeys, 1\r
43288         JZ       @@1\r
43289 @@0:\r
43290         MOV      ECX, EDX\r
43291         AND      CL, 7Fh\r
43292         CMP      CL, VK_TAB\r
43293         JNE      @@1\r
43295         PUSH     EDX\r
43296         CALL     TControl.ParentForm\r
43297         POP      EDX\r
43298         MOVSX    EDX, DL\r
43299         TEST     EDX, EDX\r
43300         JS       @@tab\r
43302         PUSH     EAX\r
43304         PUSH     VK_SHIFT\r
43305         CALL     GetAsyncKeyState\r
43306         SAR      EAX, 31\r
43307         {$IFDEF PARANOIA}\r
43308         DB $0C, $01\r
43309         {$ELSE}\r
43310         OR       AL, 1\r
43311         {$ENDIF}\r
43312         MOV      EDX, EAX\r
43314         POP      EAX\r
43315 @@tab:\r
43316         TEST     EDI, EDI\r
43317         POP      EDI\r
43318         JNZ      @@no_tab\r
43319         CALL     Tabulate2Next\r
43320 @@no_tab:\r
43321         MOV      AL, 1\r
43322         RET\r
43324 @@data: DB VK_LEFT, VK_LEFT\r
43325         DD offset[@@left]\r
43326         DB VK_UP, 2\r
43327         DB VK_RIGHT, VK_RIGHT\r
43328         DD offset[@@right]\r
43329         DB VK_DOWN, 2\r
43330         DB VK_UP, VK_PRIOR\r
43331         DD offset[@@up]\r
43332         DB VK_TAB or 80h, $C\r
43333         DB VK_DOWN, VK_NEXT\r
43334         DD offset[@@down]\r
43335         DB VK_TAB, $C\r
43337 @@1:\r
43338         {\r
43339           EAX <- Self_:PControl\r
43340            DL <- Key\r
43341         }\r
43342         PUSH     ESI\r
43343         MOV      ESI, offset[@@data]-6\r
43344         MOV      DH, 9\r
43345         PUSH     EAX\r
43346 @@loop:\r
43347         ADD      DH, DH\r
43348         JNB      @@l1\r
43349         JMP      @@abort\r
43350 @@fault1:\r
43351         POP      EDI\r
43352         POPAD\r
43353         PUSH     EAX\r
43354 @@abort:\r
43355         POP      EAX\r
43356 @@abort1:\r
43357         POP      ESI\r
43358         POP      EDI\r
43359         XOR      EAX, EAX\r
43360         RET\r
43362 @@right:\r
43363         MOV      EAX, [ESP].TRect.Left\r
43364         SUB      EAX, [ESP+16].TRect.Left\r
43365 @@left_right:\r
43366         JL       @@next1\r
43367         MOV      EDX, [ESP].TRect.Bottom\r
43368         SUB      EDX, [ESP+16].TRect.Top\r
43369         JL       @@next1\r
43370         MOV      EDX, [ESP].TRect.Top\r
43371         SUB      EDX, [ESP+16].TRect.Bottom\r
43372         JGE      @@next1\r
43373 @@chk_dist:\r
43374         CMP      EAX, EDI\r
43375         JA       @@next1\r
43376         MOV      EDI, EAX\r
43377         MOV      EAX, [EBX+ECX*4-4]\r
43378         MOV      [ESP+36], EAX     // Found = Ctrl\r
43379         JMP      @@next1\r
43381 @@l1:\r
43382         LODSD\r
43383         LODSW\r
43384         LODSW\r
43385         CMP      AL, DL\r
43386         JE       @@2\r
43387         CMP      AH, DL\r
43388         JNE      @@loop\r
43390 @@2:\r
43391         PUSH     ESI\r
43392         LODSD\r
43393         LODSW\r
43394         POP      ESI\r
43395         XCHG     EDX, EAX\r
43396         POP      EAX\r
43397         TEST     [EAX].TControl.fLookTabKeys, DH      \r
43398         JZ       @@abort1\r
43400         PUSHAD\r
43401         PUSH     EDI\r
43402         CALL     TControl.ParentForm\r
43403         MOV      ECX, [EAX].TControl.fCurrentControl\r
43404         JECXZ    @@fault1\r
43405         MOV      EBP, ECX           // EBP = CurCtrl\r
43407         PUSH     EAX                // save Form\r
43408         MOV      EBX, EAX\r
43409         CALL     CollectTabControls\r
43410         PUSH     0                  // save Found = nil\r
43411         PUSH     EAX                // save CollectedList\r
43412         MOV      EDI, EAX\r
43414         MOV      EBX, [EDI].TList.fItems\r
43415         ADD      ESP, -16\r
43416         PUSH     ESP\r
43417         PUSH     [EBP].TControl.fHandle\r
43418         CALL     GetWindowRect\r
43420         MOV      ECX, [EDI].TList.fCount\r
43421         OR       EDI, -1            // EDI = minDist\r
43422 @@loop1:\r
43423         MOV      EAX, [EBX+ECX*4-4]\r
43424         CMP      EAX, EBP\r
43425         JE       @@next\r
43426         {}\r
43427         MOV      DL, [EAX].TControl.fEnabled\r
43428         AND      DL, [EAX].TControl.fTabstop\r
43429         JZ       @@next\r
43430         {}\r
43431         ADD      ESP, -16\r
43432         MOV      EDX, ESP\r
43433         PUSH     ECX\r
43435         //CALL     TControl.ControlRect\r
43436         PUSH     EDX\r
43437         PUSH     [EAX].TControl.fHandle\r
43438         CALL     GetWindowRect\r
43440         POP      ECX\r
43441         JMP      dword ptr [ESI]\r
43443 @@left:\r
43444         MOV      EAX, [ESP+16].TRect.Left\r
43445         SUB      EAX, [ESP].TRect.Left\r
43446         JMP      @@left_right\r
43448 @@not_found:\r
43449         POP      EDI\r
43450         POPAD\r
43451         MOV      DL, [ESI+4]\r
43452         POP      ESI\r
43453         JMP      @@0\r
43455 @@up:\r
43456         MOV      EAX, [ESP+16].TRect.Top\r
43457         SUB      EAX, [ESP].TRect.Top\r
43458         JMP      @@up_down\r
43459 @@down:\r
43460         MOV      EAX, [ESP].TRect.Top\r
43461         SUB      EAX, [ESP+16].TRect.Top\r
43462 @@up_down:\r
43463         JL       @@next1\r
43464         MOV      EDX, [ESP].TRect.Right\r
43465         SUB      EDX, [ESP+16].TRect.Left\r
43466         JL       @@next1\r
43467         MOV      EDX, [ESP].TRect.Left\r
43468         SUB      EDX, [ESP+16].TRect.Right\r
43469         JL       @@chk_dist\r
43471 @@next1:\r
43472         ADD      ESP, 16\r
43473 @@next:\r
43474         LOOP     @@loop1\r
43475         ADD      ESP, 16\r
43476         POP      EAX       // pop CollectedList\r
43477         CALL     TObj.Free\r
43478         POP      ECX       // pop Found\r
43479         POP      EAX       // pop Form\r
43480         JECXZ    @@not_found\r
43482         POP      EDI\r
43483         TEST     EDI, EDI\r
43484         JNZ      @@no_go\r
43486         MOV      [EAX].TControl.fCurrentControl, ECX\r
43487         INC      [ECX].TControl.fClickDisabled\r
43488         PUSH     ECX\r
43489         MOV      ECX, [ECX].TControl.fHandle\r
43490         JECXZ    @@4\r
43491         PUSH     ECX\r
43492         CALL     Windows.SetFocus\r
43493 @@4:    POP      ECX\r
43494         DEC      [ECX].TControl.fClickDisabled\r
43495 @@no_go:\r
43496         POPAD\r
43497         POP      ESI\r
43498         POP      EDI\r
43499         MOV      AL, 1      // Result = True\r
43500 end;\r
43501 {$ELSE ASM_VERSION} //Pascal\r
43502 function Tabulate2ControlEx( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;\r
43503 label search_tabcontrol;\r
43504 var Form: PControl;\r
43505     CL : PList;\r
43506     I : Integer;\r
43507     CurCtrl, Ctrl, Found : PControl;\r
43508     MinDist, Dist: Integer;\r
43509     R, R1 : TRect;\r
43510 begin\r
43511   Result := False;\r
43512   case Key of\r
43513   VK_TAB: if not (tkTab in Self_.fLookTabKeys) then exit;\r
43514   VK_LEFT, VK_RIGHT: if not (tkLeftRight in Self_.fLookTabKeys) then exit;\r
43515   VK_UP, VK_DOWN: if not (tkUpDown in Self_.fLookTabKeys) then exit;\r
43516   VK_NEXT, VK_PRIOR: if not (tkPageUpPageDn in Self_.fLookTabKeys) then exit;\r
43517   else exit;\r
43518   end;\r
43520   Result := True;\r
43521   if checkOnly then Exit;\r
43523   Form := Self_.ParentForm;\r
43524   if Key = VK_TAB then\r
43525     if GetKeyState( VK_SHIFT ) < 0 then\r
43526       Tabulate2Next( Form, -1 )\r
43527     else\r
43528       Tabulate2Next( Form, 1 )\r
43529   else\r
43530   begin\r
43531     CL := CollectTabControls( Form );\r
43532     I := CL.IndexOf( Form.fCurrentControl );\r
43533     Found := nil;\r
43534     if I >= 0 then\r
43535     begin\r
43536       CurCtrl := CL.fItems[ I ];\r
43537       //R := CurCtrl.ControlRect;\r
43538       GetWindowRect( CurCtrl.Handle, R );\r
43539     search_tabcontrol:\r
43540       MinDist := MaxInt;\r
43541       for I := CL.fCount - 1 downto 0 do\r
43542       begin\r
43543         Ctrl := CL.fItems[ I ];\r
43544         if Ctrl = CurCtrl then continue;\r
43545         if not (Ctrl.fEnabled and Ctrl.fTabstop) then continue;\r
43546         //R1 := Ctrl.ControlRect;\r
43547         GetWindowRect( Ctrl.Handle, R1 );\r
43548         Dist := MaxInt;\r
43549         case Key of\r
43550           VK_LEFT:\r
43551             begin\r
43552               if (R1.Bottom < R.Top)\r
43553               or (R1.Top >= R.Bottom)\r
43554               or (R1.Left > R.Left) then continue;\r
43555               Dist := R.Left - R1.Left;\r
43556             end;\r
43557           VK_RIGHT:\r
43558             begin\r
43559               if (R1.Bottom < R.Top)\r
43560               or (R1.Top >= R.Bottom)\r
43561               or (R1.Left < R.Left) then continue;\r
43562               Dist := R1.Left - R.Left;\r
43563             end;\r
43564           VK_UP, VK_PRIOR:\r
43565             begin\r
43566               if (R1.Right < R.Left)\r
43567               or (R1.Left >= R.Right)\r
43568               or (R1.Top > R.Top) then continue;\r
43569               Dist := R.Top - R1.Top;\r
43570             end;\r
43571           VK_DOWN, VK_NEXT:\r
43572             begin\r
43573               if (R1.Right < R.Left)\r
43574               or (R1.Left >= R.Right)\r
43575               or (R1.Top < R.Bottom) then continue;\r
43576               Dist := R1.Top - R.Top;\r
43577             end;\r
43578         end;\r
43579         if Dist < MinDist then\r
43580         begin\r
43581           Found := Ctrl;\r
43582           MinDist := Dist;\r
43583         end;\r
43584       end;\r
43585       if Found = nil then\r
43586       begin\r
43587         case Key of\r
43588           VK_LEFT:\r
43589             begin\r
43590               Key := VK_UP; goto search_tabcontrol;\r
43591             end;\r
43592           VK_RIGHT:\r
43593             begin\r
43594               Key := VK_DOWN; goto search_tabcontrol;\r
43595             end;\r
43596           VK_UP, VK_PRIOR:\r
43597             Tabulate2Next( Form, -1 );\r
43598           VK_DOWN, VK_NEXT:\r
43599             Tabulate2Next( Form, 1 );\r
43600         end;\r
43601       end\r
43602          else\r
43603       begin\r
43604         if Found.fHandle <> 0 then\r
43605         begin\r
43606           Inc( Found.fClickDisabled );\r
43607           SetFocus( Found.fHandle );\r
43608           Dec( Found.fClickDisabled );\r
43609         end;\r
43610         Form.fCurrentControl := Found;\r
43611       end;\r
43612     end;\r
43613     CL.Free;\r
43614   end;\r
43615 end;\r
43616 {$ENDIF ASM_VERSION}\r
43617 //[END Tabulate2ControlEx]\r
43619 {$IFDEF ASM_VERSION}\r
43620 //[function TControl.Tabulate]\r
43621 function TControl.Tabulate: PControl;\r
43622 asm\r
43623         PUSH     EAX\r
43624         CALL     ParentForm\r
43625         TEST     EAX, EAX\r
43626         JZ       @@exit\r
43627         MOV      [EAX].fGotoControl, offset[Tabulate2Control]\r
43628 @@exit: POP      EAX\r
43629 end;\r
43630 {$ELSE ASM_VERSION} //Pascal\r
43631 function TControl.Tabulate: PControl;\r
43632 var F : PControl;\r
43633 begin\r
43634   Result := @Self;\r
43635   F := ParentForm;\r
43636   if F = nil then Exit;\r
43637   F.fGotoControl := Tabulate2Control;\r
43638 end;\r
43639 {$ENDIF ASM_VERSION}\r
43641 {$IFDEF ASM_VERSION}\r
43642 //[function TControl.TabulateEx]\r
43643 function TControl.TabulateEx: PControl;\r
43644 asm\r
43645         PUSH     EAX\r
43646         CALL     ParentForm\r
43647         TEST     EAX, EAX\r
43648         JZ       @@exit\r
43649         MOV      [EAX].fGotoControl, offset[Tabulate2ControlEx]\r
43650 @@exit: POP      EAX\r
43651 end;\r
43652 {$ELSE ASM_VERSION} //Pascal\r
43653 function TControl.TabulateEx: PControl;\r
43654 var F : PControl;\r
43655 begin\r
43656   Result := @Self;\r
43657   F := ParentForm;\r
43658   if F = nil then Exit;\r
43659   F.fGotoControl := Tabulate2ControlEx;\r
43660 end;\r
43661 {$ENDIF ASM_VERSION}\r
43663 //*\r
43664 //[procedure TControl.GotoControl]\r
43665 procedure TControl.GotoControl(Key: DWORD);\r
43666 var Form: PControl;\r
43667 begin\r
43668   Form := ParentForm;\r
43669   if Form <> nil then\r
43670   if assigned( Form.fGotoControl ) then\r
43671      Form.fGotoControl( Form.fCurrentControl, Key, false );\r
43672 end;\r
43674 {$IFDEF ASM_VERSION}\r
43675 //[function TControl.GetCurIndex]\r
43676 function TControl.GetCurIndex: Integer;\r
43677 asm\r
43678         PUSH     EBX\r
43679         XCHG     EBX, EAX\r
43680         MOV      EAX, [EBX].fCurIndex\r
43681         MOVZX    ECX, [EBX].fCommandActions.aGetCurrent\r
43682         JECXZ    @@exit\r
43683         XOR      EAX, EAX\r
43684         CDQ\r
43685         CMP      CX, LVM_GETNEXTITEM\r
43686         JNE      @@0\r
43687         INC      EAX\r
43688         INC      EAX\r
43689         JMP      @@1\r
43690 @@0:\r
43691         CMP      CL, EM_LINEINDEX and $FF\r
43692         JNZ      @@2\r
43693 @@1:\r
43694         DEC      EDX\r
43695 @@2:\r
43696         PUSH     EAX\r
43697         PUSH     EDX\r
43698         PUSH     ECX\r
43699         PUSH     EBX\r
43700         CALL     Perform\r
43702 @@exit: POP      EBX\r
43703 end;\r
43704 {$ELSE ASM_VERSION} //Pascal\r
43705 function TControl.GetCurIndex: Integer;\r
43706 var I, J: Integer;\r
43707 begin\r
43708   Result := fCurIndex;\r
43709   if fCommandActions.aGetCurrent = 0 then\r
43710     Exit;\r
43711   I := 0;\r
43712   if fCommandActions.aGetCurrent = EM_LINEINDEX then\r
43713      Dec( I );\r
43714   J := 0;\r
43715   if fCommandActions.aGetCurrent = LVM_GETNEXTITEM then\r
43716   begin\r
43717      J := 2 {LVNI_SELECTED};\r
43718      Dec( I );\r
43719   end;\r
43720   Result := Perform( fCommandActions.aGetCurrent, I, J );\r
43721 end;\r
43722 {$ENDIF ASM_VERSION}\r
43724 {$IFDEF ASM_VERSION}\r
43725 //[procedure TControl.SetCurIndex]\r
43726 procedure TControl.SetCurIndex(const Value: Integer);\r
43727 asm\r
43728         MOVZX    ECX, [EAX].fCommandActions.aSetCurrent\r
43729         JECXZ    @@set_item_sel\r
43730         PUSHAD\r
43731         PUSH     0\r
43732         PUSH     EDX\r
43733         PUSH     ECX\r
43734         PUSH     EAX\r
43735         CALL     Perform\r
43736         POPAD\r
43737         CMP      CX, TCM_SETCURSEL\r
43738         JNE      @@exit\r
43739         PUSH     TCN_SELCHANGE\r
43740         PUSH     EAX // idfrom doesn't matter\r
43741         PUSH     [EAX].fHandle\r
43742         PUSH     ESP\r
43743         PUSH     0\r
43744         PUSH     WM_NOTIFY\r
43745         PUSH     EAX\r
43746         CALL     Perform\r
43747         POP      ECX\r
43748         POP      ECX\r
43749         POP      ECX\r
43750 @@exit:\r
43751         RET\r
43752 @@set_item_sel:\r
43753         INC      ECX\r
43754         CALL     SetItemSelected\r
43755 end;\r
43756 {$ELSE ASM_VERSION} //Pascal\r
43757 procedure TControl.SetCurIndex(const Value: Integer);\r
43758 var NMHdr: TNMHdr;\r
43759 begin\r
43760   if fCommandActions.aSetCurrent <> 0 then\r
43761   begin\r
43762      Perform( fCommandActions.aSetCurrent, Value, 0 );\r
43763      if fCommandActions.aSetCurrent = TCM_SETCURSEL then\r
43764      begin\r
43765        NMHdr.code := TCN_SELCHANGE;\r
43766        NMHdr.hwndFrom := fHandle;\r
43767        Perform( WM_NOTIFY, 0, Integer( @NMHdr ) );\r
43768      end;\r
43769   end\r
43770   else\r
43771      ItemSelected[ Value ] := True;\r
43772 end;\r
43773 {$ENDIF ASM_VERSION}\r
43775 {$IFDEF ASM_VERSION}\r
43776 //[function TControl.GetTextAlign]\r
43777 function TControl.GetTextAlign: TTextAlign;\r
43778 asm\r
43779         PUSH     EAX\r
43780         CALL     UpdateWndStyles\r
43781         MOV      ECX, [EAX].fStyle\r
43782         MOV      EDX, dword ptr [EAX].fCommandActions.aTextAlignRight\r
43783         XOR      EAX, EAX\r
43784         AND      DX, CX\r
43785         JNZ      @@ret_1\r
43786         SHR      EDX, 16\r
43787         AND      ECX, EDX\r
43788         JNZ      @@ret_2\r
43789         POP      EAX\r
43790         MOVZX    EAX, [EAX].fTextAlign\r
43791         RET\r
43793 @@ret_2:INC      EAX\r
43794 @@ret_1:INC      EAX\r
43795 @@ret_0:POP      ECX\r
43796 end;\r
43797 {$ELSE ASM_VERSION} //Pascal\r
43798 function TControl.GetTextAlign: TTextAlign;\r
43799 begin\r
43800   UpdateWndStyles;\r
43801   if (fStyle and fCommandActions.aTextAlignRight) = fCommandActions.aTextAlignRight then\r
43802      Result := taRight\r
43803   else\r
43804   if (fStyle and fCommandActions.aTextAlignCenter) = fCommandActions.aTextAlignCenter then\r
43805      Result := taCenter\r
43806   else\r
43807      Result := fTextAlign;\r
43808 end;\r
43809 {$ENDIF ASM_VERSION}\r
43811 {$IFDEF ASM_VERSION}\r
43812 //[function TControl.GetVerticalAlign]\r
43813 function TControl.GetVerticalAlign: TVerticalAlign;\r
43814 asm\r
43815         PUSH     EAX\r
43816         CALL     UpdateWndStyles\r
43817         MOV      EDX, dword ptr [EAX].fCommandActions.aVertAlignCenter\r
43818         MOV      ECX, [EAX].fStyle\r
43819         XOR      EAX, EAX\r
43820         MOV      DH, DL\r
43821         AND      DL, CH\r
43822         JZ       @@1\r
43823         CMP      DL, DH\r
43824         JE       @@ret_0\r
43825 @@1:    SHR      EDX, 16\r
43826         MOV      DH, DL\r
43827         AND      DL, CH\r
43828         JZ       @@2\r
43829         CMP      DL, DH\r
43830         JE       @@ret_2\r
43831 @@2:    POP      EAX\r
43832         MOVZX    EAX, [EAX].fVerticalAlign\r
43833         RET\r
43834 @@ret_2:INC      EAX\r
43835 @@ret_1:INC      EAX\r
43836 @@ret_0:POP      ECX\r
43837 end;\r
43838 {$ELSE ASM_VERSION} //Pascal\r
43839 function TControl.GetVerticalAlign: TVerticalAlign;\r
43840 begin\r
43841   UpdateWndStyles;\r
43842   if (fStyle and (fCommandActions.aVertAlignCenter shl 8)) = (fCommandActions.aVertAlignCenter shl 8) then\r
43843      Result := vaCenter\r
43844   else\r
43845   if (fStyle and (fCommandActions.aVertAlignBottom shl 8)) = (fCommandActions.aVertAlignBottom shl 8) then\r
43846      Result := vaBottom\r
43847   else\r
43848      Result := fVerticalAlign;\r
43849 end;\r
43850 {$ENDIF ASM_VERSION}\r
43852 {$IFDEF ASM_VERSION}\r
43853 //[procedure TControl.SetTextAlign]\r
43854 procedure TControl.SetTextAlign(const Value: TTextAlign);\r
43855 asm\r
43856         MOV      [EAX].fTextAlign, DL\r
43857         XOR      ECX, ECX\r
43858         MOV      CX, [EAX].fCommandActions.aTextAlignLeft\r
43859         OR       CX, [EAX].fCommandActions.aTextAlignCenter\r
43860         OR       CX, [EAX].fCommandActions.aTextAlignRight\r
43861         NOT      ECX\r
43862         AND      ECX, [EAX].fStyle\r
43864         AND      EDX, 3\r
43865         OR       CX, [EAX + EDX * 2].fCommandActions.aTextAlignLeft\r
43867         MOV      DL, [EAX].fCommandActions.aTextAlignMask\r
43868         NOT      EDX\r
43869         AND      EDX, ECX\r
43870         CALL     SetStyle\r
43871 end;\r
43872 {$ELSE ASM_VERSION} //Pascal\r
43873 procedure TControl.SetTextAlign(const Value: TTextAlign);\r
43874 var NewStyle: DWORD;\r
43875 begin\r
43876   fTextAlign := Value;\r
43877   NewStyle := 0;\r
43878   with fCommandActions do\r
43879   case Value of\r
43880   taLeft: NewStyle := fStyle and not DWORD(aTextAlignCenter or aTextAlignRight)\r
43881                           or aTextAlignLeft;\r
43882   taRight: NewStyle := fStyle and not DWORD(aTextAlignLeft or aTextAlignCenter)\r
43883                           or aTextAlignRight;\r
43884   taCenter: NewStyle := fStyle and not DWORD(aTextAlignLeft or aTextAlignRight)\r
43885                           or aTextAlignCenter;\r
43886   end;\r
43887   NewStyle := NewStyle and not DWORD(fCommandActions.aTextAlignMask);\r
43888   Style := NewStyle;\r
43889 end;\r
43890 {$ENDIF ASM_VERSION}\r
43892 {$IFDEF ASM_noVERSION}\r
43893 //[procedure TControl.SetVerticalAlign]\r
43894 procedure TControl.SetVerticalAlign(const Value: TVerticalAlign);\r
43895 asm\r
43896         MOV      [EAX].fVerticalAlign, DL\r
43897         XOR      ECX, ECX\r
43898         MOV      CX, word ptr [EAX].fCommandActions.aVertAlignTop\r
43899         OR       CH, CL\r
43900         MOV      CL, 0\r
43901         NOT      ECX\r
43902         AND      ECX, [EAX].fStyle\r
43903         AND      EDX, 3\r
43904         MOV      DH, [EAX + EDX].fCommandActions.aVertAlignCenter\r
43905         MOV      DL, 0\r
43906         OR       EDX, ECX\r
43907         CALL     SetStyle\r
43908 end;\r
43909 {$ELSE ASM_VERSION} //Pascal\r
43910 procedure TControl.SetVerticalAlign(const Value: TVerticalAlign);\r
43911 var NewStyle: DWORD;\r
43912 begin\r
43913   fVerticalAlign := Value;\r
43914   with fCommandActions do\r
43915   begin\r
43916     NewStyle := fStyle and not DWORD((aVertAlignTop or aVertAlignCenter or aVertAlignBottom) shl 8);\r
43917     case Value of\r
43918     vaCenter: NewStyle := NewStyle or (aVertAlignCenter shl 8);\r
43919     vaTop:    NewStyle := NewStyle or (aVertAlignTop shl 8);\r
43920     vaBottom: NewStyle := NewStyle or (aVertAlignBottom shl 8);\r
43921     end;\r
43922   end;\r
43923   Style := NewStyle;\r
43924 end;\r
43925 {$ENDIF ASM_VERSION}\r
43927 {$IFDEF ASM_noVERSION}\r
43928 //[function TControl.Dc2Canvas]\r
43929 function TControl.Dc2Canvas( Sender: PCanvas ): HDC;\r
43930 asm\r
43931         MOV      ECX, [EAX].fPaintDC\r
43932         JECXZ    @@chk_fHandle\r
43933         PUSH     ECX\r
43934         XCHG     EAX, EDX // EAX <= Sender\r
43935         MOV      EDX, ECX // EDX <= fPaintDC\r
43936         PUSH     EAX\r
43937         CALL     TCanvas.SetHandle\r
43938         POP      EAX\r
43939         MOV      [EAX].TCanvas.fIsPaintDC, 1\r
43940         POP      ECX\r
43941 @@ret_ECX:\r
43942         XCHG     EAX, ECX\r
43943         RET\r
43944 @@chk_fHandle:\r
43945         MOV      ECX, [EDX].TCanvas.fHandle\r
43946         INC      ECX\r
43947         LOOP     @@ret_ECX\r
43948         CALL     GetWindowHandle\r
43949         PUSH     EAX\r
43950         CALL     GetDC\r
43951 end;\r
43952 {$ELSE ASM_VERSION} //Pascal\r
43953 function TControl.Dc2Canvas( Sender: PCanvas ): HDC;\r
43954 begin\r
43955   if fPaintDC <> 0 then\r
43956   begin\r
43957      Result := fPaintDC;\r
43958      Sender.SetHandle( Result );\r
43959      Sender.fIsPaintDC := True;\r
43960   end\r
43961     else\r
43962   begin\r
43963     if Sender.fHandle <> 0 then\r
43964        Result := Sender.fHandle\r
43965     else\r
43966        Result := GetDC( GetWindowHandle );\r
43967   end;\r
43968 end;\r
43969 {$ENDIF ASM_VERSION}\r
43971 {$IFDEF ASM_VERSION}\r
43972 //[function TControl.GetCanvas]\r
43973 function TControl.GetCanvas: PCanvas;\r
43974 asm\r
43975         PUSH     EBX\r
43976         PUSH     ESI\r
43977         XCHG     EBX, EAX\r
43979         MOV      ESI, [EBX].fCanvas\r
43980         TEST     ESI, ESI\r
43981         JNZ      @@exit\r
43983         XOR      EAX, EAX\r
43984         CALL     NewCanvas\r
43985         MOV      [EBX].fCanvas, EAX\r
43986         MOV      [EAX].TCanvas.fOwnerControl, EBX\r
43987         MOV      [EAX].TCanvas.fOnGetHandle.TMethod.Code, offset[ DC2Canvas ]\r
43988         MOV      [EAX].TCanvas.fOnGetHandle.TMethod.Data, EBX\r
43989         XCHG     ESI, EAX\r
43991         MOV      ECX, [EBX].fFont\r
43992         JECXZ    @@exit\r
43994         MOV      EAX, [ESI].TCanvas.fFont\r
43995         MOV      EDX, ECX\r
43996         CALL     TGraphicTool.Assign\r
43997         MOV      [ESI].TCanvas.fFont, EAX\r
43999         MOV      ECX, [EBX].fBrush\r
44000         JECXZ    @@exit\r
44002         MOV      EAX, [ESI].TCanvas.fBrush\r
44003         MOV      EDX, ECX\r
44004         CALL     TGraphicTool.Assign\r
44005         MOV      [ESI].TCanvas.fBrush, EAX\r
44007 @@exit: XCHG     EAX, ESI\r
44008         POP      ESI\r
44009         POP      EBX\r
44010 end;\r
44011 {$ELSE ASM_VERSION} //Pascal\r
44012 function TControl.GetCanvas: PCanvas;\r
44013 begin\r
44014   if not assigned( fCanvas ) then\r
44015   begin\r
44016     fCanvas := NewCanvas( 0 );\r
44017     fCanvas.OnGetHandle := Dc2Canvas;\r
44018     fCanvas.fOwnerControl := @Self;\r
44019     if assigned( fFont ) then\r
44020       fCanvas.fFont := fCanvas.fFont.Assign( fFont );\r
44021     if assigned( fBrush ) then\r
44022       fCanvas.fBrush := fCanvas.fBrush.Assign( fBrush );\r
44023   end;\r
44024   Result := fCanvas;\r
44025 end;\r
44026 {$ENDIF ASM_VERSION}\r
44028 //[function TControl.DblBufTopParent]\r
44029 function TControl.DblBufTopParent: PControl;\r
44030 var Ctl: PControl;\r
44031 begin\r
44032   Result := nil;\r
44033   Ctl := @ Self;\r
44034   while Ctl <> nil do\r
44035   begin\r
44036     if Ctl.fDoubleBuffered then\r
44037       Result := Ctl;\r
44038     Ctl := Ctl.fParent;\r
44039   end;\r
44040 end;\r
44042 //[procedure InvalidateDblBufParent]\r
44043 procedure InvalidateDblBufParent( Sender: PControl );\r
44044 var C: PControl;\r
44045 begin\r
44046   C := Sender.DblBufTopParent;\r
44047   if C <> nil then\r
44048     InvalidateRect( C.fHandle, nil, TRUE );\r
44049 end;\r
44051 //[function WndFuncPreventDraw]\r
44052 function WndFuncPreventDraw( W: HWnd; Msg: Cardinal; wParam, lParam: Integer ): Integer; stdcall;\r
44053 var C: PControl;\r
44054     PrntW: HWnd;\r
44055 //********************************************************** Added By M.Gerasimov\r
44056 //*\r
44057     PrevProc:Pointer;\r
44058 //*\r
44059 //********************************************************** Added By M.Gerasimov\r
44060 begin\r
44061   //if not AppletTerminated then\r
44062   case Msg of\r
44063   WM_NCPAINT,\r
44064   //WM_PAINT,\r
44065   WM_ERASEBKGND:\r
44066     begin\r
44067       C := Pointer( GetProp( W, ID_SELF ) );\r
44068       if C = nil then\r
44069       begin\r
44070         PrntW := GetParent( W );\r
44071         if PrntW <> 0 then\r
44072         begin\r
44073           C := Pointer( GetProp( PrntW, ID_SELF ) );\r
44074           if (C <> nil) and not C.fCannotDoubleBuf and\r
44075              (C.DblBufTopParent <> nil) and\r
44076              (not C.DblBufTopParent.fDblBufPainting) then\r
44077           begin\r
44078             case Msg of\r
44079             WM_NCPAINT: Result := 0;\r
44080             WM_PAINT:   Result := 0;\r
44081             else Result := 1;\r
44082             end;\r
44083             Exit;\r
44084           end;\r
44085         end;\r
44086       end;\r
44087     end;\r
44088   end;\r
44089 //********************************************************** By M.Gerasimov\r
44090 //*\r
44091       PrevProc:=Pointer(GetProp( W, ID_PREVPROC ));\r
44092       if PrevProc <> Nil then\r
44093        Result := CallWindowProc( PrevProc , W, Msg, wParam, lParam )\r
44094       else\r
44095        Result:=0;\r
44096 //*\r
44097 //********************************************************** Remarked By M.Gerasimov\r
44098 //Result := CallWindowProc( Pointer( GetProp( W, 'PREV_PROC' ) ),\r
44099 //       W, Msg, wParam, lParam );\r
44100 //******************************************************************************\r
44101 end;\r
44103 //[procedure DblBufCreateWndProc]\r
44104 procedure DblBufCreateWndProc( Sender: PControl );\r
44105 var Chld: HWnd;\r
44106     PrevProc: DWORD;\r
44107 begin\r
44108   Chld := GetWindow( Sender.fHandle, GW_CHILD );\r
44109   while Chld <> 0 do\r
44110   begin\r
44111 //********************************************************** Changed By M.Gerasimov\r
44112 //  if GetProp( Chld, 'PREV_PROC' ) = 0 then\r
44113 //**********************************************************\r
44114     if GetProp( Chld, ID_PREVPROC ) = 0 then              //\r
44115 //**********************************************************\r
44116     begin\r
44117       PrevProc :=\r
44118         SetWindowLong( Chld, GWL_WNDPROC, Longint( @WndFuncPreventDraw ) );\r
44119 //********************************************************** Changed By M.Gerasimov\r
44120 //    SetProp( Chld, 'PREV_PROC', PrevProc );\r
44121 //**********************************************************\r
44122       SetProp( Chld, ID_PREVPROC, PrevProc );             //\r
44123 //**********************************************************\r
44124      end;\r
44125     Chld := GetWindow( Chld, GW_HWNDNEXT );\r
44126   end;\r
44127 end;\r
44129 //[procedure TControl.SetDoubleBuffered]\r
44130 procedure TControl.SetDoubleBuffered(const Value: Boolean);\r
44131 begin\r
44132   if CannotDoubleBuf then Exit;\r
44133   fDoubleBuffered := Value;\r
44134   Global_OnBufferedDraw := WndProcBufferedDraw;\r
44135   Global_Invalidate := @ InvalidateDblBufParent;\r
44136   Global_DblBufCreateWnd := @ DblBufCreateWndProc;\r
44137 end;\r
44139 {$IFDEF ASM_VERSION}\r
44140 //[procedure TControl.SetTransparent]\r
44141 procedure TControl.SetTransparent(const Value: Boolean);\r
44142 asm\r
44143         CMP      [EAX].fTransparent, DL\r
44144         JZ       @@exit\r
44145         MOV      [EAX].fTransparent, DL\r
44146         TEST     DL, DL\r
44147         JZ       @@exit\r
44148         MOV      ECX, [EAX].fParent\r
44149         JECXZ    @@exit\r
44150         XCHG     EAX, ECX\r
44151         CALL     SetDoubleBuffered\r
44152 @@exit:\r
44153 end;\r
44154 {$ELSE ASM_VERSION} //Pascal\r
44155 procedure TControl.SetTransparent(const Value: Boolean);\r
44156 begin\r
44157   if fTransparent = Value then Exit;\r
44158   fTransparent := Value;\r
44159   //ExStyle := ExStyle or WS_EX_TRANSPARENT;\r
44160   if fParent = nil then Exit;\r
44161   if Value then\r
44162     fParent.DoubleBuffered := True;\r
44163 end;\r
44164 {$ENDIF ASM_VERSION}\r
44166 //[function TControl.SetBorder]\r
44167 function TControl.SetBorder( Value: Integer ): PControl;\r
44168 begin\r
44169   fMargin := Value;\r
44170   Result := @ Self;\r
44171 end;\r
44173 { TTrayIcon }\r
44175 var FTrayItems: PList;\r
44177 //[FUNCTION WndProcTray]\r
44178 {$IFDEF ASM_noVERSION}\r
44179 function WndProcTray( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;\r
44180 asm\r
44181         PUSH     ECX\r
44182         MOV      ECX, [EDX].TMsg.message\r
44183         CMP      CX, CM_TRAYICON\r
44184         JNE      @@1\r
44186           MOV      ECX, [EDX].TMsg.lParam\r
44187           MOV      EDX, [EDX].TMsg.wParam\r
44188           MOV      EAX, [EDX].TTrayIcon.fOnMouse.TMethod.Data\r
44189           CMP      word ptr [EDX].TTrayIcon.fOnMouse.TMethod.Code+2, 0\r
44190           JE       @@no_on\r
44192           CALL     [EDX].TTrayIcon.fOnMouse.TMethod.Code\r
44193 @@no_on:\r
44194           POP      ECX\r
44195           XOR      EAX, EAX\r
44196           MOV      [ECX], EAX\r
44197           INC      EAX\r
44198           RET\r
44200 @@1:\r
44201         SUB      ECX, WM_CLOSE\r
44202         JNE      @@exit_0\r
44203 @@2:\r
44205           POP      ECX\r
44206           PUSH     EBX\r
44207           XCHG     EBX, EAX\r
44209           MOV      EAX, [EBX].TControl.fHandle\r
44210           CMP      EAX, [EDX].TMsg.hwnd\r
44211           JNE      @@otherwin\r
44213           MOV      EDX, [FTrayItems]\r
44214           MOV      ECX, [EDX].TList.fCount\r
44215           MOV      EDX, [EDX].TList.fItems\r
44216 @@loop:\r
44217           MOV      EAX, [EDX + ECX*4 - 4]\r
44218           CMP      [EAX].TTray.FNoAutoDeactivate, 0\r
44219           JNZ      @@3\r
44220           CMP      [EAX].TTrayIcon.fControl, EBX\r
44221           JNE      @@3\r
44222           PUSHAD\r
44223           XOR      EDX, EDX\r
44224           CALL     TTrayIcon.SetActive\r
44225           POPAD\r
44226 @@3:      LOOP     @@loop\r
44228 @@otherwin:\r
44229           POP      EBX\r
44230           PUSH     ECX\r
44232 @@exit_0:\r
44233         XOR      EAX, EAX\r
44234         POP      ECX\r
44235 end;\r
44236 {$ELSE ASM_VERSION} //Pascal\r
44237 function WndProcTray( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;\r
44238 var Self_: PTrayIcon;\r
44239     I : Integer;\r
44240 begin\r
44241   Result := False;\r
44242   case Msg.message of\r
44243   CM_TRAYICON:\r
44244     begin\r
44245       Self_ := Pointer( Msg.wParam );\r
44246       if Assigned( Self_.FOnMouse ) then\r
44247          Self_.FOnMouse( @Self_, Msg.lParam );\r
44248       Rslt := 0;\r
44249       Result := True;\r
44250     end;\r
44251   WM_CLOSE:\r
44252     if Msg.hwnd = Control.fHandle then\r
44253     begin\r
44254       if FTrayItems <> nil then // ?????????????????\r
44255       for I := FTrayItems.Count - 1 downto 0 do\r
44256       begin\r
44257         Self_ := FTrayItems.Items[ I ];\r
44258         if not Self_.FNoAutoDeactivate then\r
44259         if Self_.FControl = Control then\r
44260            Self_.Active := False;\r
44261       end;\r
44262     end;\r
44263   end;\r
44264 end;\r
44265 {$ENDIF ASM_VERSION}\r
44266 //[END WndProcTray]\r
44268 //[FUNCTION _NewTrayIcon]\r
44269 {$IFDEF ASM_VERSION}\r
44270 function _NewTrayIcon: PTrayIcon;\r
44271 begin\r
44272   New(Result,Create);\r
44273 end;\r
44274 {$ENDIF ASM_VERSION}\r
44275 //[END _NewTrayIcon]\r
44277 function WndProcTrayIconWnd( Wnd: HWnd; Msg: DWORD; wParam, lParam: Integer ): Integer;\r
44278          stdcall;\r
44279 var PrevProc: function ( Wnd: HWnd; Msg: DWORD;\r
44280                          wParam, lParam: Integer ): Integer; stdcall;\r
44281 var Tr: PTrayIcon;\r
44282 begin\r
44283   PrevProc := Pointer( GetProp( Wnd, 'TRAYSAVEPROC' ) );\r
44284   if Msg = CM_TRAYICON then\r
44285   begin\r
44286     Tr := Pointer( wParam );\r
44287     if Assigned( Tr.FOnMouse ) then\r
44288        Tr.FOnMouse( Tr, lParam );\r
44289     Result := 0;\r
44290     Exit;\r
44291   end\r
44292     else\r
44293   if Msg = WM_CLOSE then\r
44294   begin\r
44295     if Assigned( PrevProc ) then\r
44296     begin\r
44297       SetWindowLong( Wnd, GWL_WNDPROC, Integer( @ PrevProc ) );\r
44298       RemoveProp( Wnd, 'TRAYSAVEPROC' );\r
44299       PostMessage( Wnd, WM_CLOSE, wParam, lParam );\r
44300       Result := 0;\r
44301       Exit;\r
44302       //Wnd := 0;\r
44303     end;\r
44304   end;\r
44305   if (Wnd <> 0) and IsWindow( Wnd ) and Assigned( PrevProc ) then\r
44306     Result := PrevProc( Wnd, Msg, wParam, lParam )\r
44307   else\r
44308     Result := DefWindowProc( Wnd, Msg, wParam, lParam );\r
44309 end;\r
44311 //[PROCEDURE TTrayIcon.AttachProc2Wnd]\r
44312 procedure TTrayIcon.AttachProc2Wnd;\r
44313 begin\r
44314   if FWnd = 0 then Exit;\r
44315   if GetProp( FWnd, 'TRAYSAVEPROC' ) <> 0 then Exit; // already attached\r
44316   SetProp( FWnd, 'TRAYSAVEPROC', GetWindowLong( FWnd, GWL_WNDPROC ) );\r
44317   SetWindowLong( FWnd, GWL_WNDPROC, Integer( @ WndProcTrayIconWnd ) );\r
44318 end;\r
44319 // [END TTrayIcon.AttachProc2Wnd]\r
44321 // [PROCEDURE TTrayIcon.DetachProc2Wnd]\r
44322 procedure TTrayIcon.DetachProc2Wnd;\r
44323 var OldProc: function ( Wnd: HWnd; Msg: DWORD;\r
44324              wParam, lParam: Integer ): Integer; stdcall;\r
44325 begin\r
44326   if FWnd = 0 then Exit;\r
44327   OldProc := Pointer( GetProp( FWnd, 'TRAYSAVEPROC' ) );\r
44328   if not Assigned( OldProc ) then Exit; // not attached\r
44329   SetWindowLong( FWnd, GWL_WNDPROC, Integer( @ OldProc ) );\r
44330   RemoveProp( FWnd, 'TRAYSAVEPROC' );\r
44331 end;\r
44332 // [END TTrayIcon.DetachProc2Wnd]\r
44334 //[FUNCTION NewTrayIcon]\r
44335 {$IFDEF ASM_VERSION}\r
44336 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;\r
44337 asm\r
44338         PUSH     EBX\r
44339         PUSH     EDX // push Icon\r
44340         PUSH     EAX // push Wnd\r
44341         CALL     _NewTrayIcon\r
44342         XCHG     EBX, EAX\r
44344         MOV      EAX, [FTrayItems]\r
44345         TEST     EAX, EAX\r
44346         JNZ      @@1\r
44347         CALL     NewList\r
44348         MOV      [FTrayItems], EAX\r
44349 @@1:\r
44350         MOV      EDX, EBX\r
44351         CALL     TList.Add\r
44353         POP      EAX //Wnd\r
44354         MOV      [EBX].TTrayIcon.fControl, EAX\r
44355         POP      [EBX].TTrayIcon.fIcon //Icon\r
44357         MOV      EDX, offset[WndProcTray]\r
44358         TEST     EAX, EAX\r
44359         JZ       @@2\r
44360         CALL     TControl.AttachProc\r
44361 @@2:\r
44362         MOV      DL, 1\r
44363         MOV      EAX, EBX\r
44364         CALL     TTrayIcon.SetActive\r
44365         XCHG     EAX, EBX\r
44366         POP      EBX\r
44367 end;\r
44368 {$ELSE ASM_VERSION} //Pascal\r
44369 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;\r
44370 begin\r
44371   if FTrayItems = nil then\r
44372      FTrayItems := NewList;\r
44373   {-}\r
44374   New( Result, Create );\r
44375   {+}{++}(*Result := PTrayIcon.Create;*){--}\r
44376   FTrayItems.Add( Result );\r
44377   if Wnd <> nil then\r
44378     Wnd.AttachProc( WndProcTray );\r
44379   Result.FControl := Wnd;\r
44380   Result.FIcon := Icon;\r
44381   Result.Active := True;\r
44382 end;\r
44383 {$ENDIF ASM_VERSION}\r
44384 //[END NewTrayIcon]\r
44386 var fRecreateMsg: DWORD;\r
44388 //[FUNCTION WndProcRecreateTrayIcons]\r
44389 {$IFDEF ASM_VERSION}\r
44390 function WndProcRecreateTrayIcons( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
44391 asm     //cmd    //opd\r
44392         MOV      ECX, [fRecreateMsg]\r
44393         CMP      word ptr [EDX].TMsg.message, CX\r
44394         JNE      @@ret_false\r
44395         PUSH     ESI\r
44396         MOV      ESI, [FTrayItems]\r
44397         MOV      ECX, [ESI].TList.fCount\r
44398         MOV      ESI, [ESI].TList.fItems\r
44399         //JECXZ    @@e_loo\r
44400 @@loo:  PUSH     ECX\r
44401         LODSD\r
44402         MOV      DL, [EAX].TTrayIcon.fAutoRecreate\r
44403         AND      DL, [EAX].TTrayIcon.fActive\r
44404         JZ       @@nx\r
44405         DEC      [EAX].TTrayIcon.fActive\r
44406         CALL     TTrayIcon.SetActive\r
44407 @@nx:   POP      ECX\r
44408         LOOP     @@loo\r
44409 @@e_loo:POP      ESI\r
44410 @@ret_false:\r
44411         XOR      EAX, EAX\r
44412 end;\r
44413 {$ELSE ASM_VERSION} //Pascal\r
44414 function WndProcRecreateTrayIcons( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
44415 var I: Integer;\r
44416     TI: PTrayIcon;\r
44417 begin\r
44418   if Msg.message = fRecreateMsg then\r
44419   begin\r
44420     for I := 0 to FTrayItems.fCount - 1 do\r
44421     begin\r
44422       TI := FTrayItems.Items[ I ];\r
44423       if TI.fAutoRecreate then\r
44424       if TI.fActive then\r
44425       begin\r
44426         TI.fActive := False;\r
44427         TI.Active := True;\r
44428       end;\r
44429     end;\r
44430   end;\r
44431   Result := False;\r
44432 end;\r
44433 {$ENDIF ASM_VERSION}\r
44434 //[END WndProcRecreateTrayIcons]\r
44436 const\r
44437   TaskbarCreatedMsg: array[ 0..14 ] of Char = ('T','a','s','k','b','a','r',\r
44438                      'C','r','e','a','t','e','d',#0);\r
44439 {$IFDEF ASM_VERSION}\r
44440 //[procedure TTrayIcon.SetAutoRecreate]\r
44441 procedure TTrayIcon.SetAutoRecreate(const Value: Boolean);\r
44442 asm     //cmd    //opd\r
44443         MOV      [EAX].fAutoRecreate, DL\r
44444         MOV      EAX, [EAX].FControl\r
44445         CALL     TControl.ParentForm\r
44446         MOV      EDX, offset[WndProcRecreateTrayIcons]\r
44447         CALL     TControl.AttachProc\r
44448         PUSH     offset[TaskbarCreatedMsg]\r
44449         CALL     RegisterWindowMessage\r
44450         MOV      [fRecreateMsg], EAX\r
44451 end;\r
44452 {$ELSE ASM_VERSION} //Pascal\r
44453 procedure TTrayIcon.SetAutoRecreate(const Value: Boolean);\r
44454 begin\r
44455   fAutoRecreate := Value;\r
44456   FControl.ParentForm.AttachProc( WndProcRecreateTrayIcons );\r
44457   fRecreateMsg := RegisterWindowMessage( TaskbarCreatedMsg );\r
44458 end;\r
44459 {$ENDIF ASM_VERSION}\r
44461 {$IFDEF ASM_VERSION}\r
44462 //[destructor TTrayIcon.Destroy]\r
44463 destructor TTrayIcon.Destroy;\r
44464 asm\r
44465         PUSH     EBX\r
44466         PUSH     ESI\r
44467         MOV      EBX, EAX\r
44468         XOR      EDX, EDX\r
44469         CALL     SetActive\r
44471         MOV      ECX, [EBX].fIcon\r
44472         JECXZ    @@icon_destroyed\r
44473         PUSH     ECX\r
44474         CALL     DestroyIcon\r
44475 @@icon_destroyed:\r
44477         MOV      EDX, EBX\r
44478         MOV      ESI, [FTrayItems]\r
44479         MOV      EAX, ESI\r
44480         CALL     TList.IndexOf\r
44481         TEST     EAX, EAX\r
44482         JL       @@fin\r
44483           XCHG     EDX, EAX\r
44484           MOV      EAX, ESI\r
44485           CALL     TList.Delete\r
44486           MOV      EAX, [ESI].TList.fCount\r
44487           TEST     EAX, EAX\r
44488           JNZ      @@fin\r
44489           XCHG     EAX, [FTrayItems]\r
44490           CALL     TObj.Free\r
44491 @@fin:  LEA      EAX, [EBX].FTooltip\r
44492         CALL     System.@LStrClr\r
44493         XCHG     EAX, EBX\r
44494         CALL     TObj.Destroy\r
44495         POP      ESI\r
44496         POP      EBX\r
44497 end;\r
44498 {$ELSE ASM_VERSION} //Pascal\r
44499 destructor TTrayIcon.Destroy;\r
44500 begin\r
44501   Active := False;\r
44503   if fIcon <> 0 then\r
44504     DestroyIcon( fIcon );\r
44506   FTrayItems.Remove( @ Self );\r
44507   if FTrayItems.Count = 0 then\r
44508     Free_And_Nil( FTrayItems );\r
44509   FTooltip := '';\r
44510   inherited;\r
44511 end;\r
44512 {$ENDIF ASM_VERSION}\r
44514 {$IFDEF ASM_VERSION}\r
44515 //[procedure TTrayIcon.SetActive]\r
44516 procedure TTrayIcon.SetActive(const Value: Boolean);\r
44517 asm\r
44518         CMP      [EAX].fActive, DL\r
44519         JE       @@exit\r
44520         MOV      ECX, [EAX].fIcon\r
44521         JECXZ    @@exit\r
44522         PUSH     EDX\r
44523         PUSH     EAX\r
44524           MOV      ECX, [EAX].FWnd\r
44525           INC      ECX\r
44526           LOOP     @@1\r
44527           MOV      ECX, [EAX].fControl\r
44528           XOR      EAX, EAX\r
44529           JECXZ    @@1\r
44530           XCHG     EAX, ECX\r
44531           CALL     TControl.GetWindowHandle\r
44532 @@1:\r
44533         POP      ECX\r
44534         POP      EDX\r
44535         XCHG     EAX, ECX\r
44536         JECXZ    @@exit\r
44537         MOV      [EAX].fActive, DL\r
44538         MOVZX    EDX, DL\r
44539         XOR      DL, 1\r
44540         ADD      EDX, EDX\r
44541         CALL     SetTrayIcon\r
44542 @@exit:\r
44543 end;\r
44544 {$ELSE ASM_VERSION} //Pascal\r
44545 procedure TTrayIcon.SetActive(const Value: Boolean);\r
44546 begin\r
44547   if FActive = Value then Exit;\r
44548   if FIcon = 0 then Exit;\r
44549   if (Wnd = 0) and ((FControl = nil) or (FControl.GetWindowHandle = 0)) then Exit;\r
44550   FActive := Value;\r
44551   if Value then\r
44552      SetTrayIcon( NIM_ADD )\r
44553   else\r
44554      SetTrayIcon( NIM_DELETE );\r
44555 end;\r
44556 {$ENDIF ASM_VERSION}\r
44558 {$IFDEF ASM_VERSION}\r
44559 //[procedure TTrayIcon.SetIcon]\r
44560 procedure TTrayIcon.SetIcon(const Value: HIcon);\r
44561 asm\r
44562         MOV      ECX, [EAX].fIcon\r
44563         CMP      ECX, EDX\r
44564         JE       @@exit\r
44565         MOV      [EAX].fIcon, EDX\r
44566         XOR      EDX, EDX\r
44567         JECXZ    @@nim_add\r
44568         INC      EDX      // NIM_MODIFY = 1\r
44569 @@nim_add:\r
44570         MOVZX    ECX, [EAX].fActive\r
44571         JECXZ    @@exit\r
44572         CALL     SetTrayIcon\r
44573 @@exit:\r
44574 end;\r
44575 {$ELSE ASM_VERSION} //Pascal\r
44576 procedure TTrayIcon.SetIcon(const Value: HIcon);\r
44577 var Cmd : DWORD;\r
44578 begin\r
44579   if FIcon = Value then Exit;\r
44580   // Previous icon is not destroying. This is normal for\r
44581   // icons, loaded from resources using LoadIcon. For icons,\r
44582   // created using CreateIconIndirect, You have to call\r
44583   // DestroyIcon manually.\r
44584   Cmd := NIM_MODIFY;\r
44585   if FIcon = 0 then\r
44586      Cmd := NIM_ADD;\r
44587   FIcon := Value;\r
44588   if FActive then\r
44589      SetTrayIcon( Cmd );\r
44590 end;\r
44591 {$ENDIF ASM_VERSION}\r
44593 {$IFDEF ASM_VERSION}\r
44594 //[procedure TTrayIcon.SetTooltip]\r
44595 procedure TTrayIcon.SetTooltip(const Value: String);\r
44596 asm\r
44597         PUSH     EBX\r
44598         XCHG     EBX, EAX\r
44599         MOV      EAX, [EBX].fTooltip\r
44600         PUSH     EDX\r
44601         CALL     System.@LStrCmp\r
44602         POP      EDX\r
44603         JE       @@exit\r
44604         LEA      EAX, [EBX].fTooltip\r
44605         CALL     System.@LStrAsg\r
44606         CMP      [EBX].fActive, 0\r
44607         JE       @@exit\r
44608         XOR      EDX, EDX\r
44609         INC      EDX     // EDX = NIM_MODIFY\r
44610         XCHG     EAX, EBX\r
44611         CALL     SetTrayIcon\r
44612 @@exit:\r
44613         POP      EBX\r
44614 end;\r
44615 {$ELSE ASM_VERSION} //Pascal\r
44616 procedure TTrayIcon.SetTooltip(const Value: String);\r
44617 begin\r
44618   if FTooltip = Value then Exit;\r
44619   FTooltip := Value;\r
44620   if Active then\r
44621      SetTrayIcon( NIM_MODIFY );\r
44622 end;\r
44623 {$ENDIF ASM_VERSION}\r
44625 {$IFDEF ASM_VERSION}\r
44626 //[procedure TTrayIcon.SetTrayIcon]\r
44627 procedure TTrayIcon.SetTrayIcon(const Value: DWORD);\r
44628 const sz_tid = sizeof( TNotifyIconData );\r
44629 asm\r
44630         //MOV      ECX, [EAX].fIcon\r
44631         //JECXZ    @@exit\r
44633         CMP      [AppletTerminated], 0\r
44634         JE       @@1\r
44635         MOV      DL, NIM_DELETE\r
44636 @@1:\r
44637         PUSH     EBX\r
44638         PUSH     ESI\r
44639         MOV      ESI, EAX\r
44640         MOV      EBX, EDX\r
44642         XOR      ECX, ECX\r
44643         PUSH     ECX\r
44644         ADD      ESP, -60\r
44645         MOV      EDX, [ESI].fToolTip\r
44646         CALL     EDX2PChar\r
44647         MOV      EAX, ESP\r
44648         MOV      CL, 63\r
44649         CALL     StrLCopy\r
44651         PUSH     [ESI].fIcon\r
44652         PUSH     CM_TRAYICON\r
44653         XOR      EDX, EDX\r
44654         CMP      BL, NIM_DELETE\r
44655         JE       @@2\r
44656         MOV      DL, NIF_ICON or NIF_MESSAGE or NIF_TIP\r
44657 @@2:    PUSH     EDX\r
44658         PUSH     ESI\r
44659         MOV      EAX, [ESI].FWnd\r
44660         TEST     EAX, EAX\r
44661         JNZ      @@3\r
44662         MOV      EAX, [ESI].fControl\r
44663         MOV      EAX, [EAX].TControl.fHandle\r
44664 @@3:\r
44665         PUSH     EAX\r
44666         PUSH     sz_tid\r
44668         PUSH     ESP\r
44669         PUSH     EBX\r
44670         CALL     Shell_NotifyIcon\r
44672         ADD      ESP, sz_tid\r
44673         POP      ESI\r
44674         POP      EBX\r
44675 @@exit:\r
44676 end;\r
44677 {$ELSE ASM_VERSION} //Pascal\r
44678 procedure TTrayIcon.SetTrayIcon(const Value: DWORD);\r
44679 var NID : TNotifyIconData;\r
44680     L : Integer;\r
44681     V : DWORD;\r
44682 begin\r
44683   //if FIcon = 0 then Exit; - already tested\r
44684   V := Value;\r
44685   if AppletTerminated then\r
44686     V := NIM_DELETE;\r
44687   if Wnd <> 0 then\r
44688     NID.Wnd := Wnd\r
44689   else\r
44690     NID.Wnd := FControl.fHandle;\r
44692   NID.cbSize := Sizeof( NID );\r
44693   NID.uID := DWORD( @Self );\r
44694   NID.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;\r
44695   if V = NIM_DELETE then\r
44696      NID.uFlags := 0;\r
44697   NID.uCallbackMessage := CM_TRAYICON;\r
44698   NID.hIcon := FIcon;\r
44699   L := Length( FToolTip );\r
44700   if L > 63 then L := 63;\r
44701   Move( FTooltip[1], NID.szTip[0], Min( 63, L ) );\r
44702   NID.szTip[ L ] := #0;\r
44704   Shell_NotifyIcon( V, @NID );\r
44705 end;\r
44706 {$ENDIF ASM_VERSION}\r
44708 { -- JustOne -- }\r
44710 var JustOneMutex: THandle;\r
44712 //[FUNCTION WndProcJustOne]\r
44713 {$IFDEF ASM_VERSION}\r
44714 function WndProcJustOne( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;\r
44715 asm\r
44716         MOV      ECX, [EDX].TMsg.message\r
44717         SUB      ECX, WM_CLOSE\r
44718         JE       @@1\r
44719         SUB      ECX, WM_NCDESTROY - WM_CLOSE\r
44720         JNE      @@exit\r
44721 @@1:\r
44722         XCHG     ECX, [JustOneMutex]\r
44723         JECXZ    @@exit\r
44724         PUSH     ECX\r
44725         PUSH     ECX\r
44726         CALL     ReleaseMutex\r
44727         CALL     CloseHandle\r
44729 @@exit:\r
44730         XOR      EAX, EAX\r
44731 end;\r
44732 {$ELSE ASM_VERSION} //Pascal\r
44733 function WndProcJustOne( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;\r
44734 begin\r
44735   Result := False;\r
44736   case Msg.message of\r
44737   WM_CLOSE, WM_NCDESTROY:\r
44738       if LongBool( JustOneMutex ) then\r
44739       begin\r
44740         ReleaseMutex( JustOneMutex );\r
44741         CloseHandle( JustOneMutex );\r
44742         JustOneMutex := 0;\r
44743       end;\r
44744   end;\r
44745 end;\r
44746 {$ENDIF ASM_VERSION}\r
44747 //[END WndProcJustOne]\r
44749 //[FUNCTION JustOne]\r
44750 {$IFDEF ASM_VERSION}\r
44751 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;\r
44752 const JOcs: PChar = 'KOL.Just1.CrtSec';\r
44753 asm\r
44754         PUSH     EBX\r
44755         PUSH     ESI\r
44756         XOR      ESI, ESI\r
44757         PUSH     EDI\r
44758         XCHG     EBX, EAX\r
44760         CALL     EDX2PChar\r
44761         PUSH     EDX\r
44763         PUSH     [JOcs]\r
44764         PUSH     1\r
44765         PUSH     ESI\r
44766         MOV      EDI, offset[CreateMutex]\r
44767         CALL     EDI\r
44769         POP      EDX\r
44770         TEST     EAX, EAX\r
44771         JZ       @@exit     //\r
44772         PUSH     EAX\r
44773         PUSH     EAX\r
44775         PUSH     EDX\r
44776         PUSH     ESI\r
44777         PUSH     ESI\r
44778         CALL     EDI\r
44779         MOV      [JustOneMutex], EAX\r
44780         TEST     EAX, EAX\r
44781         JE       @@1        //\r
44783         PUSH     ESI\r
44784         PUSH     EAX\r
44785         CALL     WaitForSingleObject\r
44786         SUB      EAX, WAIT_TIMEOUT\r
44787         JE       @@1\r
44789         INC      ESI\r
44790 @@1:\r
44791         //MOV      [EBX].TControl.fWndProcJustOne, offset[WndProcJustOne]\r
44792         XCHG     EAX, EBX\r
44793         MOV      EDX, offset[WndProcJustOne]\r
44794         CALL     TControl.AttachProc\r
44796         CALL     ReleaseMutex\r
44797         CALL     CloseHandle\r
44799 @@exit:\r
44800         XCHG     EAX, ESI\r
44801         POP      EDI\r
44802         POP      ESI\r
44803         POP      EBX\r
44804 end;\r
44805 {$ELSE ASM_VERSION} //Pascal\r
44806 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;\r
44807 var CritSecMutex : THandle;\r
44808     DW : Longint;\r
44809 begin\r
44810    Result := False;\r
44811    CritSecMutex := CreateMutex( nil, True, PChar( 'KOL.Just1.CrtSec' ) );\r
44812    if CritSecMutex = 0 then Exit;\r
44814    JustOneMutex := CreateMutex( nil, False, PChar( Identifier ) );\r
44815    if JustOneMutex <> 0 then\r
44816    begin\r
44817      DW := WaitForSingleObject( JustOneMutex, 0 );\r
44818      Result := (DW <> WAIT_TIMEOUT);\r
44819    end;\r
44821    //Wnd.fWndProcJustOne := WndProcJustOne;\r
44822    Wnd.AttachProc( WndProcJustOne );\r
44824    ReleaseMutex( CritSecMutex );\r
44825    CloseHandle( CritSecMutex );\r
44826 end;\r
44827 {$ENDIF ASM_VERSION}\r
44828 //[END JustOne]\r
44830 { JustOneNotify }\r
44832 var\r
44833   OnAnotherInstance: TOnAnotherInstance;\r
44834   JustOneMsg: DWORD;\r
44836 //[FUNCTION WndProcJustOneNotify]\r
44837 {$IFDEF ASM_VERSION}\r
44838 function WndProcJustOneNotify( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;\r
44839 asm\r
44840         PUSH     EBP\r
44841         MOV      EBP, ESP\r
44842         PUSHAD\r
44843         CALL     WndProcJustOne\r
44844         POPAD\r
44845         XOR      EAX, EAX\r
44846         PUSH     ECX\r
44847           MOV      ECX, [EDX].TMsg.message\r
44848           SUB      ECX, [JustOneMsg]\r
44849         POP      ECX\r
44850         JNE      @@exit\r
44851         MOV      [ECX], EAX\r
44852         CMP      [OnAnotherInstance].TMethod.Code, EAX\r
44853         JE       @@exit_1\r
44855         //MOV      EAX, (MAX_PATH + 3) and 0FFFFCh\r
44856         MOV      AH, 2\r
44857         SUB      ESP, EAX\r
44859         MOV      ECX, ESP\r
44860         PUSH     EAX\r
44861         PUSH     ECX\r
44862         PUSH     [EDX].TMsg.lParam\r
44863         CALL     GetWindowText\r
44865         MOV      EDX, ESP\r
44866         PUSH     0\r
44867         MOV      EAX, ESP\r
44868         CALL     System.@LStrFromPChar\r
44870         MOV      EDX, [ESP]\r
44871         MOV      EAX, [OnAnotherInstance].TMethod.Data\r
44872         CALL     [OnAnotherInstance].TMethod.Code\r
44874         MOV      EAX, ESP\r
44875         CALL     System.@LStrClr\r
44876 @@exit_1:\r
44877         MOV      AL, 1\r
44878 @@exit:\r
44879         MOV      ESP, EBP\r
44880         POP      EBP\r
44881 end;\r
44882 {$ELSE ASM_VERSION} //Pascal\r
44883 function WndProcJustOneNotify( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;\r
44884 var Buf : array[0..MAX_PATH] of Char;\r
44885 begin\r
44886   WndProcJustOne( Control, Msg, Rslt );\r
44887   Result := False;\r
44888   if Msg.message = JustOneMsg then\r
44889   begin\r
44890     Result := True;\r
44891     if assigned( OnAnotherInstance ) then\r
44892     begin\r
44893       GetWindowText( Msg.lParam, Buf, MAX_PATH );\r
44894       OnAnotherInstance( Buf );\r
44895     end;\r
44896     Rslt := 0;\r
44897   end;\r
44898 end;\r
44899 {$ENDIF ASM_VERSION}\r
44900 //[END WndProcJustOneNotify]\r
44902 // Redefine here incorrectly declared BroadcastSystemMessage API function.\r
44903 // It should not refer to BroadcastSystemMessageA, which is not present in\r
44904 // earlier versions of Windows95, but to BroadcastSystemMessage, which is\r
44905 // present in all Windows95/98/Me and NT/2K/XP.\r
44906 //[API BroadcastSystemMessage]\r
44907 function BroadcastSystemMessage(Flags: DWORD; Recipients: PDWORD;\r
44908   uiMessage: UINT; wParam: WPARAM; lParam: LPARAM): Longint; stdcall;\r
44909 external user32 name 'BroadcastSystemMessage';\r
44911 //[FUNCTION JustOneNotify]\r
44912 {$IFDEF ASM_VERSION}\r
44913 function JustOneNotify( Wnd: PControl; const Identifier : String;\r
44914                         const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;\r
44915 asm\r
44916         PUSHAD\r
44917         MOV      EBP, ESP\r
44919         XCHG     EAX, EDX\r
44920         PUSH     EAX\r
44921         CALL     System.@LStrLen\r
44922         POP      EDX\r
44923         ADD      EAX, EAX\r
44924         SUB      ESP, EAX\r
44925         MOV      EAX, ESP\r
44926         CALL     StrPCopy\r
44927         PUSH     '.ega'\r
44928         PUSH     'sseM'\r
44929         PUSH     ESP\r
44930         CALL     RegisterWindowMessage\r
44931         MOV      [JustOneMsg], EAX\r
44932         TEST     EAX, EAX\r
44934         MOV      ESP, EBP\r
44935         POPAD\r
44936         JE       @@exit_f\r
44938         PUSHAD\r
44939         CALL     JustOne\r
44940         DEC      AL\r
44941         POPAD\r
44942         JZ       @@exit_t\r
44944         PUSH     EBX\r
44945         XCHG     EBX, EAX\r
44946         XOR      EDX, EDX\r
44947         XCHG     [EBX].TControl.fCaption, EDX\r
44948         PUSH     EDX\r
44950         CALL     GetCommandLine\r
44951         XCHG     EDX, EAX\r
44952         MOV      EAX, EBX\r
44953         CALL     TControl.SetCaption\r
44954         MOV      EAX, EBX\r
44955         CALL     TControl.GetWindowHandle\r
44956         TEST     EAX, EAX\r
44957         JZ       @@rest_cap\r
44959         PUSH     BSM_APPLICATIONS\r
44960         MOV      EDX, ESP\r
44962         PUSH     EAX\r
44963         PUSH     0\r
44964         PUSH     [JustOneMsg]\r
44965         PUSH     EDX\r
44966         PUSH     BSF_QUERY or BSF_IGNORECURRENTTASK\r
44967         CALL     BroadcastSystemMessage\r
44969         POP      EDX\r
44970 @@rest_cap:\r
44971         XOR      EDX, EDX\r
44972         MOV      EAX, EBX\r
44973         CALL     TControl.SetCaption\r
44974         POP      EDX\r
44975         MOV      [EBX].TControl.fCaption, EDX\r
44976         PUSH     EDX\r
44977         PUSH     [EBX].TControl.fHandle\r
44978         CALL     SetWindowText\r
44979         POP      EBX\r
44980 @@exit_f:\r
44981         XOR      EAX, EAX\r
44982           POP      EBP  // because compiler inserts PUSH EBP;MOV EBP,ESP at the BEGIN\r
44983         RET\r
44985 @@exit_t:\r
44986         PUSHAD\r
44987         LEA      ESI, [aOnAnotherInstance]\r
44988         LEA      EDI, [OnAnotherInstance]\r
44989         MOVSD\r
44990         MOVSD\r
44991         //MOV      [EAX].TControl.fWndProcJustOne, offset[WndProcJustOneNotify]\r
44992         MOV      EDX, offset[WndProcJustOneNotify]\r
44993         CALL     TControl.AttachProc\r
44995         POPAD\r
44996         MOV      AL, 1\r
44997 end;\r
44998 {$ELSE ASM_VERSION} //Pascal\r
44999 function JustOneNotify( Wnd: PControl; const Identifier : String;\r
45000                         const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;\r
45001 var Recipients : DWord;\r
45002     OldCap: String;\r
45003 begin\r
45004    Result := False;\r
45005    JustOneMsg := RegisterWindowMessage( PChar( 'Message.' + Identifier ) );\r
45006    if JustOneMsg = 0 then Exit;\r
45008    Result := JustOne( Wnd, Identifier );\r
45009    if not Result then\r
45010    begin\r
45011       // Send a message to the first instance of applet\r
45013       //Wnd.CreateVisible := False;\r
45014       OldCap := Wnd.Caption;\r
45015       Wnd.Caption := GetCommandLine;\r
45016       if Wnd.GetWindowHandle <> 0 then\r
45017       begin\r
45018          Recipients := BSM_APPLICATIONS;\r
45019          BroadcastSystemMessage( BSF_QUERY or BSF_IGNORECURRENTTASK, @Recipients,\r
45020                                  JustOneMsg, 0, Wnd.fHandle );\r
45021       end;\r
45022       Wnd.Caption := OldCap;\r
45023    end\r
45024       else\r
45025    begin\r
45026       // Store event handler to notify this instance about another\r
45027       // instance staring:\r
45028       OnAnotherInstance := aOnAnotherInstance;\r
45029       //Wnd.fWndProcJustOne := WndProcJustOneNotify;\r
45030       Wnd.AttachProc( WndProcJustOneNotify );\r
45032       {\r
45033       if JustOneNotifier = nil then\r
45034          JustOneNotifier := ZJustOneNotifier.Create;\r
45035       }\r
45036    end;\r
45037 end;\r
45038 {$ENDIF ASM_VERSION}\r
45039 //[END JustOneNotify]\r
45042 ///////////////////////////////////////// STRING LIST OBJECT /////////////////\r
45044 { TStrList }\r
45046 //[function NewStrList]\r
45047 function NewStrList: PStrList;\r
45048 begin\r
45049   {-}\r
45050   New( Result, Create );\r
45051   {+}\r
45052   {++}(*\r
45053   Result := PStrList.Create;\r
45054   *){--}\r
45055 end;\r
45056 //[END NewStrList]\r
45058 {$IFDEF ASM_VERSION}\r
45059 //[destructor TStrList.Destroy]\r
45060 destructor TStrList.Destroy;\r
45061 asm\r
45062         PUSH     EAX\r
45063         CALL     Clear\r
45064         POP      EAX\r
45065         CALL     TObj.Destroy\r
45066 end;\r
45067 {$ELSE ASM_VERSION} //Pascal\r
45068 destructor TStrList.Destroy;\r
45069 begin\r
45070   Clear;\r
45071   inherited;\r
45072 end;\r
45073 {$ENDIF ASM_VERSION}\r
45075 //[procedure TStrList.Init]\r
45076 procedure TStrList.Init;\r
45077 begin\r
45078   //inherited;\r
45079   fNameDelim := DefaultNameDelimiter;\r
45080 end;\r
45082 {$IFDEF ASM_VERSION}\r
45083 //[function TStrList.Add]\r
45084 function TStrList.Add(const S: string): integer;\r
45085 asm\r
45086         MOV      ECX, EDX\r
45087         MOV      EDX, [EAX].fCount\r
45088         PUSH     EDX\r
45089         CALL     Insert\r
45090         POP      EAX\r
45091 end;\r
45092 {$ELSE ASM_VERSION} //Pascal\r
45093 function TStrList.Add(const S: string): integer;\r
45094 begin\r
45095   Result := fCount;\r
45096   Insert( Result, S );\r
45097 end;\r
45098 {$ENDIF ASM_VERSION}\r
45100 {$IFDEF ASM_VERSION}\r
45101 //[procedure TStrList.AddStrings]\r
45102 procedure TStrList.AddStrings(Strings: PStrList);\r
45103 asm\r
45104         PUSH     EAX\r
45105         XCHG     EAX, EDX\r
45106         PUSH     0\r
45107         MOV      EDX, ESP\r
45108         CALL     GetTextStr\r
45109         POP      EDX\r
45110         POP      EAX\r
45111         MOV      CL, 1\r
45112         PUSH     EDX\r
45113         CALL     SetText\r
45114         CALL     RemoveStr\r
45115 end;\r
45116 {$ELSE ASM_VERSION} //Pascal\r
45117 procedure TStrList.AddStrings(Strings: PStrList);\r
45118 begin\r
45119   SetText( Strings.Text, True );\r
45120 end;\r
45121 {$ENDIF ASM_VERSION}\r
45123 {$IFDEF ASM_VERSION}\r
45124 //[function TStrList.AppendToFile]\r
45125 function TStrList.AppendToFile(const FileName: string): Boolean;\r
45126 asm\r
45127         PUSH     EBX\r
45128         MOV      EBX, EDX\r
45129         PUSH     0\r
45130         MOV      EDX, ESP\r
45131         CALL     GetTextStr\r
45132         XCHG     EAX, EBX\r
45133         MOV      EDX, ofOpenWrite or ofOpenAlways\r
45134         CALL     FileCreate\r
45135         MOV      EBX, EAX\r
45136         INC      EAX\r
45137         JZ       @@exit\r
45138         DEC      EAX\r
45139         XOR      EDX, EDX\r
45140         XOR      ECX, ECX\r
45141         MOV      CL, spEnd\r
45142         CALL     FileSeek\r
45143         POP      EAX\r
45144         PUSH     EAX\r
45145         CALL     System.@LStrLen\r
45146         XCHG     ECX, EAX\r
45147         MOV      EAX, EBX\r
45148         POP      EDX\r
45149         PUSH     EDX\r
45150         CALL     FileWrite\r
45151         XCHG     EAX, EBX\r
45152         CALL     FileClose\r
45153 @@exit:\r
45154         CALL     RemoveStr\r
45155         POP      EBX\r
45156 end;\r
45157 {$ELSE ASM_VERSION} //Pascal\r
45158 function TStrList.AppendToFile(const FileName: string): Boolean;\r
45159 var F: HFile;\r
45160     Buf: String;\r
45161     L: Integer;\r
45162 begin\r
45163   F := FileCreate( FileName, ofOpenWrite or ofOpenAlways );\r
45164   Result := F <> INVALID_HANDLE_VALUE;\r
45165   if Result then\r
45166   begin\r
45167     FileSeek( F, 0, spEnd );\r
45168     Buf := Text;\r
45169     L := Length( Buf );\r
45170     FileWrite( F, Buf[ 1 ], L );\r
45171     FileClose( F );\r
45172   end;\r
45173 end;\r
45174 {$ENDIF ASM_VERSION}\r
45176 {$IFDEF ASM_VERSION}\r
45177 //[procedure TStrList.Assign]\r
45178 procedure TStrList.Assign(Strings: PStrList);\r
45179 asm\r
45180         PUSHAD\r
45181         CALL     Clear\r
45182         POPAD\r
45183         JMP      AddStrings\r
45184 end;\r
45185 {$ELSE ASM_VERSION} //Pascal\r
45186 procedure TStrList.Assign(Strings: PStrList);\r
45187 begin\r
45188   Clear;\r
45189   AddStrings( Strings );\r
45190 end;\r
45191 {$ENDIF ASM_VERSION}\r
45193 {$IFDEF ASM_VERSION}\r
45194 //[procedure TStrList.Clear]\r
45195 procedure TStrList.Clear;\r
45196 asm\r
45197         PUSH     EBX\r
45198         XCHG     EBX, EAX\r
45199         MOV      EDX, [EBX].fCount\r
45200 @@loo:  DEC      EDX\r
45201         JL       @@eloo\r
45202         PUSH     EDX\r
45203         MOV      EAX, EBX\r
45204         CALL     Delete\r
45205         POP      EDX\r
45206         JMP      @@loo\r
45207 @@eloo:\r
45208         XOR      EAX, EAX\r
45209         MOV      [EBX].fTextSiz, EAX\r
45210         XCHG     EAX, [EBX].fTextBuf\r
45211         TEST     EAX, EAX\r
45212         JZ       @@1\r
45213         CALL     System.@FreeMem\r
45214         //XOR      EAX, EAX // not needed: if OK, EAX = 0\r
45215 @@1:    XCHG     EAX, [EBX].fList\r
45216         CALL     TObj.Free\r
45217         POP      EBX\r
45218 end;\r
45219 {$ELSE ASM_VERSION} //Pascal\r
45220 procedure TStrList.Clear;\r
45221 var I: Integer;\r
45222 begin\r
45223   if fCount > 0 then\r
45224   for I := fList.Count - 1 downto 0 do\r
45225     Delete( I );\r
45226   fList.Free;\r
45227   fList := nil;\r
45228   fCount := 0;\r
45229   if fTextBuf <> nil then\r
45230   begin\r
45231     FreeMem( fTextBuf );\r
45232     fTextBuf := nil;\r
45233     fTextSiz := 0;\r
45234   end;\r
45235 end;\r
45236 {$ENDIF ASM_VERSION}\r
45238 {$IFDEF ASM_VERSION}\r
45239 //[procedure TStrList.Delete]\r
45240 procedure TStrList.Delete(Idx: integer);\r
45241 asm\r
45242         DEC      [EAX].fCount\r
45243         PUSH     EAX\r
45244         MOV      EAX, [EAX].fList\r
45245         MOV      ECX, [EAX].TList.fItems\r
45246         PUSH     dword ptr [ECX+EDX*4]\r
45247         CALL     TList.Delete\r
45248         POP      EAX\r
45249         POP      EDX\r
45250         MOV      ECX, [EDX].fTextSiz\r
45251         JECXZ    @@fremem\r
45252         CMP      EAX, [EDX].fTextBuf\r
45253         JB       @@fremem\r
45254         ADD      ECX, [EDX].fTextBuf\r
45255         CMP      EAX, ECX\r
45256         JB       @@exit\r
45257 @@fremem:\r
45258         CALL     System.@FreeMem\r
45259 @@exit:\r
45260 end;\r
45261 {$ELSE ASM_VERSION} //Pascal\r
45262 procedure TStrList.Delete(Idx: integer);\r
45263 var P: DWORD;\r
45264     El:Pointer;\r
45265 begin\r
45266   P := DWORD( fList.fItems[ Idx ] );\r
45267   if (fTextBuf <> nil) and ( P >= DWORD( fTextBuf )) and\r
45268      ( P < DWORD( fTextBuf ) + fTextSiz ) then\r
45269   else\r
45270   begin\r
45271     El := FList.Items[ Idx ];\r
45272     FreeMem( El );\r
45273   end;\r
45274   fList.Delete( Idx );\r
45275   Dec( fCount );\r
45276 end;\r
45277 {$ENDIF ASM_VERSION}\r
45279 {$IFDEF ASM_VERSION}\r
45280 //[function TStrList.Get]\r
45281 function TStrList.Get(Idx: integer): string;\r
45282 asm\r
45283         PUSH     ECX\r
45284         MOV      EAX, [EAX].fList\r
45285         TEST     EAX, EAX\r
45286         JZ       @@1\r
45287         CALL     TList.Get\r
45288 @@1:    XCHG     EDX, EAX\r
45289         POP      EAX\r
45290         JMP      System.@LStrFromPChar\r
45291 end;\r
45292 {$ELSE ASM_VERSION} //Pascal\r
45293 function TStrList.Get(Idx: integer): string;\r
45294 begin\r
45295   if fList <> nil then\r
45296     Result := PChar( fList.Items[ Idx ] )\r
45297   else Result := '';\r
45298 end;\r
45299 {$ENDIF ASM_VERSION}\r
45301 {$IFDEF ASM_VERSION}\r
45302 //[function TStrList.GetPChars]\r
45303 function TStrList.GetPChars(Idx: Integer): PChar;\r
45304 asm\r
45305         MOV      EAX, [EAX].fList\r
45306         MOV      EAX, [EAX].TList.fItems\r
45307         MOV      EAX, [EAX+EDX*4]\r
45308 end;\r
45309 {$ELSE ASM_VERSION} //Pascal\r
45310 function TStrList.GetPChars(Idx: Integer): PChar;\r
45311 begin\r
45312   Result := PChar( fList.fItems[ Idx ] );\r
45313 end;\r
45314 {$ENDIF ASM_VERSION}\r
45316 {$IFDEF ASM_VERSION}\r
45317 //[function TStrList.GetTextStr]\r
45318 function TStrList.GetTextStr: string;\r
45319 asm\r
45320         PUSH     ESI\r
45321         PUSH     EDI\r
45322         MOV      ECX, [EAX].fCount\r
45323         MOV      EAX, [EAX].fList\r
45324         PUSH     ECX\r
45325         JECXZ    @@1\r
45326         MOV      ESI, [EAX].TList.fItems\r
45327 @@1:    PUSH     ESI\r
45328         XCHG     EAX, EDX\r
45329         XOR      EDX, EDX\r
45330         JECXZ    @@10\r
45331         PUSH     EAX\r
45332 @@loo1:\r
45333         PUSH     ECX\r
45334         PUSH     EDX\r
45335         LODSD\r
45336         CALL     StrLen\r
45337         POP      EDX\r
45338         LEA      EDX, [EDX+EAX+2]\r
45339         POP      ECX\r
45340         LOOP     @@loo1\r
45342         POP      EAX\r
45343         POP      ESI\r
45344         XCHG     ECX, EDX\r
45345         PUSH     EAX\r
45346 @@10:\r
45347         {$IFDEF _D2}\r
45348         CALL     _LStrFromPCharLen\r
45349         {$ELSE}\r
45350         CALL     System.@LStrFromPCharLen\r
45351         {$ENDIF}\r
45353         POP      EDI\r
45354         POP      ECX\r
45355         JECXZ    @@exit\r
45356         MOV      EDI, [EDI]\r
45358 @@loo2: PUSH     ECX\r
45359         LODSD\r
45360         PUSH     EAX\r
45361         CALL     StrLen\r
45362         XCHG     ECX, EAX\r
45363         POP      EAX\r
45364         XCHG     EAX, ESI\r
45365         REP      MOVSB\r
45366         XCHG     ESI, EAX\r
45367         MOV      AX, $0A0D\r
45368         STOSW\r
45369         POP      ECX\r
45370         LOOP     @@loo2\r
45372         XCHG     EAX, ECX\r
45373         STOSB\r
45374 @@exit:\r
45375         POP      EDI\r
45376         POP      ESI\r
45377 end;\r
45378 {$ELSE ASM_VERSION} //Pascal\r
45379 function TStrList.GetTextStr: string;\r
45380 var\r
45381    I, Len, Size: integer;\r
45382    P: PChar;\r
45383 begin\r
45384      Size := 0;\r
45386      for I := 0 to fCount - 1 do\r
45387        Inc(Size, StrLen( PChar(fList.fItems[I]) ) + 2);\r
45389      SetString(Result, nil, Size);\r
45391      P := Pointer(Result);\r
45392      for I := 0 to Count - 1 do\r
45393      begin\r
45394        Len := StrLen(PChar(fList.fItems[I]));\r
45395        if (Len > 0) then\r
45396        begin\r
45397          System.Move(PChar(fList.fItems[I])^, P^, Len);\r
45398          Inc(P, Len);\r
45399        end;\r
45400        P^ := #13;\r
45401        Inc(P);\r
45402        P^ := #10;\r
45403        Inc(P);\r
45404      end;\r
45405 end;\r
45406 {$ENDIF ASM_VERSION}\r
45408 {$IFDEF ASM_VERSION}\r
45409 //[function TStrList.IndexOf]\r
45410 function TStrList.IndexOf(const S: string): integer;\r
45411 asm\r
45412         PUSH     EBX\r
45413         PUSH     ESI\r
45414         OR       EBX, -1\r
45415         MOV      ECX, [EAX].fCount\r
45416         JECXZ    @@exit\r
45417         MOV      ESI, [EAX].fList\r
45418         MOV      ESI, [ESI].TList.fItems\r
45419 @@loo:  LODSD\r
45420         INC      EBX\r
45421         CMP      EAX, EDX\r
45422         JE       @@exit\r
45423         OR       EDX, EDX\r
45424         JZ       @@1\r
45425         PUSH     EDX\r
45426         PUSH     ECX\r
45427         CALL     StrComp\r
45428         POP      ECX\r
45429         POP      EDX\r
45430         JE       @@exit\r
45431 @@1:    LOOP     @@loo\r
45432         OR       EBX, -1\r
45433 @@exit: XCHG     EAX, EBX\r
45434         POP      ESI\r
45435         POP      EBX\r
45436 end;\r
45437 {$ELSE ASM_VERSION} //Pascal\r
45438 function TStrList.IndexOf(const S: string): integer;\r
45439 begin\r
45440   for Result := 0 to fCount - 1 do\r
45441     if (S = PChar( fList.Items[Result] )) then Exit;\r
45442   Result := -1;\r
45443 end;\r
45444 {$ENDIF ASM_VERSION}\r
45446 //[function TStrList.IndexOf]\r
45447 function TStrList.IndexOf_NoCase(const S: string): integer;\r
45448 begin\r
45449   for Result := 0 to fCount - 1 do\r
45450     if StrComp_NoCase( PChar( S ), PChar( fList.Items[Result] ) ) = 0 then Exit;\r
45451   Result := -1;\r
45452 end;\r
45454 function TStrList.IndexOfStrL_NoCase( Str: PChar; L: Integer ): integer;\r
45455 begin\r
45456   for Result := 0 to fCount - 1 do\r
45457     if (StrLen( PChar( fList.fItems[ Result ] ) ) = DWORD( L )) and\r
45458        (StrLComp_NoCase( Str, PChar( fList.fItems[ Result ] ), L ) = 0) then Exit;\r
45459   Result := -1;\r
45460 end;\r
45462 //[function TStrList.Find]\r
45463 function TStrList.Find(const S: String; var Index: Integer): Boolean;\r
45464 var\r
45465   L, H, I, C: Integer;\r
45466 begin\r
45467   Result := FALSE;\r
45468   L := 0;\r
45469   H := FCount - 1;\r
45470   while L <= H do\r
45471   begin\r
45472     I := (L + H) shr 1;\r
45473     C := AnsiCompareStr( PChar( fList.Items[ I ] ), S );\r
45474     if C < 0 then L := I + 1 else\r
45475     begin\r
45476       H := I - 1;\r
45477       if C = 0 then\r
45478       begin\r
45479         Result := TRUE;\r
45480         L := I;\r
45481         //break;\r
45482         //if Duplicates <> dupAccept then L := I;\r
45483       end;\r
45484     end;\r
45485   end;\r
45486   Index := L;\r
45487 end;\r
45489 {$IFDEF ASM_VERSION}\r
45490 //[procedure TStrList.Insert]\r
45491 procedure TStrList.Insert(Idx: integer; const S: string);\r
45492 asm\r
45493         PUSH     EBX\r
45494         PUSH     EDX\r
45495         PUSH     ECX\r
45496         XCHG     EBX, EAX\r
45497         MOV      EAX, [EBX].fList\r
45498         TEST     EAX, EAX\r
45499         JNZ      @@1\r
45500         CALL     NewList\r
45501         MOV      [EBX].fList, EAX\r
45502 @@1:\r
45503         POP      EAX\r
45504         PUSH     EAX          // push S\r
45505         CALL     System.@LStrLen\r
45506         INC      EAX\r
45507         PUSH     EAX          // push L\r
45508         CALL     System.@GetMem\r
45509         MOV      byte ptr[EAX], 0\r
45510         XCHG     EDX, EAX\r
45511         POP      ECX\r
45512         POP      EAX\r
45513         PUSH     EDX          // push Mem\r
45514         TEST     EAX, EAX\r
45515         JE       @@2\r
45516         CALL     System.Move\r
45517 @@2:    POP      ECX\r
45518         POP      EDX\r
45519         MOV      EAX, [EBX].fList\r
45520         CALL     TList.Insert\r
45521         INC      [EBX].fCount\r
45522         POP      EBX\r
45523 end;\r
45524 {$ELSE ASM_VERSION} //Pascal\r
45525 procedure TStrList.Insert(Idx: integer; const S: string);\r
45526 var Mem: PChar;\r
45527     L: Integer;\r
45528 begin\r
45529   if fList = nil then\r
45530      fList := NewList;\r
45531   L := Length( S ) + 1;\r
45532   GetMem( Mem, L );\r
45533   Mem[0] := #0;\r
45534   if L > 1 then\r
45535      System.Move( S[1], Mem[0], L );\r
45536   fList.Insert( Idx, Mem );\r
45537   Inc( fCount );\r
45538 end;\r
45539 {$ENDIF ASM_VERSION}\r
45541 {$IFDEF ASM_VERSION}\r
45542 //[function TStrList.LoadFromFile]\r
45543 function TStrList.LoadFromFile(const FileName: string): Boolean;\r
45544 asm\r
45545       PUSH     EAX\r
45546         XCHG     EAX, EDX\r
45547         MOV      EDX, ofOpenRead or ofShareDenyWrite or ofOpenExisting\r
45548         CALL     FileCreate\r
45549         INC      EAX\r
45550         JZ       @@exit\r
45551         DEC      EAX\r
45552         PUSH     EBX\r
45553         XCHG     EBX, EAX\r
45554         PUSH     0\r
45555         PUSH     EBX\r
45556         CALL     GetFileSize\r
45557         XOR      EDX, EDX\r
45558         PUSH     EDX\r
45559         XCHG     ECX, EAX\r
45560         MOV      EAX, ESP\r
45561         PUSH     ECX\r
45562         {$IFDEF _D2}\r
45563         CALL     _LStrFromPCharLen\r
45564         {$ELSE}\r
45565         CALL     System.@LStrFromPCharLen\r
45566         {$ENDIF}\r
45567         POP      ECX\r
45568         MOV      EAX, EBX\r
45569         POP      EDX\r
45570         PUSH     EDX\r
45571         CALL     FileRead\r
45572         XCHG     EAX, EBX\r
45573         CALL     FileClose\r
45574         POP      EDX\r
45575         POP      EBX\r
45576       POP      EAX\r
45577         PUSH     EDX\r
45578         XOR      ECX, ECX\r
45579         CALL     SetText\r
45580         CALL     RemoveStr\r
45581         PUSH     EDX\r
45582         MOV      AL, 1\r
45583 @@exit: POP      EDX\r
45584 end;\r
45585 {$ELSE ASM_VERSION} //Pascal\r
45586 function TStrList.LoadFromFile(const FileName: string): Boolean;\r
45587 var Buf: String;\r
45588     F: HFile;\r
45589     Sz: Integer;\r
45590 begin\r
45591   F := FileCreate( FileName, ofOpenRead or ofShareDenyWrite or ofOpenExisting );\r
45592   Result := F <> INVALID_HANDLE_VALUE;\r
45593   if Result then\r
45594   begin\r
45595     Sz := GetFileSize( F, nil );\r
45596     SetString( Buf, nil, Sz );\r
45597     FileRead( F, Buf[1], Sz );\r
45598     FileClose( F );\r
45600     SetText( Buf, False );\r
45601   end;\r
45602 end;\r
45603 {$ENDIF ASM_VERSION}\r
45605 {$IFDEF ASM_VERSION}\r
45606 //[procedure TStrList.LoadFromStream]\r
45607 procedure TStrList.LoadFromStream(Stream: PStream; Append2List: boolean);\r
45608 asm\r
45609         PUSH     EAX\r
45610         PUSH     ECX\r
45611         PUSH     EBX\r
45612         XCHG     EAX, EDX\r
45613         MOV      EBX, EAX\r
45614         CALL     TStream.GetSize\r
45615         PUSH     EAX\r
45616         MOV      EAX, EBX\r
45617         CALL     TStream.GetPosition\r
45618         POP      ECX\r
45619         SUB      ECX, EAX\r
45620         XOR      EDX, EDX\r
45621         PUSH     EDX\r
45622         MOV      EAX, ESP\r
45623         PUSH     ECX\r
45624         {$IFDEF _D2}\r
45625         CALL     _LStrFromPCharLen\r
45626         {$ELSE}\r
45627         CALL     System.@LStrFromPCharLen\r
45628         {$ENDIF}\r
45629         POP      ECX\r
45630         POP      EDX\r
45631         XCHG     EAX, EBX\r
45632         PUSH     EDX\r
45633         CALL     TStream.Read\r
45634         POP      EDX\r
45635         POP      EBX\r
45636         POP      ECX\r
45637         POP      EAX\r
45638         PUSH     EDX\r
45639         CALL     SetText\r
45640         CALL     RemoveStr\r
45641 end;\r
45642 {$ELSE ASM_VERSION} //Pascal\r
45643 procedure TStrList.LoadFromStream(Stream: PStream; Append2List: boolean);\r
45644 var Buf: String;\r
45645     Sz: Integer;\r
45646 begin\r
45647   Sz := Stream.Size - Stream.Position;\r
45648   SetString( Buf, nil, Sz );\r
45649   Stream.Read( Buf[1], Sz );\r
45650   SetText( Buf, Append2List );\r
45651 end;\r
45652 {$ENDIF ASM_VERSION}\r
45654 {$IFDEF ASM_VERSION}\r
45655 //[procedure TStrList.MergeFromFile]\r
45656 procedure TStrList.MergeFromFile(const FileName: string);\r
45657 asm\r
45658         PUSH     EAX\r
45659         XCHG     EAX, EDX\r
45660         CALL     NewReadFileStream\r
45661         XCHG     EDX, EAX\r
45662         POP      EAX\r
45663         MOV      CL, 1\r
45664         PUSH     EDX\r
45665         CALL     LoadFromStream\r
45666         POP      EAX\r
45667         JMP      TObj.Free\r
45668 end;\r
45669 {$ELSE ASM_VERSION} //Pascal\r
45670 procedure TStrList.MergeFromFile(const FileName: string);\r
45671 var TmpStream: PStream;\r
45672 begin\r
45673   TmpStream := NewReadFileStream( FileName );\r
45674   LoadFromStream( TmpStream, True );\r
45675   TmpStream.Free;\r
45676 end;\r
45677 {$ENDIF ASM_VERSION}\r
45679 //[procedure TStrList.Move]\r
45680 procedure TStrList.Move(CurIndex, NewIndex: integer);\r
45681 begin\r
45682   fList.MoveItem( CurIndex, NewIndex );\r
45683 end;\r
45685 {$IFDEF ASM_VERSION}\r
45686 //[procedure TStrList.Put]\r
45687 procedure TStrList.Put(Idx: integer; const Value: string);\r
45688 asm\r
45689         PUSH     EAX\r
45690         PUSH     EDX\r
45691         CALL     Insert\r
45692         POP      EDX\r
45693         POP      EAX\r
45694         INC      EDX\r
45695         JMP      Delete\r
45696 end;\r
45697 {$ELSE ASM_VERSION} //Pascal\r
45698 procedure TStrList.Put(Idx: integer; const Value: string);\r
45699 begin\r
45700   Delete( Idx );\r
45701   Insert( Idx, Value );\r
45702 end;\r
45703 {$ENDIF ASM_VERSION}\r
45705 {$IFDEF ASM_VERSION}\r
45706 //[function TStrList.SaveToFile]\r
45707 function TStrList.SaveToFile(const FileName: string): Boolean;\r
45708 asm\r
45709         PUSH     EBX\r
45710         PUSH     EAX\r
45711         XCHG     EAX, EDX\r
45712         MOV      EDX, ofOpenWrite or ofOpenAlways\r
45713         CALL     FileCreate\r
45714         INC      EAX\r
45715         JZ       @@exit\r
45716         DEC      EAX\r
45717         XCHG     EBX, EAX\r
45718         POP      EAX\r
45719         PUSH     0\r
45720         MOV      EDX, ESP\r
45721         CALL     GetTextStr\r
45722         POP      EAX\r
45723         PUSH     EAX\r
45724         CALL     System.@LStrLen\r
45725         XCHG     ECX, EAX\r
45726         POP      EDX\r
45727         PUSH     EDX\r
45728         MOV      EAX, EBX\r
45729         CALL     FileWrite\r
45730         PUSH     EBX\r
45731         CALL     SetEndOfFile\r
45732         XCHG     EAX, EBX\r
45733         CALL     FileClose\r
45734         CALL     RemoveStr\r
45735         PUSH     EDX\r
45736         INC      EAX\r
45737 @@exit:\r
45738         POP      EDX\r
45739         POP      EBX\r
45740 end;\r
45741 {$ELSE ASM_VERSION} //Pascal\r
45742 function TStrList.SaveToFile(const FileName: string): Boolean;\r
45743 var F: HFile;\r
45744     Buf: String;\r
45745 begin\r
45746   F := FileCreate( FileName, ofOpenWrite or ofOpenAlways );\r
45747   Result := F <> INVALID_HANDLE_VALUE;\r
45748   if Result then\r
45749   begin\r
45750     Buf := Text;\r
45751     FileWrite( F, Buf[ 1 ], Length( Buf ) );\r
45752     SetEndOfFile( F ); // necessary! - V.K.\r
45753     FileClose( F );\r
45754   end;\r
45755 end;\r
45756 {$ENDIF ASM_VERSION}\r
45758 {$IFDEF ASM_VERSION}\r
45759 //[procedure TStrList.SaveToStream]\r
45760 procedure TStrList.SaveToStream(Stream: PStream);\r
45761 asm\r
45762         PUSH     EDX\r
45763         PUSH     0\r
45764         MOV      EDX, ESP\r
45765         CALL     GetTextStr\r
45766         POP      EAX\r
45767         PUSH     EAX\r
45768         CALL     System.@LStrLen\r
45769         XCHG     ECX, EAX\r
45770         POP      EDX\r
45771         POP      EAX\r
45772         PUSH     EDX\r
45773         JECXZ    @@1\r
45774         CALL     TStream.Write\r
45775 @@1:\r
45776         CALL     RemoveStr\r
45777 end;\r
45778 {$ELSE ASM_VERSION} //Pascal\r
45779 procedure TStrList.SaveToStream(Stream: PStream);\r
45780 var S: string;\r
45781     L: Integer;\r
45782 begin\r
45783    S := GetTextStr;\r
45784    L := Length( S );\r
45785    if L <> 0 then\r
45786    Stream.Write( S[1], L );\r
45787 end;\r
45788 {$ENDIF ASM_VERSION}\r
45790 {$IFDEF ASM_VERSION}\r
45791 //[procedure TStrList.SetText]\r
45792 procedure TStrList.SetText(const S: string; Append2List: boolean);\r
45793 asm\r
45794         DEC      CL\r
45795         JZ       @@1\r
45796         PUSHAD\r
45797         CALL     Clear\r
45798         POPAD\r
45799 @@1:    CALL     EDX2PChar\r
45800         JZ       @@exit\r
45802         PUSH     EBX\r
45803         PUSH     EDI\r
45804         MOV      EBX, EAX\r
45805         MOV      EDI, [EBX].fTextSiz\r
45807         MOV      EAX, [EDX-4] // EAX = Length(S)\r
45808         INC      EAX\r
45809         PUSH     EAX\r
45811         // add S to text buffer\r
45812         //CMP      byte ptr [EDX], 0\r
45813         //JZ       @@eatb\r
45815         PUSH     EDX\r
45816         PUSH     [EBX].fTextBuf\r
45817         ADD      EAX, [EBX].fTextSiz\r
45818         CALL     System.@GetMem\r
45819         MOV      [EBX].fTextBuf, EAX\r
45821         MOV      ECX, EDI\r
45822         XCHG     EDX, EAX\r
45823         POP      EAX\r
45824         JECXZ    @@atb_fin\r
45825         PUSH     EAX\r
45826         CALL     System.Move\r
45828         POP      EDX\r
45829         PUSH     EDX\r
45831         PUSH     ESI\r
45832         MOV      ESI, [EBX].fList\r
45833         MOV      ESI, [ESI].TList.fItems\r
45834         MOV      ECX, [EBX].fCount\r
45836 @@atb_loo:\r
45837         LODSD\r
45838         SUB      EAX, EDX\r
45839         CMP      EAX, [EBX].fTextSiz\r
45840         JAE      @@atb_nxt\r
45842         ADD      EAX, [EBX].fTextBuf\r
45843         MOV      [ESI-4], EAX\r
45845 @@atb_nxt: LOOP  @@atb_loo\r
45847         POP      ESI\r
45848         POP      EAX\r
45849         CALL     System.@FreeMem\r
45850 @@atb_fin:\r
45851         POP      EAX\r
45853         MOV      EDX, EDI\r
45854         ADD      EDX, [EBX].fTextBuf\r
45855         POP      ECX\r
45856         PUSH     ECX\r
45857         ADD      [EBX].fTextSiz, ECX\r
45859         CALL     System.Move\r
45861 @@eatb:\r
45862         ADD      EDI, [EBX].fTextBuf // EDI ~ P\r
45864         MOV      ECX, [EBX].fList\r
45865         INC      ECX\r
45866         LOOP     @@2\r
45867         CALL     NewList\r
45868         MOV      [EBX].fList, EAX\r
45869 @@2:\r
45870         POP      ECX\r
45871         MOV      EDX, [EBX].fCount\r
45873         PUSH     EDI\r
45874         PUSH     ECX\r
45875         MOV      AL, $0D\r
45877 @@loo1: CMP      byte ptr [EDI], 0\r
45878         JZ       @@eloo1\r
45880         INC      EDX\r
45881         REPNZ    SCASB\r
45882         JNZ      @@eloo1\r
45884         CMP      byte ptr [EDI], $0A\r
45885         JNZ      @@loo1\r
45886         INC      EDI\r
45887         LOOP     @@loo1\r
45889 @@eloo1:\r
45890         MOV      [EBX].fCount, EDX\r
45891         MOV      EAX, [EBX].fList\r
45892         PUSH     EDX\r
45893         PUSH     EAX\r
45894         CMP      EDX, [EAX].TList.fCapacity\r
45895         JLE      @@3\r
45896         CALL     TList.SetCapacity\r
45897 @@3:    POP      EAX\r
45898         POP      ECX\r
45900         XCHG     ECX, [EAX].TList.fCount\r
45901         MOV      EDX, [EAX].TList.fItems\r
45902         LEA      EDX, [EDX+ECX*4]\r
45904         POP      ECX\r
45905         POP      EDI\r
45907         MOV      EAX, $0D\r
45908 @@loo2: CMP      byte ptr [EDI], AH\r
45909         JZ       @@eloo2\r
45911         MOV      [EDX], EDI\r
45912         ADD      EDX, 4\r
45914         REPNZ    SCASB\r
45915         JNZ      @@eloo2\r
45917         MOV      [EDI-1], AH\r
45919         CMP      byte ptr [EDI], $0A\r
45920         JNZ      @@loo2\r
45921         INC      EDI\r
45922         LOOP     @@loo2\r
45923 @@eloo2:\r
45925         POP      EDI\r
45926         POP      EBX\r
45927 @@exit:\r
45928 end;\r
45929 {$ELSE ASM_VERSION} //Pascal\r
45930 //[procedure TStrList.SetText]\r
45931 procedure TStrList.SetText(const S: string; Append2List: boolean);\r
45932 var\r
45933   P, TheLast : PChar;\r
45934   L, I : Integer;\r
45936   procedure AddTextBuf(Src: PChar; Len: DWORD);\r
45937   var OldTextBuf, P: PChar;\r
45938       I : Integer;\r
45939   begin\r
45940     if Src <> nil then\r
45941     begin\r
45942       OldTextBuf := fTextBuf;\r
45943       GetMem( fTextBuf, fTextSiz + Len );\r
45944       if fTextSiz <> 0 then\r
45945       begin\r
45946         System.Move( OldTextBuf^, fTextBuf^, fTextSiz );\r
45947         for I := 0 to fCount - 1 do\r
45948         begin\r
45949           P := fList.fItems[ I ];\r
45950           if (DWORD( P ) >= DWORD( OldTextBuf )) and\r
45951              (DWORD( P ) < DWORD( OldTextBuf ) + fTextSiz) then\r
45952             fList.fItems[ I ] := Pointer( DWORD( P ) - DWORD( OldTextBuf ) + DWORD( fTextBuf ) );\r
45953         end;\r
45954         FreeMem( OldTextBuf );\r
45955       end;\r
45956       System.Move( Src^, fTextBuf[ fTextSiz ], Len );\r
45957       Inc( fTextSiz, Len );\r
45958     end;\r
45959   end;\r
45961 begin\r
45962      if not Append2List then Clear;\r
45963      if S = '' then Exit;\r
45965      L := fTextSiz;\r
45966      AddTextBuf( PChar( S ), Length( S ) + 1 );\r
45968      P := PChar( DWORD( fTextBuf ) + DWORD( L ) );\r
45969      if fList = nil then\r
45970        fList := NewList;\r
45972      I := 0;\r
45973      TheLast := P + Length( S );\r
45974      while P^ <> #0 do\r
45975      begin\r
45976        Inc( I );\r
45977        P := StrScanLen( P, #13, TheLast - P );\r
45978        if P^ = #10 then\r
45979          Inc( P );\r
45980      end;\r
45982      Inc( fCount, I );\r
45983      if fList.fCapacity < fCount  then\r
45984         fList.Capacity := fCount;\r
45986      P := PChar( DWORD( fTextBuf ) + DWORD( L ) );\r
45987      while P^ <> #0 do\r
45988      begin\r
45989        fList.Add( P );\r
45990        P := StrScanLen( P, #13, TheLast - P );\r
45991        if PChar( P - 1 )^ = #13 then\r
45992          PChar( P - 1 )^ := #0;\r
45993        if P^ = #10 then Inc(P);\r
45994      end;\r
45995 end;\r
45996 {$ENDIF ASM_VERSION}\r
45998 //[procedure TStrList.SetUnixText]\r
45999 procedure TStrList.SetUnixText(const S: String; Append2List: Boolean);\r
46000 var S1: String;\r
46001 begin\r
46002   S1 := S;\r
46003   NormalizeUnixText( S1 );\r
46004   SetText( S1, Append2List );\r
46005 end;\r
46007 //[procedure TStrList.SetTextStr]\r
46008 procedure TStrList.SetTextStr(const Value: string);\r
46009 begin\r
46010   SetText( Value, False );\r
46011 end;\r
46013 //[PROCEDURE LowerCaseStrFromPCharEDX]\r
46014 {$IFDEF ASM_VERSION}\r
46015 procedure LowerCaseStrFromPCharEDX;\r
46016 asm\r
46017           { <- EDX = PChar string\r
46018             -> [ESP] = LowerCase( PChar( EDX ) ),\r
46019                EAX, EDX, ECX - ?\r
46020           }\r
46021         POP      EAX\r
46022         PUSH     0\r
46023         PUSH     EAX\r
46024         LEA      EAX, [ESP+4]\r
46025         PUSH     EAX\r
46026         CALL     System.@LStrFromPChar\r
46027         POP      EDX\r
46028         MOV      EAX, [EDX]\r
46029         JMP      LowerCase\r
46030 end;\r
46031 {$ENDIF ASM_VERSION}\r
46032 //[END LowerCaseStrFromPCharEDX]\r
46034 //[FUNCTION CompareStrListItems]\r
46035 {$IFDEF ASM_VERSION}\r
46036 function CompareStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;\r
46037 asm\r
46038         CMP      [EAX].TStrList.fCaseSensitiveSort, 0\r
46039         MOV      EAX, [EAX].TStrList.fList\r
46040         MOV      EAX, [EAX].TList.fItems\r
46041         MOV      EDX, [EAX+EDX*4]\r
46042         MOV      EAX, [EAX+ECX*4]\r
46043         XCHG     EAX, EDX\r
46044         JNZ      StrComp\r
46045         PUSH     EBX\r
46047         XCHG     EBX, EAX\r
46048         CALL     LowerCaseStrFromPCharEDX\r
46050         MOV      EDX, EBX\r
46051         CALL     LowerCaseStrFromPCharEDX\r
46053         POP      EAX\r
46054         POP      EDX\r
46055         PUSH     EDX\r
46056         PUSH     EAX\r
46057         CALL     EAX2PChar\r
46058         CALL     EDX2PChar\r
46059         CALL     StrComp\r
46060         XCHG     EBX, EAX\r
46062         CALL     RemoveStr\r
46063         CALL     RemoveStr\r
46065         XCHG     EAX, EBX\r
46066         POP      EBX\r
46067 end;\r
46068 {$ELSE ASM_VERSION} //Pascal\r
46069 function CompareStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;\r
46070 var S1, S2 : PChar;\r
46071 begin\r
46072   S1 := PStrList( Sender ).fList.Items[ e1 ];\r
46073   S2 := PStrList( Sender ).fList.Items[ e2 ];\r
46074   if PStrList( Sender ).fCaseSensitiveSort then\r
46075     Result := StrComp( S1, S2 )\r
46076   else\r
46077     Result := StrComp( PChar( LowerCase( S1 ) ), PChar( LowerCase( S2 ) ) );\r
46078 end;\r
46079 {$ENDIF ASM_VERSION}\r
46080 //[END CompareStrListItems]\r
46082 //[FUNCTION CompareAnsiStrListItems]\r
46083 {$IFDEF ASM_VERSION}\r
46084 function CompareAnsiStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;\r
46085 asm\r
46086         CMP      byte ptr [EAX].TStrList.fCaseSensitiveSort, 0\r
46087         MOV      EAX, [EAX].TStrList.fList\r
46088         MOV      EAX, [EAX].TList.fItems\r
46089         MOV      EDX, [EAX+EDX*4]\r
46090         MOV      EAX, [EAX+ECX*4]\r
46091         XCHG     EAX, EDX\r
46092         JZ       _AnsiCompareStrNoCase\r
46093         JMP      _AnsiCompareStr\r
46094 end;\r
46095 {$ELSE ASM_VERSION} //Pascal\r
46096 function CompareAnsiStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;\r
46097 var S1, S2 : PChar;\r
46098 begin\r
46099   S1 := PStrList( Sender ).fList.Items[ e1 ];\r
46100   S2 := PStrList( Sender ).fList.Items[ e2 ];\r
46101   if PStrList( Sender ).fCaseSensitiveSort then\r
46102     Result := _AnsiCompareStr( S1, S2 )\r
46103   else\r
46104     Result := _AnsiCompareStrNoCase( S1, S2 );\r
46105 end;\r
46106 {$ENDIF ASM_VERSION}\r
46107 //[END CompareAnsiStrListItems]\r
46109 {$IFNDEF ASM_VERSION}\r
46110 //[procedure SwapStrListItems]\r
46111 procedure SwapStrListItems( const Sender: Pointer; const e1, e2: DWORD );\r
46112 begin\r
46113   PStrList( Sender ).Swap( e1, e2 );\r
46114 end;\r
46115 {$ENDIF}\r
46117 {$IFDEF ASM_VERSION}\r
46118 //[procedure TStrList.Sort]\r
46119 procedure TStrList.Sort(CaseSensitive: Boolean);\r
46120 asm\r
46121         MOV      [EAX].fCaseSensitiveSort, DL\r
46122         PUSH     Offset[TStrList.Swap]\r
46123         MOV      ECX, Offset[CompareStrListItems]\r
46124         MOV      EDX, [EAX].fCount\r
46125         CALL     SortData\r
46126 end;\r
46127 {$ELSE ASM_VERSION} //Pascal\r
46128 procedure TStrList.Sort(CaseSensitive: Boolean);\r
46129 begin\r
46130   fCaseSensitiveSort := CaseSensitive;\r
46131   SortData( @Self, fCount, @CompareStrListItems, @SwapStrListItems );\r
46132 end;\r
46133 {$ENDIF ASM_VERSION}\r
46135 {$IFDEF ASM_VERSION}\r
46136 //[procedure TStrList.AnsiSort]\r
46137 procedure TStrList.AnsiSort(CaseSensitive: Boolean);\r
46138 asm\r
46139         MOV      [EAX].fCaseSensitiveSort, DL\r
46140         PUSH     Offset[TStrList.Swap]\r
46141         MOV      ECX, Offset[CompareAnsiStrListItems]\r
46142         MOV      EDX, [EAX].fCount\r
46143         CALL     SortData\r
46144 end;\r
46145 {$ELSE ASM_VERSION} //Pascal\r
46146 procedure TStrList.AnsiSort(CaseSensitive: Boolean);\r
46147 begin\r
46148   fCaseSensitiveSort := CaseSensitive;\r
46149   SortData( @Self, fCount, @CompareAnsiStrListItems, @SwapStrListItems );\r
46150 end;\r
46151 {$ENDIF ASM_VERSION}\r
46153 //[procedure TStrList.Swap]\r
46154 procedure TStrList.Swap(Idx1, Idx2: Integer);\r
46155 begin\r
46156   fList.Swap( Idx1, Idx2 );\r
46157 end;\r
46159 //[function TStrList.Last]\r
46160 function TStrList.Last: String;\r
46161 begin\r
46162   if Count = 0 then\r
46163     Result := ''\r
46164   else\r
46165     Result := Items[ Count - 1 ];\r
46166 end;\r
46168 //-- code by Dod:\r
46169 //[function TStrList.IndexOfName]\r
46170 function TStrList.IndexOfName(Name: string): Integer;\r
46171 var\r
46172   i: Integer;\r
46173   L: Integer;\r
46174 begin\r
46175   Result:=-1;\r
46176   // Do not start search if empty string\r
46177   L := Length( Name );\r
46178   if L > 0 then\r
46179   begin\r
46180     Name := LowerCase( Name ) + fNameDelim;\r
46181     Inc( L );\r
46182     for i := 0 to fCount - 1 do\r
46183     begin\r
46184       // For optimization, check only list entry that begin with same letter as searched name\r
46185       if StrLComp( PChar( LowerCase( ItemPtrs[ i ] ) ), PChar( Name ), L ) = 0 then\r
46186       begin\r
46187         Result:=i;\r
46188         exit;\r
46189       end;\r
46190     end;\r
46191   end;\r
46192 end;\r
46194 //-- code by Dod:\r
46195 //[function TStrList.GetValue]\r
46196 function TStrList.GetValue(const Name: string): string;\r
46197 var\r
46198   i: Integer;\r
46199 begin\r
46200   I := IndexOfName(Name);\r
46201   if I >= 0\r
46202   then Result := Copy(Items[i], Length(Name) + 2, Length(Items[i])-Length(Name)-1)\r
46203   else Result := '';\r
46204 end;\r
46206 //-- code by Dod:\r
46207 //[procedure TStrList.SetValue]\r
46208 procedure TStrList.SetValue(const Name, Value: string);\r
46209 var\r
46210   I: Integer;\r
46211 begin\r
46212   I := IndexOfName(Name);\r
46213   if i=-1\r
46214   then Add( Name + fNameDelim + Value )\r
46215   else Items[i] := Name + fNameDelim + Value;\r
46216 end;\r
46218 //[function TStrList.GetLineName]\r
46219 function TStrList.GetLineName(Idx: Integer): string;\r
46220 begin\r
46221   Result := Items[ Idx ];\r
46222   Result := Parse( Result, fNameDelim );\r
46223 end;\r
46225 //[procedure TStrList.SetLineName]\r
46226 procedure TStrList.SetLineName(Idx: Integer; const NV: string);\r
46227 begin\r
46228   Items[ Idx ] := NV + fNameDelim + LineValue[ Idx ];\r
46229 end;\r
46231 //[function TStrList.GetLineValue]\r
46232 function TStrList.GetLineValue(Idx: Integer): string;\r
46233 begin\r
46234   Result := Items[ Idx ];\r
46235   Parse( Result, fNameDelim );\r
46236 end;\r
46238 //[procedure TStrList.SetLineValue]\r
46239 procedure TStrList.SetLineValue(Idx: Integer; const Value: string);\r
46240 begin\r
46241   Items[ Idx ] := LineName[ Idx ] + fNameDelim + Value;\r
46242 end;\r
46244 ////////////////////////////////// EXTENDED STRING LIST OBJECT ////////////////\r
46246 { TStrListEx }\r
46248 //[function NewStrListEx]\r
46249 function NewStrListEx: PStrListEx;\r
46250 begin\r
46251   {-}\r
46252   new( Result, Create );\r
46253   {+}\r
46254   {++}(*\r
46255   Result := PStrListEx.Create;\r
46256   *){--}\r
46257 end;\r
46258 //[END NewStrListEx]\r
46260 //[destructor TStrListEx.Destroy]\r
46261 destructor TStrListEx.Destroy;\r
46262 var Obj: PList;\r
46263 begin\r
46264   Obj := FObjects;\r
46265   inherited;\r
46266   Obj.Free;\r
46267 end;\r
46269 //[function TStrListEx.GetObjects]\r
46270 function TStrListEx.GetObjects(Idx: Integer): DWORD;\r
46271 begin\r
46272   Result := DWORD( FObjects.Items[ Idx ] );\r
46273 end;\r
46275 //[procedure TStrListEx.SetObjects]\r
46276 procedure TStrListEx.SetObjects(Idx: Integer; const Value: DWORD);\r
46277 begin\r
46278   ProvideObjCapacity( Idx + 1 );\r
46279   FObjects.Items[ Idx ] := Pointer( Value );\r
46280 end;\r
46282 //[procedure TStrListEx.Init]\r
46283 procedure TStrListEx.Init;\r
46284 begin\r
46285   FObjects := NewList;\r
46286 end;\r
46288 //[procedure SwapStrListExItems]\r
46289 procedure SwapStrListExItems( const Sender: Pointer; const e1, e2: DWORD );\r
46290 begin\r
46291   PStrListEx( Sender ).Swap( e1, e2 );\r
46292 end;\r
46294 //[procedure TStrListEx.AnsiSort]\r
46295 procedure TStrListEx.AnsiSort(CaseSensitive: Boolean);\r
46296 begin\r
46297   fCaseSensitiveSort := CaseSensitive;\r
46298   SortData( @Self, fCount, @CompareAnsiStrListItems, @SwapStrListExItems );\r
46299 end;\r
46301 //[procedure TStrListEx.Sort]\r
46302 procedure TStrListEx.Sort(CaseSensitive: Boolean);\r
46303 begin\r
46304   fCaseSensitiveSort := CaseSensitive;\r
46305   SortData( @Self, fCount, @CompareStrListItems, @SwapStrListExItems );\r
46306 end;\r
46308 //[procedure TStrListEx.Move]\r
46309 procedure TStrListEx.Move(CurIndex, NewIndex: integer);\r
46310 begin\r
46311   // move string\r
46312   fList.MoveItem( CurIndex, NewIndex );\r
46313   // move object\r
46314   if FObjects.fCount >= Min( CurIndex, NewIndex ) then\r
46315   begin\r
46316     ProvideObjCapacity( max( CurIndex, NewIndex ) + 1 );\r
46317     FObjects.MoveItem( CurIndex, NewIndex );\r
46318   end;\r
46319 end;\r
46321 //[procedure TStrListEx.Swap]\r
46322 procedure TStrListEx.Swap(Idx1, Idx2: Integer);\r
46323 begin\r
46324   // swap strings\r
46325   fList.Swap( Idx1, Idx2 );\r
46326   // swap objects\r
46327   if FObjects.fCount >= Min( Idx1, Idx2 ) then\r
46328   begin\r
46329     ProvideObjCapacity( max( Idx1, Idx2 ) + 1 );\r
46330     FObjects.Swap( Idx1, Idx2 );\r
46331   end;\r
46332 end;\r
46334 //[procedure TStrListEx.ProvideObjCapacity]\r
46335 procedure TStrListEx.ProvideObjCapacity(NewCap: Integer);\r
46336 begin\r
46337   if FObjects.FCount < NewCap then\r
46338   begin\r
46339     FObjects.Capacity := NewCap;\r
46340     FillChar( FObjects.FItems[ FObjects.FCount ],\r
46341               (FObjects.Capacity - FObjects.Count) * sizeof( Pointer ), 0 );\r
46342     FObjects.FCount := NewCap;\r
46343   end;\r
46344 end;\r
46346 //[procedure TStrListEx.AddStrings]\r
46347 procedure TStrListEx.AddStrings(Strings: PStrListEx);\r
46348 var I: Integer;\r
46349 begin\r
46350   I := Count;\r
46351   if Strings.FObjects.fCount > 0 then\r
46352     ProvideObjCapacity( Count );\r
46353   inherited AddStrings( Strings );\r
46354   if Strings.FObjects.fCount > 0 then\r
46355   begin\r
46356     ProvideObjCapacity( I + Strings.FObjects.fCount );\r
46357     System.Move( Strings.FObjects.FItems[ 0 ],\r
46358                  FObjects.FItems[ I ],\r
46359                  Sizeof( Pointer ) * Strings.FObjects.fCount );\r
46360   end;\r
46361 end;\r
46363 //[procedure TStrListEx.Assign]\r
46364 procedure TStrListEx.Assign(Strings: PStrListEx);\r
46365 begin\r
46366   inherited Assign( Strings );\r
46367   FObjects.Assign( Strings.FObjects );\r
46368 end;\r
46370 //[procedure TStrListEx.Clear]\r
46371 procedure TStrListEx.Clear;\r
46372 begin\r
46373   inherited;\r
46374   FObjects.Clear;\r
46375 end;\r
46377 //[procedure TStrListEx.Delete]\r
46378 procedure TStrListEx.Delete(Idx: integer);\r
46379 begin\r
46380   inherited;\r
46381   if FObjects.fCount > Idx then // mdw: '>=' -> '>'\r
46382     FObjects.Delete( Idx );\r
46383 end;\r
46385 //[function TStrListEx.LastObj]\r
46386 function TStrListEx.LastObj: DWORD;\r
46387 begin\r
46388   if Count = 0 then\r
46389     Result := 0\r
46390   else\r
46391     Result := Objects[ Count - 1 ];\r
46392 end;\r
46394 //[function TStrListEx.AddObject]\r
46395 function TStrListEx.AddObject(const S: String; Obj: DWORD): Integer;\r
46396 begin\r
46397   Result := Count;\r
46398   InsertObject( Count, S, Obj );\r
46399 end;\r
46401 //[procedure TStrListEx.InsertObject]\r
46402 procedure TStrListEx.InsertObject(Before: Integer; const S: String; Obj: DWORD);\r
46403 begin\r
46404   Insert( Before, S );\r
46405   FObjects.Insert( Before, Pointer( Obj ) );\r
46406 end;\r
46408 //[function TStrListEx.IndexOfObj]\r
46409 function TStrListEx.IndexOfObj( Obj: Pointer ): Integer;\r
46410 begin\r
46411   Result := FObjects.IndexOf( Obj );\r
46412 end;\r
46414 {-}\r
46415 //[function WStrLen]\r
46416 function WStrLen( W: PWideChar ): Integer;\r
46417 asm\r
46418          XCHG     EDI, EAX\r
46419          XCHG     EDX, EAX\r
46420          OR       ECX, -1\r
46421          XOR      EAX, EAX\r
46422          CMP      EAX, EDI\r
46423          JE       @@exit0\r
46424          REPNE    SCASW\r
46425          DEC      EAX\r
46426          DEC      EAX\r
46427          SUB      EAX, ECX\r
46428 @@exit0:\r
46429          MOV      EDI, EDX\r
46430 end;\r
46432 //[procedure WStrCopy]\r
46433 procedure WStrCopy( Dest, Src: PWideChar );\r
46434 asm\r
46435         PUSH    EDI\r
46436         PUSH    ESI\r
46437         MOV     ESI,EAX\r
46438         MOV     EDI,EDX\r
46439         OR      ECX, -1\r
46440         XOR     EAX, EAX\r
46441         REPNE   SCASW\r
46442         NOT     ECX\r
46443         MOV     EDI,ESI\r
46444         MOV     ESI,EDX\r
46445         REP     MOVSW\r
46446         POP     ESI\r
46447         POP     EDI\r
46448 end;\r
46450 //[function WStrCmp]\r
46451 function WStrCmp( W1, W2: PWideChar ): Integer;\r
46452 asm\r
46453          PUSH     ESI\r
46454          PUSH     EDI\r
46455          XCHG     ESI, EAX\r
46456          MOV      EDI, EDX\r
46457          XOR      EAX, EAX\r
46458          CWDE\r
46459 @@loop:  LODSW\r
46460          MOV      DX, [EDI]\r
46461          INC      EDI\r
46462          INC      EDI\r
46463          CMP      EAX, EDX\r
46464          JNE      @@exit\r
46465          TEST     EAX, EAX\r
46466          JNZ      @@loop\r
46467 @@exit:  SUB      EAX, EDX\r
46468          POP      EDI\r
46469          POP      ESI\r
46470 end;\r
46472 {$IFNDEF _D2}\r
46474 //[function NewWStrList]\r
46475 function NewWStrList: PWStrList;\r
46476 begin\r
46477   new( Result, Create );\r
46478 end;\r
46480 { TWStrList }\r
46482 //[function TWStrList.Add]\r
46483 function TWStrList.Add(const W: WideString): Integer;\r
46484 begin\r
46485   Result := Count;\r
46486   Insert( Result, W );\r
46487 end;\r
46489 //[procedure TWStrList.AddWStrings]\r
46490 procedure TWStrList.AddWStrings(WL: PWStrList);\r
46491 begin\r
46492   Text := Text + WL.Text;\r
46493 end;\r
46495 //[function TWStrList.AppendToFile]\r
46496 function TWStrList.AppendToFile(const Filename: String): Boolean;\r
46497 var Strm: PStream;\r
46498 begin\r
46499   Strm := NewReadWriteFileStream( Filename );\r
46500   Result := Strm.Handle <> INVALID_HANDLE_VALUE;\r
46501   if Result then\r
46502   begin\r
46503     Strm.Position := Strm.Size;\r
46504     SaveToStream( Strm );\r
46505   end;\r
46506   Strm.Free;\r
46507 end;\r
46509 //[procedure TWStrList.Assign]\r
46510 procedure TWStrList.Assign(WL: PWStrList);\r
46511 begin\r
46512   Text := WL.Text;\r
46513 end;\r
46515 //[procedure TWStrList.Clear]\r
46516 procedure TWStrList.Clear;\r
46517 var I: Integer;\r
46518     P: Pointer;\r
46519 begin\r
46520   for I := 0 to Count-1 do\r
46521   begin\r
46522     P := fList.Items[ I ];\r
46523     if P <> nil then\r
46524     if not( (P >= fText) and (P <= fText + fTextBufSz) ) then\r
46525       FreeMem( P );\r
46526   end;\r
46527   if fText <> nil then\r
46528     FreeMem( fText );\r
46529   fText := nil;\r
46530   fTextBufSz := 0;\r
46531   fList.Clear;\r
46532 end;\r
46534 //[procedure TWStrList.Delete]\r
46535 procedure TWStrList.Delete(Idx: Integer);\r
46536 var P: Pointer;\r
46537 begin\r
46538   P := fList.Items[ Idx ];\r
46539   if P <> nil then\r
46540   if not( (P >= fText) and (P <= fText + fTextBufSz) ) then\r
46541     FreeMem( P );\r
46542   fList.Delete( Idx );\r
46543 end;\r
46545 //[destructor TWStrList.Destroy]\r
46546 destructor TWStrList.Destroy;\r
46547 begin\r
46548   Clear;\r
46549   fList.Free;\r
46550   inherited;\r
46551 end;\r
46553 //[function TWStrList.GetCount]\r
46554 function TWStrList.GetCount: Integer;\r
46555 begin\r
46556   Result := fList.Count;\r
46557 end;\r
46559 //[function TWStrList.GetItems]\r
46560 function TWStrList.GetItems(Idx: Integer): WideString;\r
46561 begin\r
46562   Result := PWideChar( fList.Items[ Idx ] );\r
46563 end;\r
46565 //[function TWStrList.GetPtrs]\r
46566 function TWStrList.GetPtrs(Idx: Integer): PWideChar;\r
46567 begin\r
46568   Result := fList.Items[ Idx ];\r
46569 end;\r
46571 //[function TWStrList.GetText]\r
46572 function TWStrList.GetText: WideString;\r
46573 const\r
46574     EoL: array[ 0..5 ] of Char = ( #13, #0, #10, #0, #0, #0 );\r
46575 var L, I: Integer;\r
46576     P, Dest: Pointer;\r
46577 begin\r
46578   L := 0;\r
46579   for I := 0 to Count-1 do\r
46580   begin\r
46581     P := fList.Items[ I ];\r
46582     if P <> nil then\r
46583       L := L + WStrLen( P ) + 2\r
46584     else\r
46585       L := L + 2;\r
46586   end;\r
46587   SetLength( Result, L );\r
46588   Dest := PWideChar( Result );\r
46589   for I := 0 to Count-1 do\r
46590   begin\r
46591     P := fList.Items[ I ];\r
46592     if P <> nil then\r
46593     begin\r
46594       WStrCopy( Dest, P );\r
46595       Dest := Pointer( Integer( Dest ) + WStrLen( P ) * 2 );\r
46596     end;\r
46597     WStrCopy( Dest, Pointer( @ EoL[ 0 ] ) );\r
46598     Dest := Pointer( Integer( Dest ) + 4 );\r
46599   end;\r
46600 end;\r
46602 //[procedure TWStrList.Init]\r
46603 procedure TWStrList.Init;\r
46604 begin\r
46605   fList := NewList;\r
46606 end;\r
46608 //[procedure TWStrList.Insert]\r
46609 procedure TWStrList.Insert(Idx: Integer; const W: WideString);\r
46610 var P: Pointer;\r
46611 begin\r
46612   while Idx < Count-2 do\r
46613     fList.Add( nil );\r
46614   GetMem( P, (Length( W ) + 1) * 2 );\r
46615   fList.Insert( Idx, P );\r
46616   WStrCopy( P, PWideChar( W ) );\r
46617 end;\r
46619 //[function TWStrList.LoadFromFile]\r
46620 function TWStrList.LoadFromFile(const Filename: String): Boolean;\r
46621 begin\r
46622   Clear;\r
46623   Result := MergeFromFile( Filename );\r
46624 end;\r
46626 //[procedure TWStrList.LoadFromStream]\r
46627 procedure TWStrList.LoadFromStream(Strm: PStream);\r
46628 begin\r
46629   Clear;\r
46630   MergeFromStream( Strm );\r
46631 end;\r
46633 //[function TWStrList.MergeFromFile]\r
46634 function TWStrList.MergeFromFile(const Filename: String): Boolean;\r
46635 var Strm: PStream;\r
46636 begin\r
46637   Strm := NewReadFileStream( Filename );\r
46638   Result := Strm.Handle <> INVALID_HANDLE_VALUE;\r
46639   if Result then\r
46640     MergeFromStream( Strm );\r
46641   Strm.Free;\r
46642 end;\r
46644 //[procedure TWStrList.MergeFromStream]\r
46645 procedure TWStrList.MergeFromStream(Strm: PStream);\r
46646 var Buf: WideString;\r
46647     L: Integer;\r
46648 begin\r
46649   L := Strm.Size - Strm.Position;\r
46650   Assert( L mod 1 = 0, 'Wide strings streams must be of even length in bytes.' );\r
46651   if L = 0 then Exit;\r
46652   SetLength( Buf, L div 2 );\r
46653   Strm.Read( Buf[ 1 ], L );\r
46654   Text := Text + Buf;\r
46655 end;\r
46657 //[procedure TWStrList.Move]\r
46658 procedure TWStrList.Move(IdxOld, IdxNew: Integer);\r
46659 begin\r
46660   fList.MoveItem( IdxOld, IdxNew );\r
46661 end;\r
46663 //[function TWStrList.SaveToFile]\r
46664 function TWStrList.SaveToFile(const Filename: String): Boolean;\r
46665 var Strm: PStream;\r
46666 begin\r
46667   Strm := NewWriteFileStream( Filename );\r
46668   Result := Strm.Handle <> INVALID_HANDLE_VALUE;\r
46669   if Result then\r
46670     SaveToStream( Strm );\r
46671   Strm.Free;\r
46672 end;\r
46674 //[procedure TWStrList.SaveToStream]\r
46675 procedure TWStrList.SaveToStream(Strm: PStream);\r
46676 var Buf, Dest: PWideChar;\r
46677     I, L, Sz: Integer;\r
46678     P: Pointer;\r
46679 begin\r
46680   Sz := 0;\r
46681   for I := 0 to Count-1 do\r
46682   begin\r
46683     P := fList.Items[ I ];\r
46684     if P <> nil then\r
46685       Sz := Sz + WStrLen( P ) * 2 + 4\r
46686     else\r
46687       Sz := Sz + 4;\r
46688   end;\r
46689   GetMem( Buf, Sz );\r
46690   Dest := Buf;\r
46691   for I := 0 to Count-1 do\r
46692   begin\r
46693     P := fList.Items[ I ];\r
46694     if P <> nil then\r
46695     begin\r
46696       L := WStrLen( P );\r
46697       System.Move( P^, Dest^, L * 2 );\r
46698       Inc( Dest, L );\r
46699     end;\r
46700     Dest^ := #13;\r
46701     Inc( Dest );\r
46702     Dest^ := #10;\r
46703     Inc( Dest );\r
46704   end;\r
46705   Strm.Write( Buf^, Sz );\r
46706   FreeMem( Buf );\r
46707 end;\r
46709 //[procedure TWStrList.SetItems]\r
46710 procedure TWStrList.SetItems(Idx: Integer; const Value: WideString);\r
46711 var P: Pointer;\r
46712 begin\r
46713   while Idx > Count-1 do\r
46714     fList.Add( nil );\r
46715   if WStrLen( ItemPtrs[ Idx ] ) <= Length( Value ) then\r
46716     WStrCopy( ItemPtrs[ Idx ], PWideChar( Value ) )\r
46717   else\r
46718   begin\r
46719     P := fList.Items[ Idx ];\r
46720     if P <> nil then\r
46721     if not ((P >= fText) and (P <= fText + fTextBufSz)) then\r
46722       FreeMem( P );\r
46723     GetMem( P, (Length( Value ) + 1) * 2 );\r
46724     fList.Items[ Idx ] := P;\r
46725     WStrCopy( P, PWideChar( Value ) );\r
46726   end;\r
46727 end;\r
46729 //[procedure TWStrList.SetText]\r
46730 procedure TWStrList.SetText(const Value: WideString);\r
46731 var L, N: Integer;\r
46732     P: PWideChar;\r
46733 begin\r
46734   Clear;\r
46735   if Value = '' then Exit;\r
46736   L := (Length( Value ) + 1) * 2;\r
46737   GetMem( fText, L );\r
46738   System.Move( Value[ 1 ], fText^, L );\r
46739   fTextBufSz := Length( Value );\r
46740   N := 0;\r
46741   P := fText;\r
46742   while Word( P^ ) <> 0 do\r
46743   begin\r
46744     if (Word( P^ ) = 13) then\r
46745     begin\r
46746       Inc( N );\r
46747       PWord( P )^ := 0;\r
46748       if Word( P[ 1 ] ) = 10 then\r
46749         Inc( P );\r
46750     end\r
46751       else\r
46752     if (Word( P^ ) = 10) and ((P = fText) or (Word( P[ -1 ] ) <> 0)) then\r
46753     begin\r
46754       Inc( N );\r
46755       PWord( P )^ := 0;\r
46756     end;\r
46757     Inc( P );\r
46758   end;\r
46759   fList.Capacity := N;\r
46760   P := fText;\r
46761   while P < fText + fTextBufSz do\r
46762   begin\r
46763     fList.Add( P );\r
46764     while Word( P^ ) <> 0 do Inc( P );\r
46765     Inc( P );\r
46766     if Word( P^ ) = 10 then Inc( P );\r
46767   end;\r
46768 end;\r
46770 //[function CompareWStrListItems]\r
46771 function CompareWStrListItems( const Sender: Pointer; const Idx1, Idx2: DWORD ): Integer;\r
46772 var WL: PWStrList;\r
46773 begin\r
46774   WL := Sender;\r
46775   Result := WStrCmp( WL.fList.Items[ Idx1 ], WL.fList.Items[ Idx2 ] );\r
46776 end;\r
46778 //[function CompareWStrListItems_UpperCase]\r
46779 function CompareWStrListItems_UpperCase( const Sender: Pointer; const Idx1, Idx2: DWORD ): Integer;\r
46780 var WL: PWStrList;\r
46781     L1, L2: Integer;\r
46782 begin\r
46783   WL := Sender;\r
46784   L1 := WStrLen( WL.fList.Items[ Idx1 ] );\r
46785   L2 := WStrLen( WL.fList.Items[ Idx2 ] );\r
46786   if Length( WL.fTmp1 ) < L1 then\r
46787     SetLength( WL.fTmp1, L1 + 1 );\r
46788   if Length( WL.fTmp2 ) < L2 then\r
46789     SetLength( WL.fTmp2, L2 + 1 );\r
46790   if L1 > 0 then\r
46791     Move( WL.fList.Items[ Idx1 ]^, WL.fTmp1[ 1 ], (L1 + 1) * 2 )\r
46792   else\r
46793     WL.fTmp1[ 1 ] := #0;\r
46794   if L2 > 0 then\r
46795     Move( WL.fList.Items[ Idx2 ]^, WL.fTmp2[ 1 ], (L2 + 1) * 2 )\r
46796   else\r
46797     WL.fTmp2[ 1 ] := #0;\r
46798   CharUpperBuffW( PWideChar( WL.fTmp1 ), L1 );\r
46799   CharUpperBuffW( PWideChar( WL.fTmp2 ), L2 );\r
46800   Result := WStrCmp( PWideChar( WL.fTmp1 ), PWideChar( WL.fTmp2 ) );\r
46801 end;\r
46803 //[procedure SwapWStrListItems]\r
46804 procedure SwapWStrListItems( const Sender: Pointer; const Idx1, Idx2: DWORD );\r
46805 var WL: PWStrList;\r
46806 begin\r
46807   WL := Sender;\r
46808   WL.Swap( Idx1, Idx2 );\r
46809 end;\r
46811 //[procedure TWStrList.Sort]\r
46812 procedure TWStrList.Sort( CaseSensitive: Boolean );\r
46813 begin\r
46814   if CaseSensitive then\r
46815     SortData( @ Self, Count, @CompareWStrListItems, @SwapWStrListItems )\r
46816   else\r
46817   begin\r
46818     SortData( @ Self, Count, @CompareWStrListItems_UpperCase, @SwapWStrListItems );\r
46819     fTmp1 := '';\r
46820     fTmp2 := '';\r
46821   end;\r
46822 end;\r
46824 //[procedure TWStrList.Swap]\r
46825 procedure TWStrList.Swap(Idx1, Idx2: Integer);\r
46826 begin\r
46827   fList.Swap( Idx1, Idx2 );\r
46828 end;\r
46830 //[function NewWStrListEx]\r
46831 function NewWStrListEx: PWStrListEx;\r
46832 begin\r
46833   new( Result, Create );\r
46834 end;\r
46836 { TWStrListEx }\r
46838 //[function TWStrListEx.AddObject]\r
46839 function TWStrListEx.AddObject(const S: WideString; Obj: DWORD): Integer;\r
46840 begin\r
46841   Result := Count;\r
46842   InsertObject( Count, S, Obj );\r
46843 end;\r
46845 //[procedure TWStrListEx.AddWStrings]\r
46846 procedure TWStrListEx.AddWStrings(WL: PWStrListEx);\r
46847 var I: Integer;\r
46848 begin\r
46849   I := Count;\r
46850   if WL.FObjects.Count > 0 then\r
46851     ProvideObjectsCapacity( Count );\r
46852   inherited AddWStrings( WL );\r
46853   if WL.FObjects.Count > 0 then\r
46854   begin\r
46855     ProvideObjectsCapacity( I + WL.FObjects.Count );\r
46856     System.Move( WL.FObjects.FItems[ 0 ],\r
46857                  FObjects.FItems[ I ],\r
46858                  Sizeof( Pointer ) * WL.FObjects.Count );\r
46859   end;\r
46860 end;\r
46862 //[procedure TWStrListEx.Assign]\r
46863 procedure TWStrListEx.Assign(WL: PWStrListEx);\r
46864 begin\r
46865   inherited Assign( WL );\r
46866   FObjects.Assign( WL.FObjects );\r
46867 end;\r
46869 //[procedure TWStrListEx.Clear]\r
46870 procedure TWStrListEx.Clear;\r
46871 begin\r
46872   inherited Clear;\r
46873   FObjects.Clear;\r
46874 end;\r
46876 //[procedure TWStrListEx.Delete]\r
46877 procedure TWStrListEx.Delete(Idx: Integer);\r
46878 begin\r
46879   inherited Delete( Idx );\r
46880   if FObjects.FCount >= Idx then\r
46881     FObjects.Delete( Idx );\r
46882 end;\r
46884 //[destructor TWStrListEx.Destroy]\r
46885 destructor TWStrListEx.Destroy;\r
46886 begin\r
46887   fObjects.Free;\r
46888   inherited;\r
46889 end;\r
46891 //[function TWStrListEx.GetObjects]\r
46892 function TWStrListEx.GetObjects(Idx: Integer): DWORD;\r
46893 begin\r
46894   Result := DWORD( fObjects.Items[ Idx ] );\r
46895 end;\r
46897 //[function TWStrListEx.IndexOfObj]\r
46898 function TWStrListEx.IndexOfObj(Obj: Pointer): Integer;\r
46899 begin\r
46900   Result := FObjects.IndexOf( Obj );\r
46901 end;\r
46903 //[procedure TWStrListEx.Init]\r
46904 procedure TWStrListEx.Init;\r
46905 begin\r
46906   inherited;\r
46907   fObjects := NewList;\r
46908 end;\r
46910 //[procedure TWStrListEx.InsertObject]\r
46911 procedure TWStrListEx.InsertObject(Before: Integer; const S: WideString;\r
46912   Obj: DWORD);\r
46913 begin\r
46914   Insert( Before, S );\r
46915   FObjects.Insert( Before, Pointer( Obj ) );\r
46916 end;\r
46918 //[procedure TWStrListEx.Move]\r
46919 procedure TWStrListEx.Move(IdxOld, IdxNew: Integer);\r
46920 begin\r
46921   fList.MoveItem( IdxOld, IdxNew );\r
46922   if FObjects.FCount >= Min( IdxOld, IdxNew ) then\r
46923   begin\r
46924     ProvideObjectsCapacity( Max( IdxOld, IdxNew ) + 1 );\r
46925     FObjects.MoveItem( IdxOld, IdxNew );\r
46926   end;\r
46927 end;\r
46929 //[procedure TWStrListEx.ProvideObjectsCapacity]\r
46930 procedure TWStrListEx.ProvideObjectsCapacity(NewCap: Integer);\r
46931 begin\r
46932   if fObjects.Capacity >= NewCap then Exit;\r
46933   fObjects.Capacity := NewCap;\r
46934   FillChar( FObjects.FItems[ FObjects.FCount ],\r
46935             (FObjects.Capacity - FObjects.Count) * Sizeof( Pointer ), 0 );\r
46936   FObjects.FCount := NewCap;\r
46937 end;\r
46939 //[procedure TWStrListEx.SetObjects]\r
46940 procedure TWStrListEx.SetObjects(Idx: Integer; const Value: DWORD);\r
46941 begin\r
46942   ProvideObjectsCapacity( Idx + 1 );\r
46943   fObjects.Items[ Idx ] := Pointer( Value );\r
46944 end;\r
46946 {$ENDIF}\r
46947 {+}\r
46950 //////////////////////////////////////////////////////////////////////////\r
46951 //\r
46952 //\r
46953 //                            S  O  R  T  I  N  G\r
46954 //\r
46955 //\r
46956 //////////////////////////////////////////////////////////////////////////\r
46958 { -- qsort -- }\r
46960 //[PROCEDURE SortData]\r
46961 {$IFDEF ASM_VERSION} // translated to BASM by Kladov Vladimir\r
46962 procedure SortData( const Data: Pointer; const uNElem: Dword;\r
46963                     const CompareFun: TCompareEvent;\r
46964                     const SwapProc: TSwapEvent );\r
46965 asm\r
46966         CMP      EDX, 2\r
46967         JL       @@exit\r
46969         PUSH     EAX      // [EBP-4] = Data\r
46970         PUSH     ECX      // [EBP-8] = CompareFun\r
46971         PUSH     EBX      // EBX = pivotP\r
46972         XOR      EBX, EBX\r
46973         INC      EBX      // EBX = 1 to pass to qSortHelp as PivotP\r
46974         MOV      EAX, EDX // EAX = nElem\r
46975         CALL     @@qSortHelp\r
46976         POP      EBX\r
46977         POP      ECX\r
46978         POP      ECX\r
46979 @@exit:\r
46980         POP      EBP\r
46981         RET      4\r
46983 @@qSortHelp:\r
46984         PUSH     EBX      // EBX (in) = PivotP\r
46985         PUSH     ESI      // ESI      = leftP\r
46986         PUSH     EDI      // EDI      = rightP\r
46988 @@TailRecursion:\r
46989         CMP      EAX, 2\r
46990         JG       @@2\r
46991         JNE      @@exit_qSortHelp\r
46992         LEA      ECX, [EBX+1]\r
46993         MOV      EDX, EBX\r
46994         CALL     @@Compare\r
46995         JLE      @@exit_qSortHelp\r
46996 @@swp_exit:\r
46997         CALL     @@Swap\r
46998 @@exit_qSortHelp:\r
46999         POP      EDI\r
47000         POP      ESI\r
47001         POP      EBX\r
47002         RET\r
47004         // ESI = leftP\r
47005         // EDI = rightP\r
47006 @@2:    LEA      EDI, [EAX+EBX-1]\r
47007         MOV      ESI, EAX\r
47008         SHR      ESI, 1\r
47009         ADD      ESI, EBX\r
47010         MOV      ECX, ESI\r
47011         MOV      EDX, EDI\r
47012         CALL     @@CompareLeSwap\r
47013         MOV      EDX, EBX\r
47014         CALL     @@Compare\r
47016         JG       @@4\r
47017         CALL     @@Swap\r
47018         JMP      @@5\r
47019 @@4:    MOV      ECX, EBX\r
47020         MOV      EDX, EDI\r
47021         CALL     @@CompareLeSwap\r
47022 @@5:\r
47023         CMP      EAX, 3\r
47024         JNE      @@6\r
47025         MOV      EDX, EBX\r
47026         MOV      ECX, ESI\r
47027         JMP      @@swp_exit\r
47028 @@6:    // classic Horae algorithm\r
47030         PUSH     EAX     // EAX = pivotEnd\r
47031         LEA      EAX, [EBX+1]\r
47032         MOV      ESI, EAX\r
47033 @@repeat:\r
47034         MOV      EDX, ESI\r
47035         MOV      ECX, EBX\r
47036         CALL     @@Compare\r
47037         JG       @@while2\r
47038 @@while1:\r
47039         JNE      @@7\r
47040         MOV      EDX, ESI\r
47041         MOV      ECX, EAX\r
47042         CALL     @@Swap\r
47043         INC      EAX\r
47044 @@7:\r
47045         CMP      ESI, EDI\r
47046         JGE      @@qBreak\r
47047         INC      ESI\r
47048         JMP      @@repeat\r
47049 @@while2:\r
47050         CMP      ESI, EDI\r
47051         JGE      @@until\r
47052         MOV      EDX, EBX\r
47053         MOV      ECX, EDI\r
47054         CALL     @@Compare\r
47055         JGE      @@8\r
47056         DEC      EDI\r
47057         JMP      @@while2\r
47058 @@8:\r
47059         MOV      EDX, ESI\r
47060         MOV      ECX, EDI\r
47061         PUSHFD\r
47062         CALL     @@Swap\r
47063         POPFD\r
47064         JE       @@until\r
47065         INC      ESI\r
47066         DEC      EDI\r
47067 @@until:\r
47068         CMP      ESI, EDI\r
47069         JL       @@repeat\r
47070 @@qBreak:\r
47071         MOV      EDX, ESI\r
47072         MOV      ECX, EBX\r
47073         CALL     @@Compare\r
47074         JG       @@9\r
47075         INC      ESI\r
47076 @@9:\r
47077         PUSH     EBX      // EBX = PivotTemp\r
47078         PUSH     ESI      // ESI = leftTemp\r
47079         DEC      ESI\r
47080 @@while3:\r
47081         CMP      EBX, EAX\r
47082         JGE      @@while3_break\r
47083         CMP      ESI, EAX\r
47084         JL       @@while3_break\r
47085         MOV      EDX, EBX\r
47086         MOV      ECX, ESI\r
47087         CALL     @@Swap\r
47088         INC      EBX\r
47089         DEC      ESI\r
47090         JMP      @@while3\r
47091 @@while3_break:\r
47092         POP      ESI\r
47093         POP      EBX\r
47095         MOV      EDX, EAX\r
47096         POP      EAX     // EAX = nElem\r
47097         PUSH     EDI     // EDI = lNum\r
47098         MOV      EDI, ESI\r
47099         SUB      EDI, EDX\r
47100         ADD      EAX, EBX\r
47101         SUB      EAX, ESI\r
47103         PUSH     EBX\r
47104         PUSH     EAX\r
47105         CMP      EAX, EDI\r
47106         JGE      @@10\r
47108         MOV      EBX, ESI\r
47109         CALL     @@qSortHelp\r
47110         POP      EAX\r
47111         MOV      EAX, EDI\r
47112         POP      EBX\r
47113         JMP      @@11\r
47115 @@10:   MOV      EAX, EDI\r
47116         CALL     @@qSortHelp\r
47117         POP      EAX\r
47118         POP      EBX\r
47119         MOV      EBX, ESI\r
47120 @@11:\r
47121         POP      EDI\r
47122         JMP      @@TailRecursion\r
47124 @@Compare:\r
47125         PUSH     EAX\r
47126         PUSH     EDX\r
47127         PUSH     ECX\r
47128         MOV      EAX, [EBP-4]\r
47129         DEC      EDX\r
47130         DEC      ECX\r
47131         CALL     dword ptr [EBP-8]\r
47132         POP      ECX\r
47133         POP      EDX\r
47134         TEST     EAX, EAX\r
47135         POP      EAX\r
47136         RET\r
47138 @@CompareLeSwap:\r
47139         CALL     @@Compare\r
47140         JG       @@ret\r
47142 @@Swap: PUSH     EAX\r
47143         PUSH     EDX\r
47144         PUSH     ECX\r
47145         MOV      EAX, [EBP-4]\r
47146         DEC      EDX\r
47147         DEC      ECX\r
47148         CALL     dword ptr [SwapProc]\r
47149         POP      ECX\r
47150         POP      EDX\r
47151         TEST     EAX, EAX\r
47152         POP      EAX\r
47153 @@ret:\r
47154         RET\r
47156 end;\r
47157 {$ELSE ASM_VERSION} //Pascal\r
47158 procedure SortData( const Data: Pointer; const uNElem: Dword;\r
47159                     const CompareFun: TCompareEvent;\r
47160                     const SwapProc: TSwapEvent );\r
47161 { uNElem - number of elements to sort }\r
47163   function Compare( const e1, e2 : DWord ) : Integer;\r
47164   begin\r
47165     Result := CompareFun( Data, e1 - 1, e2 - 1 );\r
47166   end;\r
47168   procedure Swap( const e1, e2 : DWord );\r
47169   begin\r
47170     SwapProc( Data, e1 - 1, e2 - 1 );\r
47171   end;\r
47173   procedure qSortHelp(pivotP: Dword; nElem: Dword);\r
47174   label\r
47175     TailRecursion,\r
47176     qBreak;\r
47177   var\r
47178     leftP, rightP, pivotEnd, pivotTemp, leftTemp: Dword;\r
47179     lNum: Dword;\r
47180     retval: integer;\r
47181   begin\r
47182     TailRecursion:\r
47183       if (nElem <= 2) then\r
47184       begin\r
47185         if (nElem = 2) then\r
47186           begin\r
47187             rightP := pivotP +1;\r
47188             retval := Compare(pivotP,rightP);\r
47189             if (retval > 0) then Swap(pivotP,rightP);\r
47190           end;\r
47191         exit;\r
47192       end;\r
47193       rightP := (nElem -1) + pivotP;\r
47194       leftP :=  (nElem shr 1) + pivotP;\r
47195       { sort pivot, left, and right elements for "median of 3" }\r
47196       retval := Compare(leftP,rightP);\r
47197       if (retval > 0) then Swap(leftP, rightP);\r
47198       retval := Compare(leftP,pivotP);\r
47200       if (retval > 0) then\r
47201         Swap(leftP, pivotP)\r
47202       else\r
47203       begin\r
47204         retval := Compare(pivotP,rightP);\r
47205         if retval > 0 then Swap(pivotP, rightP);\r
47206       end;\r
47207       if (nElem = 3) then\r
47208       begin\r
47209         Swap(pivotP, leftP);\r
47210         exit;\r
47211       end;\r
47212       { now for the classic Horae algorithm }\r
47213       pivotEnd := pivotP + 1;\r
47214       leftP := pivotEnd;\r
47215       repeat\r
47217         retval := Compare(leftP, pivotP);\r
47218         while (retval <= 0) do\r
47219           begin\r
47221             if (retval = 0) then\r
47222               begin\r
47223                 Swap(leftP, pivotEnd);\r
47224                 Inc(pivotEnd);\r
47225               end;\r
47226             if (leftP < rightP) then\r
47227               Inc(leftP)\r
47228             else\r
47229               goto qBreak;\r
47230             retval := Compare(leftP, pivotP);\r
47231           end; {while}\r
47232         while (leftP < rightP) do\r
47233           begin\r
47234             retval := Compare(pivotP, rightP);\r
47235             if (retval < 0) then\r
47236               Dec(rightP)\r
47238             else\r
47239               begin\r
47240                 Swap(leftP, rightP);\r
47241                 if (retval <> 0) then\r
47242                   begin\r
47243                     Inc(leftP);\r
47244                     Dec(rightP);\r
47245                   end;\r
47246                 break;\r
47247               end;\r
47248           end; {while}\r
47250       until (leftP >= rightP);\r
47251     qBreak:\r
47252       retval := Compare(leftP,pivotP);\r
47253       if (retval <= 0) then Inc(leftP);\r
47255       leftTemp := leftP -1;\r
47256       pivotTemp := pivotP;\r
47257       while ((pivotTemp < pivotEnd) and (leftTemp >= pivotEnd)) do\r
47258       begin\r
47259         Swap(pivotTemp, leftTemp);\r
47260         Inc(pivotTemp);\r
47261         Dec(leftTemp);\r
47262       end; {while}\r
47263       lNum := (leftP - pivotEnd);\r
47264       nElem := ((nElem + pivotP) -leftP);\r
47266       if (nElem < lNum) then\r
47267       begin\r
47268         qSortHelp(leftP, nElem);\r
47269         nElem := lNum;\r
47270       end\r
47271         else\r
47272       begin\r
47273         qSortHelp(pivotP, lNum);\r
47274         pivotP := leftP;\r
47275       end;\r
47276       goto TailRecursion;\r
47277     end; {qSortHelp }\r
47279 begin\r
47280   if (uNElem < 2) then  exit; { nothing to sort }\r
47281   qSortHelp(1, uNElem);\r
47282 end;\r
47283 {$ENDIF ASM_VERSION}\r
47284 //[END SortData]\r
47286 //[FUNCTION CompareIntegers]\r
47287 {$IFDEF ASM_VERSION}\r
47288 function CompareIntegers( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;\r
47289 asm\r
47290         MOV      EDX, [EAX+EDX*4]\r
47291         SUB      EDX, [EAX+ECX*4]\r
47292         XCHG     EAX, EDX\r
47293 end;\r
47294 {$ELSE ASM_VERSION} //Pascal\r
47295 function CompareIntegers( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;\r
47296 var I1, I2 : Integer;\r
47297 begin\r
47298   I1 := PInteger( DWORD( Sender ) + e1 * Sizeof( Integer ) )^;\r
47299   I2 := PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;\r
47300   Result := 0;\r
47301   if I1 < I2 then Result := -1\r
47302   else\r
47303   if I1 > I2 then Result := 1;\r
47304 end;\r
47305 {$ENDIF ASM_VERSION}\r
47306 //[END CompareIntegers]\r
47308 //[FUNCTION CompareDwords]\r
47309 {$IFDEF ASM_VERSION}\r
47310 function CompareDwords( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;\r
47311 asm\r
47312         MOV      EDX, [EAX+EDX*4]\r
47313         SUB      EDX, [EAX+ECX*4]\r
47314         XCHG     EAX, EDX\r
47315         JNB      @@1\r
47316         SBB      EAX, EAX\r
47317 @@1:\r
47318 end;\r
47319 {$ELSE ASM_VERSION} //Pascal\r
47320 function CompareDwords( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;\r
47321 var I1, I2 : DWord;\r
47322 begin\r
47323   I1 := PDWORD( DWORD( Sender ) + e1 * Sizeof( Integer ) )^;\r
47324   I2 := PDWORD( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;\r
47325   Result := 0;\r
47326   if I1 < I2 then Result := -1\r
47327   else\r
47328   if I1 > I2 then Result := 1;\r
47329 end;\r
47330 {$ENDIF ASM_VERSION}\r
47331 //[END CompareDwords]\r
47333 //[PROCEDURE SwapIntegers]\r
47334 {$IFDEF ASM_VERSION}\r
47335 procedure SwapIntegers( const Sender : Pointer; const e1, e2 : DWORD );\r
47336 asm\r
47337         LEA      EDX, [EAX+EDX*4]\r
47338         LEA      ECX, [EAX+ECX*4]\r
47339         MOV      EAX, [EDX]\r
47340         XCHG     EAX, [ECX]\r
47341         MOV      [EDX], EAX\r
47342 end;\r
47343 {$ELSE ASM_VERSION} //Pascal\r
47344 procedure SwapIntegers( const Sender : Pointer; const e1, e2 : DWORD );\r
47345 var Tmp : Integer;\r
47346 begin\r
47347   Tmp := PInteger( DWORD( Sender ) + e1 * SizeOf( Integer ) )^;\r
47348   PInteger( DWORD( Sender ) + e1 * Sizeof( Integer ) )^ :=\r
47349   PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;\r
47350   PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^ := Tmp;\r
47351 end;\r
47352 {$ENDIF ASM_VERSION}\r
47353 //[END SwapIntegers]\r
47355 //[procedure SortIntegerArray]\r
47356 procedure SortIntegerArray( var A : array of Integer );\r
47357 begin\r
47358   SortData( @A[ 0 ], High( A ) - Low( A ) + 1, @CompareIntegers, @SwapIntegers );\r
47359 end;\r
47361 //[procedure SortDwordArray]\r
47362 procedure SortDwordArray( var A : array of DWORD );\r
47363 begin\r
47364   SortData( @A[ 0 ], High( A ) - Low( A ) + 1, @CompareDwords, @SwapIntegers );\r
47365 end;\r
47368 { -- status bar implementation -- }\r
47370 //[FUNCTION _NewStatusbar]\r
47371 {$IFDEF ASM_VERSION}\r
47372 function _NewStatusbar( AParent: PControl ): PControl;\r
47373 const STAT_CLS_NAM: PChar = STATUSCLASSNAME;\r
47374 asm\r
47375         PUSH     0\r
47376         PUSH     0\r
47377         //PUSH     EAX\r
47378         //CALL     TControl.GetCanResize\r
47379         CMP      [EAX].TControl.fSizeGrip, 0\r
47380         MOV      ECX, WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or 3 or WS_VISIBLE\r
47381         //MOV      CH, AL  // SBARS_SIZEGRIP =     $0100\r
47382         JZ       @@1\r
47383         //SETNZ    CH\r
47384         INC      CH\r
47385         AND      CL, not 3\r
47386 @@1:\r
47387         //POP      EAX\r
47388         MOV      EDX, [STAT_CLS_NAM]\r
47389         CALL     _NewCommonControl\r
47390         PUSH     EBX\r
47391         XCHG     EBX, EAX\r
47392         PUSH     EDI\r
47393         LEA      EDI, [EBX].TControl.fBoundsRect\r
47394         XOR      EAX, EAX\r
47395         STOSD\r
47396         STOSD\r
47397         STOSD\r
47398         STOSD\r
47399         MOV      [EBX].TControl.fAlign, caBottom\r
47400         INC      [EBX].TControl.fNotUseAlign\r
47401         POP      EDI\r
47402         MOV      EAX, EBX\r
47403         CALL     InitCommonControlSizeNotify\r
47404         XCHG     EAX, EBX\r
47405         POP      EBX\r
47406 end;\r
47407 {$ELSE ASM_VERSION} //Pascal\r
47408 function _NewStatusbar( AParent: PControl ): PControl;\r
47409 var Style: DWORD;\r
47410     //R: TRect;\r
47411 begin\r
47412   Style := WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or 3 or WS_VISIBLE;\r
47413   {if AParent.CanResize then\r
47414      Style := Style or SBARS_SIZEGRIP;}\r
47415   if AParent.fSizeGrip then\r
47416      Style := (Style or SBARS_SIZEGRIP) and not 3;\r
47417   Result := _NewCommonControl( AParent, STATUSCLASSNAME,\r
47418             Style, FALSE, nil  );\r
47420   with Result.fBoundsRect do\r
47421   begin\r
47422     Left := 0;\r
47423     Right := 0;\r
47424     Top := 0;\r
47425     Bottom := 0;\r
47426   end;\r
47427   Result.fAlign := caBottom;\r
47428   Result.fNotUseAlign := True;\r
47429   {$IFDEF TEST_VERSION}\r
47430   Result.fTag := DWORD( PChar( 'Status bar' ) );\r
47431   {$ENDIF}\r
47432   InitCommonControlSizeNotify( Result );\r
47433   //R := AParent.ClientRect;\r
47434   //AParent.Perform( WM_SIZING, WMSZ_TOPLEFT, Integer( @ R ) );\r
47435   //Result.AttachProc( WndProcEraseBkgnd );\r
47436 end;\r
47437 {$ENDIF ASM_VERSION}\r
47438 //[END _NewStatusbar]\r
47440 {$IFDEF ASM_VERSION}\r
47441 //[procedure TControl.SetStatusText]\r
47442 procedure TControl.SetStatusText(Index: Integer; Value: PChar);\r
47443 asm\r
47444         PUSHAD\r
47445         MOV      EBX, EDX // EBX = Index\r
47446         MOV      ESI, EAX // ESI = @Self\r
47448         PUSH     Value // prepare value for call at the end of procedure\r
47449         PUSH     EBX   // prepare Index for call at the end of procedure\r
47451         MOV      ECX, [ESI].fStatusCtl\r
47452         INC      ECX\r
47453         LOOP     @@status_created\r
47455         CALL     GetClientHeight\r
47456         PUSH     EAX // ch = old client height\r
47458         MOV      EAX, ESI\r
47459         CALL     _NewStatusBar\r
47460         MOV      [ESI].fStatusCtl, EAX\r
47461         PUSH     EAX //-----------v\r
47463         CALL     TControl.GetWindowHandle\r
47464         MOV      [ESI].fStatusWnd, EAX\r
47465         XCHG     EDI, EAX\r
47466         POP      EAX //-----------^\r
47468         XOR      EDX, EDX\r
47469         PUSH     EDX\r
47470         INC      DH\r
47471         DEC      EDX\r
47472         CMP      EBX, EDX\r
47473         SETZ     DL\r
47474         NEG      EDX\r
47476 @@1:    PUSH     EDX\r
47477         PUSH     SB_SIMPLE\r
47479         PUSH     EAX\r
47480         CALL     TControl.Perform\r
47482         ADD      ESP, -16\r
47483         PUSH     ESP\r
47484         PUSH     [ESI].fStatusWnd\r
47485         CALL     GetWindowRect\r
47486         POP      EAX\r
47487         POP      EDX\r
47488         POP      EAX\r
47489         POP      EAX\r
47490         SUB      EAX, EDX\r
47491         MOV      [ESI].fClientBottom, EAX\r
47493         POP      EDX // ch\r
47495         PUSH     0\r
47496         PUSH     0\r
47497         PUSH     WM_SIZE\r
47498         PUSH     EDI\r
47500         MOV      EAX, ESI\r
47501         CALL     TControl.SetClientHeight\r
47503         CALL     SendMessage\r
47505 @@status_created:\r
47506         CMP      EBX, 255\r
47507         JGE      @@not_simple\r
47509         PUSH     0\r
47510         PUSH     0\r
47511         PUSH     SB_GETPARTS\r
47512         PUSH     [ESI].fStatusWnd\r
47513         CALL     SendMessage\r
47515         CMP      EAX, EBX\r
47516         JG       @@reset_simple\r
47518         MOV      EAX, ESI\r
47519         CALL     GetWidth\r
47520         CDQ\r
47521         MOV      ECX, EBX\r
47522         INC      ECX\r
47523         IDIV     ECX\r
47524         MOV      EDX, EAX\r
47526         ADD      ESP, -1024\r
47527         MOV      ECX, EBX\r
47528         MOV      EDI, ESP\r
47529         JECXZ    @@2\r
47531 @@store_loo:\r
47532         STOSD\r
47533         ADD      EAX, EDX\r
47534         LOOP     @@store_loo\r
47535 @@2:\r
47536         OR       dword ptr [ESP+EBX*4], -1\r
47537         PUSH     ESP\r
47538         INC      EBX\r
47539         PUSH     EBX\r
47540         PUSH     SB_SETPARTS\r
47541         PUSH     [ESI].fStatusWnd\r
47542         CALL     SendMessage\r
47543         ADD      ESP, 1024\r
47545 @@reset_simple:\r
47546         PUSH     0\r
47547         PUSH     0\r
47548         PUSH     SB_SIMPLE\r
47549         PUSH     [ESI].fStatusWnd\r
47550         CALL     SendMessage\r
47552 @@not_simple:\r
47553         PUSH     SB_SETTEXT\r
47554         PUSH     [ESI].fStatusWnd\r
47555         CALL     SendMessage\r
47556         POPAD\r
47557 end;\r
47558 {$ELSE ASM_VERSION} //Pascal\r
47559 procedure TControl.SetStatusText(Index: Integer; Value: PChar);\r
47560 var ch: Integer;\r
47561     R : TRect;\r
47562     N, I, L, W : Integer;\r
47563     WidthsBuf: array[ 0..254 ] of Integer;\r
47564 begin\r
47565   if fStatusCtl = nil then\r
47566   begin\r
47567     ch := GetClientHeight;\r
47568     fStatusCtl := _NewStatusBar( @Self );\r
47569     fStatusWnd := fStatusCtl.GetWindowHandle;\r
47570     fStatusCtl.Perform( SB_SIMPLE, Integer( LongBool( Index = 255 ) ), 0 );\r
47571     GetWindowRect( fStatusWnd, R );\r
47572     fClientBottom := R.Bottom - R.Top;\r
47573     SetClientHeight( ch );\r
47574     SendMessage( fStatusWnd, WM_SIZE, 0, 0 );\r
47575   end;\r
47576   if Index < 255 then\r
47577   begin\r
47578     N := SendMessage( fStatusWnd, SB_GETPARTS, 0, 0 );\r
47579     if N <= Index then\r
47580     begin\r
47581       W := Width;\r
47582       L := W div (Index + 1);\r
47583       W := L;\r
47584       for I := 0 to Index - 1 do\r
47585       begin\r
47586         WidthsBuf[ I ] := W;\r
47587         Inc( W, L );\r
47588       end;\r
47589       WidthsBuf[ Index ] := -1;\r
47590       SendMessage( fStatusWnd, SB_SETPARTS, Index + 1, Integer( @WidthsBuf[ 0 ] ) );\r
47591     end;\r
47592     SendMessage( fStatusWnd, SB_SIMPLE, 0, 0 );\r
47593   end;\r
47594   SendMessage( fStatusWnd, SB_SETTEXT, Index, Integer( Value ) );\r
47595 end;\r
47596 {$ENDIF ASM_VERSION}\r
47598 {$IFDEF ASM_VERSION}\r
47599 //[function TControl.GetStatusText]\r
47600 function TControl.GetStatusText( Index: Integer ): PChar;\r
47601 asm\r
47602         MOV      ECX, [EAX].fStatusWnd\r
47603         JECXZ    @@exit\r
47605         PUSH     EBX\r
47606         PUSH     ESI\r
47607         XCHG     ESI, EAX // ESI = @Self\r
47608         MOV      EBX, EDX // EBX = Index\r
47610         XOR      EAX, EAX\r
47611         XCHG     EAX, [ESI].fStatusTxt\r
47612         TEST     EAX, EAX\r
47613         JZ       @@1\r
47614         CALL     System.@FreeMem\r
47615 @@1:\r
47616         XOR      EAX, EAX\r
47617         CDQ\r
47618         MOV      DL, WM_GETTEXTLENGTH\r
47619           PUSH     WM_GETTEXT\r
47620         CMP      EBX, 255\r
47621         JZ       @@2\r
47622           POP      EAX\r
47623         MOV      EAX, EBX\r
47624         MOV      DX, SB_GETTEXTLENGTH\r
47625           PUSH     SB_GETTEXT\r
47626 @@2:\r
47627         MOV      EBX, EAX\r
47629         PUSH     0\r
47630         PUSH     EAX\r
47631         PUSH     EDX\r
47632         PUSH     [ESI].fStatusWnd\r
47633         CALL     SendMessage\r
47634         TEST     AX, AX\r
47635         JZ       @@get_rslt\r
47637         PUSH     EAX\r
47638         INC      EAX\r
47639         CALL     System.@GetMem\r
47640         POP      EDX\r
47641         MOV      [ESI].fStatusTxt, EAX\r
47642         MOV      byte ptr [EAX+EDX], 0\r
47644         POP      EDX // Msg\r
47645         PUSH     EAX\r
47646         PUSH     EBX\r
47647         PUSH     EDX\r
47648         PUSH     [ESI].fStatusWnd\r
47649         CALL     SendMessage\r
47650           PUSH     EDX\r
47651 @@get_rslt:\r
47652           POP      EDX\r
47653         MOV      ECX, [ESI].fStatusTxt\r
47654         POP      ESI\r
47655         POP      EBX\r
47657 @@exit: XCHG     EAX, ECX\r
47658 end;\r
47659 {$ELSE ASM_VERSION} //Pascal\r
47660 function TControl.GetStatusText( Index: Integer ): PChar;\r
47661 var L, I: Integer;\r
47662     Msg: DWORD;\r
47663 begin\r
47664   Result := nil;\r
47665   if fStatusWnd = 0 then Exit;\r
47666   if fStatusTxt <> nil then\r
47667      FreeMem( fStatusTxt );\r
47668   fStatusTxt := nil;\r
47669   Msg := SB_GETTEXTLENGTH;\r
47670   I := Index;\r
47671   if Index = 255 then\r
47672   begin\r
47673      Msg := WM_GETTEXTLENGTH;\r
47674      I := 0;\r
47675   end;\r
47676   L := SendMessage( fStatusWnd, Msg, I, 0 ) and $FFFF;\r
47677   if L > 0 then\r
47678   begin\r
47679     GetMem( fStatusTxt, L + 1 );\r
47680     fStatusTxt[ L ] := #0;\r
47681     Msg := SB_GETTEXT;\r
47682     if Index = 255 then\r
47683       Msg := WM_GETTEXT;\r
47684     SendMessage( fStatusWnd, Msg, I, Integer( fStatusTxt ) );\r
47685   end;\r
47686   Result := fStatusTxt;\r
47687 end;\r
47688 {$ENDIF ASM_VERSION}\r
47690 {$IFDEF ASM_VERSION}\r
47691 //[procedure TControl.RemoveStatus]\r
47692 procedure TControl.RemoveStatus;\r
47693 asm\r
47694         MOV      ECX, [EAX].fStatusCtl\r
47695         JECXZ    @@exit\r
47696         PUSH     EBX\r
47697         MOV      EBX, EAX\r
47698         CALL     GetClientHeight\r
47699         PUSH     EAX\r
47700         CDQ\r
47701         MOV      [EBX].fStatusWnd, EDX\r
47702         XCHG     EAX, EDX\r
47703         XCHG     [EBX].fStatusCtl, EAX\r
47704         CALL     TControl.Free\r
47705         POP      EAX\r
47706         CDQ\r
47707         MOV      [EBX].fClientBottom, EDX\r
47708         XCHG     EDX, EAX\r
47709         XCHG     EAX, EBX\r
47710         POP      EBX\r
47711         CALL     SetClientHeight\r
47712 @@exit:\r
47713 end;\r
47714 {$ELSE ASM_VERSION} //Pascal\r
47715 procedure TControl.RemoveStatus;\r
47716 var ch: Integer;\r
47717 begin\r
47718   if fStatusCtl = nil then Exit;\r
47719   ch := ClientHeight;\r
47720   fStatusWnd := 0;\r
47721   fStatusCtl.Free;\r
47722   fStatusCtl := nil;\r
47723   fClientBottom := 0;\r
47724   ClientHeight := ch;\r
47725 end;\r
47726 {$ENDIF ASM_VERSION}\r
47728 {$IFDEF ASM_VERSION}\r
47729 //[function TControl.StatusPanelCount]\r
47730 function TControl.StatusPanelCount: Integer;\r
47731 asm\r
47732         MOV      EAX, [EAX].fStatusWnd\r
47733         TEST     EAX, EAX\r
47734         JZ       @@exit\r
47735         PUSH     0\r
47736         PUSH     0\r
47737         PUSH     SB_GETPARTS\r
47738         PUSH     EAX\r
47739         CALL     SendMessage\r
47740 @@exit:\r
47741 end;\r
47742 {$ELSE ASM_VERSION} //Pascal\r
47743 function TControl.StatusPanelCount: Integer;\r
47744 begin\r
47745   Result := 0;\r
47746   if fStatusWnd = 0 then Exit;\r
47747   Result := SendMessage( fStatusWnd, SB_GETPARTS, 0, 0 );\r
47748 end;\r
47749 {$ENDIF ASM_VERSION}\r
47751 {$IFDEF ASM_VERSION}\r
47752 //[function TControl.GetStatusPanelX]\r
47753 function TControl.GetStatusPanelX(Idx: Integer): Integer;\r
47754 asm\r
47755         MOV      ECX, [EAX].fStatusWnd\r
47756         JECXZ    @@exit\r
47757         PUSH     EBX\r
47758         MOV      EBX, EDX\r
47759         ADD      ESP, -1024\r
47760         PUSH     ESP\r
47761         XOR      EDX, EDX\r
47762         DEC      DL\r
47763         PUSH     EDX\r
47764         MOV      DX, SB_GETPARTS\r
47765         PUSH     EDX\r
47766         PUSH     ECX\r
47767         CALL     SendMessage\r
47768         CMP      EAX, EBX\r
47769         MOV      ECX, [ESP+EBX*4]\r
47770         JG       @@1\r
47771         XOR      ECX, ECX\r
47772 @@1:    ADD      ESP, 1024\r
47773         POP      EBX\r
47774 @@exit:\r
47775         XCHG     EAX, ECX\r
47776 end;\r
47777 {$ELSE ASM_VERSION} //Pascal\r
47778 function TControl.GetStatusPanelX(Idx: Integer): Integer;\r
47779 var Buf: array[0..254] of Integer;\r
47780     N : Integer;\r
47781 begin\r
47782   Result := 0;\r
47783   if fStatusWnd = 0 then Exit;\r
47784   N := SendMessage( fStatusWnd, SB_GETPARTS, 255, Integer( @Buf[ 0 ] ) );\r
47785   if N <= Idx then Exit;\r
47786   Result := Buf[ Idx ];\r
47787 end;\r
47788 {$ENDIF ASM_VERSION}\r
47790 {$IFDEF ASM_VERSION}\r
47791 //[procedure TControl.SetStatusPanelX]\r
47792 procedure TControl.SetStatusPanelX(Idx: Integer; const Value: Integer);\r
47793 asm\r
47794         ADD      ESP, -1024\r
47795         MOV      EAX, [EAX].fStatusWnd\r
47796         TEST     EAX, EAX\r
47797         JZ       @@exit\r
47799         PUSH     ESP\r
47800         PUSH     EDX\r
47801         PUSH     SB_SETPARTS\r
47802         PUSH     EAX\r
47804         PUSH     EDX\r
47805         PUSH     ECX\r
47807         LEA      EDX, [ESP+24]\r
47808         PUSH     EDX\r
47809         PUSH     255\r
47810         PUSH     SB_GETPARTS\r
47811         PUSH     EAX\r
47812         CALL     SendMessage\r
47814         POP      ECX\r
47815         POP      EDX\r
47816         CMP      EAX, EDX\r
47817         JG       @@1\r
47818         ADD      ESP, 16\r
47819         JMP      @@exit\r
47821 @@1:    MOV      [ESP+8], EAX\r
47822         MOV      [ESP+16+EDX*4], ECX\r
47823         CALL     SendMessage\r
47825 @@exit: ADD      ESP, 1024\r
47826 end;\r
47827 {$ELSE ASM_VERSION} //Pascal\r
47828 procedure TControl.SetStatusPanelX(Idx: Integer; const Value: Integer);\r
47829 var Buf: array[0..254] of Integer;\r
47830     N : Integer;\r
47831 begin\r
47832   if fStatusWnd = 0 then Exit;\r
47833   N := SendMessage( fStatusWnd, SB_GETPARTS, 255, Integer( @Buf[ 0 ] ) );\r
47834   if N <= Idx then Exit;\r
47835   Buf[ Idx ] := Value;\r
47836   SendMessage( fStatusWnd, SB_SETPARTS, N, Integer( @Buf[ 0 ] ) );\r
47837 end;\r
47838 {$ENDIF ASM_VERSION}\r
47840 //[procedure TControl.SetColor1]\r
47841 procedure TControl.SetColor1(const Value: TColor);\r
47842 begin\r
47843   fColor1 := Value;\r
47844   Invalidate;\r
47845 end;\r
47847 //[procedure TControl.SetColor2]\r
47848 procedure TControl.SetColor2(const Value: TColor);\r
47849 begin\r
47850   fColor2 := Value;\r
47851   Invalidate;\r
47852 end;\r
47854 //[procedure TControl.SetGradientLayout]\r
47855 procedure TControl.SetGradientLayout(const Value: TGradientLayout);\r
47856 begin\r
47857   FGradientLayout := Value;\r
47858   Invalidate;\r
47859 end;\r
47861 //[procedure TControl.SetGradientStyle]\r
47862 procedure TControl.SetGradientStyle(const Value: TGradientStyle);\r
47863 begin\r
47864   FGradientStyle := Value;\r
47865   Invalidate;\r
47866 end;\r
47879 { -- Image List -- }\r
47881 //*\r
47882 {$IFDEF USE_CONSTRUCTORS}\r
47883 //[function NewImageList]\r
47884 function NewImageList( AOwner: PControl ): PImageList;\r
47885 begin\r
47886   new( Result, CreateImageList( AOwner ) );\r
47887 end;\r
47888 //[END NewImageList]\r
47889 {$ELSE not_USE_CONSTRUCTORS}\r
47890 //[function NewImageList]\r
47891 function NewImageList( AOwner: PControl ): PImageList;\r
47892 begin\r
47893   {*************} DoInitCommonControls( ICC_WIN95_CLASSES );\r
47894   {-}\r
47895   New( Result, Create );\r
47896   {+}\r
47897   {++}(*Result := TImageList.Create;*){--}\r
47898   Result.FAllocBy := 1;\r
47899   Result.FMasked := True;\r
47900   if AOwner = nil then exit;\r
47902   Result.FControl := AOwner;\r
47903   Result.fNext := PImageList( AOwner.fImageList );\r
47904   if AOwner.fImageList <> nil then\r
47905      PImageList( AOwner.fImageList ).fPrev := Result;\r
47906   Result.fBkColor := clNone;\r
47907   //ImageList_SetBkColor( Result.FHandle, CLR_NONE );\r
47908   AOwner.fImageList := Result;\r
47909   Result.FImgWidth := 32;\r
47910   Result.FImgHeight := 32;\r
47911   Result.FColors := ilcDefault;\r
47912 end;\r
47913 {$ENDIF}\r
47915 //[API ImageList_XXX]\r
47916 function ImageList_Create; stdcall; external cctrl name 'ImageList_Create';\r
47917 function ImageList_Destroy; external cctrl name 'ImageList_Destroy';\r
47918 function ImageList_GetImageCount; external cctrl name 'ImageList_GetImageCount';\r
47919 function ImageList_SetImageCount; external cctrl name 'ImageList_SetImageCount';\r
47920 function ImageList_Add; external cctrl name 'ImageList_Add';\r
47921 function ImageList_ReplaceIcon; external cctrl name 'ImageList_ReplaceIcon';\r
47922 function ImageList_SetBkColor; external cctrl name 'ImageList_SetBkColor';\r
47923 function ImageList_GetBkColor; external cctrl name 'ImageList_GetBkColor';\r
47924 function ImageList_SetOverlayImage; external cctrl name 'ImageList_SetOverlayImage';\r
47925 function ImageList_Draw; external cctrl name 'ImageList_Draw';\r
47926 function ImageList_Replace; external cctrl name 'ImageList_Replace';\r
47927 function ImageList_AddMasked; external cctrl name 'ImageList_AddMasked';\r
47928 function ImageList_DrawEx; external cctrl name 'ImageList_DrawEx';\r
47929 function ImageList_Remove; external cctrl name 'ImageList_Remove';\r
47930 function ImageList_GetIcon; external cctrl name 'ImageList_GetIcon';\r
47931 function ImageList_LoadImageA; external cctrl name 'ImageList_LoadImageA';\r
47932 function ImageList_LoadImageW; external cctrl name 'ImageList_LoadImageW';\r
47933 function ImageList_LoadImage; external cctrl name 'ImageList_LoadImageA';\r
47934 function ImageList_BeginDrag; external cctrl name 'ImageList_BeginDrag';\r
47935 function ImageList_EndDrag; external cctrl name 'ImageList_EndDrag';\r
47936 function ImageList_DragEnter; external cctrl name 'ImageList_DragEnter';\r
47937 function ImageList_DragLeave; external cctrl name 'ImageList_DragLeave';\r
47938 function ImageList_DragMove; external cctrl name 'ImageList_DragMove';\r
47939 function ImageList_SetDragCursorImage; external cctrl name 'ImageList_SetDragCursorImage';\r
47940 function ImageList_DragShowNolock; external cctrl name 'ImageList_DragShowNolock';\r
47941 function ImageList_GetDragImage; external cctrl name 'ImageList_GetDragImage';\r
47942 //function ImageList_Read; external cctrl name 'ImageList_Read';\r
47943 //function ImageList_Write; external cctrl name 'ImageList_Write';\r
47944 function ImageList_GetIconSize; external cctrl name 'ImageList_GetIconSize';\r
47945 function ImageList_SetIconSize; external cctrl name 'ImageList_SetIconSize';\r
47946 function ImageList_GetImageInfo; external cctrl name 'ImageList_GetImageInfo';\r
47947 function ImageList_Merge; external cctrl name 'ImageList_Merge';\r
47949 //[function ImageList_AddIcon]\r
47950 function ImageList_AddIcon(ImageList: HImageList; Icon: HIcon): Integer;\r
47951 begin\r
47952   Result := ImageList_ReplaceIcon(ImageList, -1, Icon);\r
47953 end;\r
47955 //[function Index2OverlayMask]\r
47956 function Index2OverlayMask(Index: Integer): Integer;\r
47957 begin\r
47958   Result := Index shl 8;\r
47959 end;\r
47961 { macros }\r
47962 //[procedure ImageList_RemoveAll]\r
47963 procedure ImageList_RemoveAll(ImageList: HImageList); stdcall;\r
47964 begin\r
47965   ImageList_Remove(ImageList, -1);\r
47966 end;\r
47968 //[function ImageList_ExtractIcon]\r
47969 function ImageList_ExtractIcon(Instance: THandle; ImageList: HImageList;\r
47970   Image: Integer): HIcon; stdcall;\r
47971 begin\r
47972   Result := ImageList_GetIcon(ImageList, Image, 0);\r
47973 end;\r
47975 //[function ImageList_LoadBitmap]\r
47976 function ImageList_LoadBitmap(Instance: THandle; Bmp: PChar;\r
47977   CX, Grow: Integer; Mask: TColorRef): HImageList; stdcall;\r
47978 begin\r
47979   Result := ImageList_LoadImage(Instance, Bmp, CX, Grow, Mask,\r
47980     IMAGE_BITMAP, 0);\r
47981 end;\r
47983 //[procedure FreeBmp]\r
47984 procedure FreeBmp( Bmp: HBitmap );\r
47985 begin\r
47986   DeleteObject( Bmp );\r
47987 end;\r
47989 //[function LoadBmp]\r
47990 function LoadBmp( Instance: Integer; Rsrc: PChar; MasterObj: PObj ): HBitmap;\r
47991 begin\r
47992   Result := LoadBitmap( Instance, Rsrc );\r
47993   MasterObj.Add2AutoFreeEx( TObjectMethod( MakeMethod( Pointer( Result ), @ FreeBmp ) ) );\r
47994 end;\r
47996 { TImageList }\r
47998 //*\r
47999 //[function TImageList.Add]\r
48000 function TImageList.Add(Bmp, Msk: HBitmap): Integer;\r
48001 begin\r
48002   Result := -1;\r
48003   if not HandleNeeded then Exit;\r
48004   Result := ImageList_Add( FHandle, Bmp, Msk );\r
48005 end;\r
48007 //*\r
48008 //[function TImageList.AddIcon]\r
48009 function TImageList.AddIcon(Ico: HIcon): Integer;\r
48010 {var Bmp : HBitmap;\r
48011     DC : HDC;}\r
48012 begin\r
48013   Result := -1;\r
48014   if ImgWidth = 0 then\r
48015     ImgWidth := 32;\r
48016   if ImgHeight = 0 then\r
48017     ImgHeight := 32;\r
48018   if not HandleNeeded then Exit;\r
48020   {DC := GetDC( 0 );\r
48021   Bmp := CreateCompatibleBitmap( DC, ImgWidth, ImgHeight );\r
48022   Result := AddMasked( Bmp, 0 );\r
48023   DeleteObject( Bmp );\r
48024   ReleaseDC( 0, DC );\r
48025   if Result >= 0 then\r
48026      ReplaceIcon( Result, Ico );}\r
48027   Result := ImageList_AddIcon( fHandle, Ico );\r
48028 end;\r
48030 //*\r
48031 //[function TImageList.AddMasked]\r
48032 function TImageList.AddMasked(Bmp: HBitmap; Color: TColor): Integer;\r
48033 begin\r
48034   Result := -1;\r
48035   if not HandleNeeded then Exit;\r
48036   Result := ImageList_AddMasked( FHandle, Bmp, Color2RGB( Color ) );\r
48037 end;\r
48039 //+\r
48040 //[procedure TImageList.Clear]\r
48041 procedure TImageList.Clear;\r
48042 begin\r
48043   Handle := 0;\r
48044 end;\r
48046 //*\r
48047 //[procedure TImageList.Delete]\r
48048 procedure TImageList.Delete(Idx: Integer);\r
48049 begin\r
48050    if FHandle = 0 then Exit;\r
48051    ImageList_Remove( FHandle, Idx );\r
48052 end;\r
48054 {$IFDEF ASM_VERSION}\r
48055 //[destructor TImageList.Destroy]\r
48056 destructor TImageList.Destroy;\r
48057 asm\r
48058         PUSH     EAX\r
48059         XOR      EDX, EDX\r
48060         CALL     SetHandle\r
48061         POP      EAX\r
48062         MOV      EDX, [EAX].fNext\r
48063         MOV      ECX, [EAX].fPrev\r
48064         TEST     EDX, EDX\r
48065         JZ       @@nonext\r
48066         MOV      [EDX].fPrev, ECX\r
48067 @@nonext:\r
48068         JECXZ    @@noprev\r
48069         MOV      [ECX].fNext, EDX\r
48070 @@noprev:\r
48071         MOV      ECX, [EAX].fControl\r
48072         JECXZ    @@fin\r
48073         CMP      [ECX].TControl.fImageList, EAX\r
48074         JNZ      @@fin\r
48075         MOV      [ECX].TControl.fImageList, EDX\r
48076 @@fin:  CALL     TObj.Destroy\r
48077 end;\r
48078 {$ELSE ASM_VERSION} //Pascal\r
48079 destructor TImageList.Destroy;\r
48080 begin\r
48081   Clear;\r
48082   if fNext <> nil then\r
48083     fNext.fPrev := fPrev;\r
48084   if fPrev <> nil then\r
48085     fPrev.fNext := fNext;\r
48086   if fControl <> nil then\r
48087   if PControl( fControl ).fImageList = @Self then\r
48088     PControl( fControl ).fImageList := fNext;\r
48089   inherited;\r
48090 end;\r
48091 {$ENDIF ASM_VERSION}\r
48093 //*\r
48094 //[procedure TImageList.Draw]\r
48095 procedure TImageList.Draw(Idx: Integer; DC: HDC; X, Y: Integer);\r
48096 begin\r
48097   if FHandle = 0 then Exit;\r
48098   ImageList_Draw( FHandle, Idx, DC, X, Y, GetDrawStyle );\r
48099 end;\r
48101 //[function TImageList.ExtractIcon]\r
48102 function TImageList.ExtractIcon(Idx: Integer): HIcon;\r
48103 begin\r
48104   Result := ImageList_ExtractIcon( 0, FHandle, Idx );\r
48105 end;\r
48107 //[function TImageList.ExtractIconEx]\r
48108 function TImageList.ExtractIconEx(Idx: Integer): HIcon;\r
48109 begin\r
48110   Result := ImageList_GetIcon( FHandle, Idx, GetDrawStyle );\r
48111 end;\r
48113 //*\r
48114 //[function TImageList.GetBitmap]\r
48115 function TImageList.GetBitmap: HBitmap;\r
48116 var II : TImageInfo;\r
48117 begin\r
48118   Result := 0;\r
48119   if FHandle = 0 then Exit;\r
48120   if ImageList_GetImageInfo( FHandle, 0, II ) then\r
48121      Result := II.hbmImage;\r
48122 end;\r
48124 //*\r
48125 //[function TImageList.GetBkColor]\r
48126 function TImageList.GetBkColor: TColor;\r
48127 begin\r
48128   Result := fBkColor;\r
48129   if FHandle = 0 then Exit;\r
48130   Result := ImageList_GetBkColor( FHandle );\r
48131 end;\r
48133 //*\r
48134 //[function TImageList.GetCount]\r
48135 function TImageList.GetCount: Integer;\r
48136 begin\r
48137   Result := 0;\r
48138   if FHandle <> 0 then\r
48139      Result := ImageList_GetImageCount( FHandle );\r
48140 end;\r
48142 //*\r
48143 //[function TImageList.GetDrawStyle]\r
48144 function TImageList.GetDrawStyle: DWord;\r
48145 begin\r
48146   Result := 0;\r
48147   if dsBlend25 in DrawingStyle then\r
48148      Result := Result or ILD_BLEND25;\r
48149   if dsBlend50 in DrawingStyle then\r
48150      Result := Result or ILD_BLEND50;\r
48151   if dsTransparent in DrawingStyle then\r
48152      Result := Result or ILD_TRANSPARENT\r
48153   else\r
48154   if dsMask in DrawingStyle then\r
48155      Result := Result or ILD_MASK\r
48156   {else\r
48157      Result := Result or ILD_NORMAL}; // ILD_NORMAL = 0\r
48158 end;\r
48160 {$IFDEF ASM_VERSION}\r
48161 //[function TImageList.GetHandle]\r
48162 function TImageList.GetHandle: THandle;\r
48163 asm\r
48164         PUSH     EAX\r
48165         CALL     HandleNeeded\r
48166         POP      EAX\r
48167         MOV      EAX, [EAX].FHandle\r
48168 end;\r
48169 {$ELSE ASM_VERSION} //Pascal\r
48170 function TImageList.GetHandle: THandle;\r
48171 begin\r
48172   HandleNeeded;\r
48173   Result := FHandle;\r
48174 end;\r
48175 {$ENDIF ASM_VERSION}\r
48177 //*\r
48178 //[function TImageList.GetMask]\r
48179 function TImageList.GetMask: HBitmap;\r
48180 var II : TImageInfo;\r
48181 begin\r
48182   Result := 0;\r
48183   if FHandle = 0 then Exit;\r
48184   if ImageList_GetImageInfo( FHandle, 0, II ) then\r
48185      Result := II.hbmMask;\r
48186 end;\r
48188 {$IFDEF ASM_noVERSION}\r
48189 //[function TImageList.HandleNeeded]\r
48190 function TImageList.HandleNeeded: Boolean;\r
48191 const ColorFlags : array[ TImageListColors ] of Byte = ( ILC_COLOR,\r
48192                  ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24,\r
48193                  ILC_COLOR32, ILC_COLORDDB );\r
48194 asm\r
48195         MOV      ECX, [EAX].FHandle\r
48196         JECXZ    @@make_handle\r
48197         MOV      AL, 1\r
48198         RET\r
48199 @@make_handle:\r
48200         MOV      ECX, [EAX].fImgWidth\r
48201         JECXZ    @@ret_ECX\r
48202         MOV      EDX, ECX\r
48203         MOV      ECX, [EAX].fImgHeight\r
48204         JECXZ    @@ret_ECX\r
48205         PUSH     EBX\r
48206         XCHG     EBX, EAX\r
48208         PUSH     [EBX].FAllocBy\r
48209         PUSH     0\r
48210         MOVZX    EAX, [EBX].FColors\r
48211         MOVZX    EAX, byte ptr [ColorFlags+EAX]\r
48212         CMP      [EBX].FMasked, 0\r
48213         JZ       @@flags_ready\r
48214         {$IFDEF PARANOIA}\r
48215         DB $0C, $01\r
48216         {$ELSE}\r
48217         OR AL, 1\r
48218         {$ENDIF}\r
48219 @@flags_ready:\r
48220         PUSH     EAX\r
48221         PUSH     ECX\r
48222         PUSH     EDX\r
48223         CALL     ImageList_Create\r
48224         MOV      [EBX].FHandle, EAX\r
48225         XCHG     ECX, EAX\r
48226         POP      EBX\r
48227 @@ret_ECX:\r
48228         TEST     ECX, ECX\r
48229         SETNZ    AL\r
48230 end;\r
48231 {$ELSE ASM_VERSION} //Pascal\r
48232 function TImageList.HandleNeeded: Boolean;\r
48233 const ColorFlags : array[ TImageListColors ] of Byte = ( ILC_COLOR,\r
48234                  ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24,\r
48235                  ILC_COLOR32, ILC_COLORDDB, 0 );\r
48236 var Flags : DWord;\r
48237 begin\r
48238   Result := True;\r
48239   if FHandle <> 0 then Exit;\r
48240   Result := False;\r
48241   if ImgWidth = 0 then Exit;\r
48242   if ImgHeight = 0 then Exit;\r
48243   Flags := ColorFlags[ FColors ];\r
48244   if Masked then\r
48245      Flags := Flags or ILC_MASK;\r
48246   FHandle := ImageList_Create( ImgWidth, ImgHeight, Flags, 0, FAllocBy );\r
48247   if fBkColor <> clNone then\r
48248     SetBkColor( fBkColor );\r
48249   Result := FHandle <> 0;\r
48250 end;\r
48251 {$ENDIF ASM_VERSION}\r
48253 //*\r
48254 //[function TImageList.ImgRect]\r
48255 function TImageList.ImgRect(Idx: Integer): TRect;\r
48256 var II : TImageInfo;\r
48257 begin\r
48258   Result := MakeRect( 0, 0, 0, 0 );\r
48259   if FHandle = 0 then Exit;\r
48260   if ImageList_GetImageInfo( FHandle, Idx, II ) then\r
48261      Result := II.rcImage;\r
48262 end;\r
48264 {$IFDEF ASM_noVERSION}\r
48265 //[function TImageList.LoadBitmap]\r
48266 function TImageList.LoadBitmap(ResourceName: PChar;\r
48267   TranspColor: TColor): Boolean;\r
48268 asm\r
48269         PUSH     EBX\r
48270         XCHG     EBX, EAX\r
48271         XCHG     EAX, ECX //TranspColor\r
48272         PUSH     EDX\r
48273         CMP      EAX, clNone\r
48274         JNE      @@2rgb\r
48275         OR       EAX, -1\r
48276         JMP      @@tranColorReady\r
48277 @@2rgb:\r
48278         CALL     Color2RGB\r
48279 @@tranColorReady:\r
48280         POP      EDX\r
48281         PUSH     EAX\r
48282         PUSH     [EBX].fAllocBy\r
48283         PUSH     [EBX].fImgWidth\r
48284         PUSH     EDX\r
48285         PUSH     [hInstance]\r
48286         CALL     ImageList_LoadBitmap\r
48287         TEST     EAX, EAX\r
48288         JZ       @@exit\r
48289         XCHG     EDX, EAX\r
48290         XCHG     EAX, EBX\r
48291         CALL     SetHandle\r
48292         MOV      AL, 1\r
48293 @@exit: POP      EBX\r
48294 end;\r
48295 {$ELSE ASM_VERSION} //Pascal\r
48296 function TImageList.LoadBitmap(ResourceName: PChar;\r
48297   TranspColor: TColor): Boolean;\r
48298 var NewHandle : THandle;\r
48299     TranColr: TColor;\r
48300 begin\r
48301   TranColr := TranspColor;\r
48302   if TranColr = clNone then TranColr := TColor( CLR_NONE )\r
48303   else TranColr := Color2RGB( TranColr );\r
48304   NewHandle := ImageList_LoadBitmap( hInstance, ResourceName,\r
48305             ImgWidth, AllocBy, TranColr );\r
48306   //ImageList_GetIconSize( NewHandle, fImgWidth, fImgHeight );\r
48307   Result := NewHandle <> 0;\r
48308   if Result then\r
48309      Handle := NewHandle;\r
48310   ImageList_GetIconSize( fHandle, FImgWidth, FImgHeight );\r
48311 end;\r
48312 {$ENDIF ASM_VERSION}\r
48314 //*\r
48315 //[function TImageList.LoadFromFile]\r
48316 function TImageList.LoadFromFile(FileName: PChar; TranspColor: TColor;\r
48317   ImgType: TImageType): Boolean;\r
48318 const ImgTypes:array[ TImageType ] of DWord = ( IMAGE_BITMAP, IMAGE_ICON, IMAGE_CURSOR );\r
48319 var NewHandle : THandle;\r
48320     TranspFlag : DWord;\r
48321 begin\r
48322   TranspFlag := 0;\r
48323   if TranspColor <> clNone then\r
48324      TranspFlag := LR_LOADTRANSPARENT;\r
48325   NewHandle := ImageList_LoadImage( hInstance, FileName, ImgWidth, AllocBy, Color2RGB( TranspColor ),\r
48326                                     ImgTypes[ ImgType ], LR_LOADFROMFILE or TranspFlag );\r
48327   Result := NewHandle <> 0;\r
48328   if Result then\r
48329      Handle := NewHandle;\r
48330 end;\r
48332 //*\r
48333 //[function TImageList.LoadSystemIcons]\r
48334 function TImageList.LoadSystemIcons(SmallIcons: Boolean): Boolean;\r
48335 var NewHandle : THandle;\r
48336     FileInfo : TSHFileInfo;\r
48337     Flags : DWord;\r
48338 begin\r
48339   OleInit;\r
48340   Flags := SHGFI_SYSICONINDEX;\r
48341   if SmallIcons then\r
48342      Flags := Flags or SHGFI_SMALLICON;\r
48343   NewHandle := SHGetFileInfo( '', 0, FileInfo, Sizeof( FileInfo ), Flags );\r
48344   Result := NewHandle <> 0;\r
48345   if Result then\r
48346   begin\r
48347      Handle := NewHandle;\r
48348      FShareImages := True;\r
48349   end;\r
48350 end;\r
48352 //*\r
48353 //[function TImageList.Merge]\r
48354 function TImageList.Merge(Idx: Integer; ImgList2: PImageList; Idx2, X,\r
48355   Y: Integer): PImageList;\r
48356 var L : THandle;\r
48357 begin\r
48358   Result := nil;\r
48359   //if FHandle = 0 then Exit;\r
48360   L := ImageList_Merge( FHandle, Idx, ImgList2.Handle, Idx2, X, Y );\r
48361   if L <> 0 then\r
48362   begin\r
48363      Result := NewImageList( fControl );\r
48364      Result.Handle := L;\r
48365   end;\r
48366 end;\r
48368 //*\r
48369 //[function TImageList.Replace]\r
48370 function TImageList.Replace(Idx: Integer; Bmp, Msk: HBitmap): Boolean;\r
48371 begin\r
48372   Result := False;\r
48373   if FHandle = 0 then Exit;\r
48374   Result := ImageList_Replace( FHandle, Idx, Bmp, Msk );\r
48375 end;\r
48377 //*\r
48378 //[function TImageList.ReplaceIcon]\r
48379 function TImageList.ReplaceIcon(Idx: Integer; Ico: HIcon): Boolean;\r
48380 begin\r
48381   Result := False;\r
48382   if FHandle = 0 then Exit;\r
48383   Result := ImageList_ReplaceIcon( FHandle, Idx, Ico ) >= 0;\r
48384 end;\r
48386 //*\r
48387 //[procedure TImageList.SetAllocBy]\r
48388 procedure TImageList.SetAllocBy(const Value: Integer);\r
48389 begin\r
48390   if FHandle <> 0 then Exit;\r
48391      // AllocBy can be changed only before adding images\r
48392      // and creating image list handle\r
48393   FAllocBy := Value;\r
48394 end;\r
48396 //*\r
48397 //[procedure TImageList.SetBkColor]\r
48398 procedure TImageList.SetBkColor(const Value: TColor);\r
48399 begin\r
48400   fBkColor := Value;\r
48401   if fHandle <> 0 then\r
48402     ImageList_SetBkColor( FHandle, Color2RGB( Value ) );\r
48403 end;\r
48405 //*\r
48406 //[procedure TImageList.SetColors]\r
48407 procedure TImageList.SetColors(const Value: TImageListColors);\r
48408 begin\r
48409   if FHandle <> 0 then Exit;\r
48410   FColors := Value;\r
48411 end;\r
48413 {$IFDEF ASM_VERSION}\r
48414 //[procedure TImageList.SetHandle]\r
48415 procedure TImageList.SetHandle(const Value: THandle);\r
48416 asm\r
48417         PUSH     EBX\r
48418         XCHG     EBX, EAX\r
48419         MOV      ECX, [EBX].FHandle\r
48420         CMP      ECX, EDX\r
48421         JZ       @@exit\r
48422         JECXZ    @@set_handle\r
48423         CMP      [EBX].fShareImages, 0\r
48424         JNZ      @@set_handle\r
48425         PUSH     EDX\r
48426         PUSH     ECX\r
48427         CALL     ImageList_Destroy\r
48428         POP      EDX\r
48430 @@set_handle:\r
48431         MOV      [EBX].FHandle, EDX\r
48432         TEST     EDX, EDX\r
48433         JZ       @@set_sz0\r
48434         LEA      EAX, [EBX].FImgHeight\r
48435         PUSH     EAX\r
48436         LEA      EAX, [EBX].FImgWidth\r
48437         PUSH     EAX\r
48438         PUSH     EDX\r
48439         CALL     ImageList_GetIconSize\r
48440         JMP      @@exit\r
48442 @@set_sz0:\r
48443         MOV      [EBX].fImgWidth, EDX\r
48444         MOV      [EBX].fImgHeight, EDX\r
48446 @@exit:\r
48447         POP      EBX\r
48448 end;\r
48449 {$ELSE ASM_VERSION} //Pascal\r
48450 procedure TImageList.SetHandle(const Value: THandle);\r
48451 begin\r
48452   if FHandle = Value then Exit;\r
48453   if (FHandle <> 0) and not FShareImages then\r
48454      ImageList_Destroy( FHandle );\r
48455   FHandle := Value;\r
48456   if FHandle <> 0 then\r
48457      ImageList_GetIconSize( FHandle, FImgWidth, FImgHeight )\r
48458   else\r
48459   begin\r
48460     FImgWidth := 0;\r
48461     FImgHeight := 0;\r
48462   end;\r
48463   //FBkColor := ImageList_GetBkColor( FHandle );\r
48464 end;\r
48465 {$ENDIF ASM_VERSION}\r
48467 //[procedure TImageList.SetImgHeight]\r
48468 procedure TImageList.SetImgHeight(const Value: Integer);\r
48469 begin\r
48470   if FHandle <> 0 then Exit;\r
48471   FImgHeight := Value;\r
48472 end;\r
48474 //[procedure TImageList.SetImgWidth]\r
48475 procedure TImageList.SetImgWidth(const Value: Integer);\r
48476 begin\r
48477   if FHandle <> 0 then Exit;\r
48478   FImgWidth := Value;\r
48479 end;\r
48481 //[procedure TImageList.SetMasked]\r
48482 procedure TImageList.SetMasked(const Value: Boolean);\r
48483 begin\r
48484   if FHandle <> 0 then Exit;\r
48485   FMasked := Value;\r
48486 end;\r
48488 //*\r
48489 //[function TImageList.GetOverlay]\r
48490 function TImageList.GetOverlay(Idx: TImgLOVrlayIdx): Integer;\r
48491 begin\r
48492   Result := fOverlay[ Idx ];\r
48493 end;\r
48495 //[procedure TImageList.SetOverlay]\r
48496 procedure TImageList.SetOverlay(Idx: TImgLOVrlayIdx; const Value: Integer);\r
48497 begin\r
48498   if ImageList_SetOverlayImage( fHandle, Value, Idx shl 8 ) then\r
48499     fOverlay[ Idx ] := Value;\r
48500 end;\r
48502 //[procedure TImageList.StretchDraw]\r
48503 procedure TImageList.StretchDraw(Idx: Integer; DC: HDC; const Rect: TRect);\r
48504 begin\r
48505   if FHandle = 0 then Exit;\r
48506   ImageList_DrawEx( FHandle, Idx, DC, Rect.Left, Rect.Top,\r
48507                     Rect.Right- Rect.Left, Rect.Bottom-Rect.Top,\r
48508                     BkColor, BlendColor, GetDrawStyle );\r
48509 end;\r
48511 //*\r
48512 //[function GetImgListSize]\r
48513 function GetImgListSize( Sender: PControl; Size: Integer ): PImageList;\r
48514 begin\r
48515   if Size > 16 then\r
48516     Result := Sender.fCtlImageListNormal\r
48517   else\r
48518     Result := Sender.fCtlImageListSml;\r
48519   if Result <> nil then\r
48520   begin\r
48521     if Result.fImgWidth = 0 then\r
48522       Result.ImgWidth := Size;\r
48523     if Result.fImgHeight = 0 then\r
48524       Result.ImgHeight := Size;\r
48525     //if (Result.FImgWidth <> Size) or (Result.FImgHeight <> Size) then\r
48526     //  Result := nil;\r
48527   end;\r
48528   if Result = nil then\r
48529   begin\r
48530     Result := Sender.fImageList;\r
48531     while Result <> nil do\r
48532     begin\r
48533       if (Result.FImgWidth = Size) and (Result.FImgHeight = Size) then\r
48534         break;\r
48535       Result := Result.fNext;\r
48536     end;\r
48537   end;\r
48538 end;\r
48540 //*\r
48541 //[function TControl.GetImgListIdx]\r
48542 function TControl.GetImgListIdx(const Index: Integer): PImageList;\r
48543 begin\r
48544   if Index <> 0 then\r
48545     Result := GetImgListSize( @Self, Index )\r
48546   else\r
48547   begin\r
48548     Result := fCtlImgListState;\r
48549     if Result = nil then\r
48550     begin\r
48551       Result := fImageList;\r
48552       while Result <> nil do\r
48553       begin\r
48554         if (Result <> GetImgListIdx( 16 )) and (Result <> GetImgListIdx( 32 )) then\r
48555            break;\r
48556         Result := Result.fNext;\r
48557       end;\r
48558     end;\r
48559   end;\r
48560 end;\r
48562 //*\r
48563 //[procedure TControl.SetImgListIdx]\r
48564 procedure TControl.SetImgListIdx(const Index: Integer;\r
48565   const Value: PImageList);\r
48566 begin\r
48568   if Value <> nil then\r
48569   begin\r
48570     if Index <> 0 then\r
48571     if (Value.ImgWidth = 0) or (Value.ImgHeight = 0) then\r
48572     begin\r
48573       Value.ImgWidth := Index;\r
48574       Value.ImgHeight := Index;\r
48575     end;\r
48576   end;\r
48578   case Index of\r
48579   32: fCtlImageListNormal := Value;\r
48580   16: fCtlImageListSml := Value;\r
48581   else fCtlImgListState := Value;\r
48582   end;\r
48583   ApplyImageLists2Control( @Self );\r
48584 end;\r
48586 { -- list view -- }\r
48588 //[function WndProcEndLabelEdit]\r
48589 function WndProcEndLabelEdit( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
48590 var NMhdr: PNMHdr;\r
48591     LVDisp: PLVDispInfo;\r
48592     {$IFNDEF _FPC}\r
48593     {$IFNDEF _D2}\r
48594     {$IFDEF UNICODE_CTRLS}\r
48595     LVDispW: PLVDispInfoW;\r
48596     {$ENDIF UNICODE_CTRLS}\r
48597     {$ENDIF _D2}\r
48598     {$ENDIF _FPC}\r
48599     Flag: Boolean;\r
48600 begin\r
48601   Result := False;\r
48602   if Msg.message = WM_NOTIFY then\r
48603   begin\r
48604     NMHdr := Pointer( Msg.lParam );\r
48605     case NMHdr.code of\r
48606       LVN_ENDLABELEDIT {$IFDEF UNICODE_CTRLS}, LVN_ENDLABELEDITW {$ENDIF UNICODE_CTRLS}:\r
48607         begin\r
48608           LVDisp := Pointer( Msg.lParam );\r
48609           Result := True;\r
48610           if LVDisp.item.pszText = nil then Exit;\r
48611           Rslt := 1;\r
48612           if assigned( Self_.fOnEditLVItem ) then\r
48613           begin\r
48614           {$IFNDEF _FPC}\r
48615           {$IFNDEF _D2}\r
48616           {$IFDEF UNICODE_CTRLS}\r
48617             if NMHdr.code = LVN_ENDLABELEDITW then\r
48618             begin\r
48619               LVDispW := Pointer( LVDisp );\r
48620               Flag := Self_.fOnEditLVItem( Self_, LVDispW.item.iItem,\r
48621                    LVDispW.item.iSubItem, PChar( LVDispW.item.pszText ) );\r
48622             end else\r
48623           {$ENDIF UNICODE_CTRLS}\r
48624           {$ENDIF _D2}\r
48625           {$ENDIF _FPC}\r
48626             Flag := Self_.fOnEditLVItem( Self_, LVDisp.item.iItem,\r
48627                              LVDisp.item.iSubItem, LVDisp.item.pszText );\r
48628             if Flag then Rslt := 1\r
48629                     else Rslt := 0;\r
48630           end;\r
48631         end;\r
48632     end;\r
48633   end;\r
48634 end;\r
48636 //[procedure TControl.SetOnEditLVItem]\r
48637 procedure TControl.SetOnEditLVItem(const Value: TOnEditLVItem);\r
48638 begin\r
48639   fOnEditLVITem := Value;\r
48640   AttachProc( WndProcEndLabelEdit );\r
48641 end;\r
48643 //*\r
48644 //[procedure TControl.LVColAdd]\r
48645 procedure TControl.LVColAdd(const aText: String; aalign: TTextAlign;\r
48646   aWidth: Integer);\r
48647 begin\r
48648 ////////////////////////////////////////////////////\r
48649 //LVColInsert( fLVColCount + 1, aText, aalign, aWidth );\r
48650 //////////////////////////////////////////////////////\r
48651   LVColInsert( fLVColCount, aText, aalign, aWidth );// 21.10.2001\r
48652   ////////////////////////////////////////////////////\r
48653 end;\r
48655 {$IFNDEF _FPC}\r
48656 {$IFNDEF _D2}\r
48657 //[procedure TControl.LVColAddW]\r
48658 procedure TControl.LVColAddW(const aText: WideString; aalign: TTextAlign;\r
48659   aWidth: Integer);\r
48660 begin\r
48661   LVColInsertW( fLVColCount, aText, aalign, aWidth );\r
48662 end;\r
48663 {$ENDIF _D2}\r
48664 {$ENDIF _FPC}\r
48666 //****************** changed by Mike Gerasimov\r
48667 //[procedure TControl.LVColInsert]\r
48668 procedure TControl.LVColInsert(ColIdx: Integer; const aText: String;\r
48669   aAlign: TTextAlign; aWidth: Integer);\r
48670 var LVColData: TLVColumn;\r
48671 begin\r
48672   LVColData.mask := LVCF_FMT or LVCF_TEXT;\r
48673   if ImageListSmall <> nil then\r
48674     LVColData.mask := LVColData.mask; // or LVCF_IMAGE ;\r
48675   LVColData.iImage := -1;\r
48676   LVColData.fmt := Ord( aAlign );\r
48677   if aWidth < 0 then\r
48678   begin\r
48679     aWidth := -aWidth;\r
48680     LVColData.fmt := LVColData.fmt or LVCFMT_BITMAP_ON_RIGHT;\r
48681   end;\r
48682   LVColData.cx := aWidth;\r
48683   if aWidth > 0 then\r
48684     LVColData.mask := LVColData.mask or LVCF_WIDTH;\r
48685   LVColData.pszText := PChar( aText );\r
48686   if Perform( LVM_INSERTCOLUMN, ColIdx, Integer( @LVColData ) ) >= 0 then\r
48687     Inc( fLVColCount );\r
48688 end;\r
48690 {$IFNDEF _FPC}\r
48691 {$IFNDEF _D2}\r
48692 //[procedure TControl.LVColInsertW]\r
48693 procedure TControl.LVColInsertW(ColIdx: Integer; const aText: WideString;\r
48694   aAlign: TTextAlign; aWidth: Integer);\r
48695 var LVColData: TLVColumnW;\r
48696 begin\r
48697   LVColData.mask := LVCF_FMT or LVCF_TEXT;\r
48698   if ImageListSmall <> nil then\r
48699     LVColData.mask := LVColData.mask; // or LVCF_IMAGE ;\r
48700   LVColData.iImage := -1;\r
48701   LVColData.fmt := Ord( aAlign );\r
48702   if aWidth < 0 then\r
48703   begin\r
48704     aWidth := -aWidth;\r
48705     LVColData.fmt := LVColData.fmt or LVCFMT_BITMAP_ON_RIGHT;\r
48706   end;\r
48707   LVColData.cx := aWidth;\r
48708   if aWidth > 0 then\r
48709     LVColData.mask := LVColData.mask or LVCF_WIDTH;\r
48710   LVColData.pszText := PWideChar( aText );\r
48711   if Perform( LVM_INSERTCOLUMNW, ColIdx, Integer( @LVColData ) ) >= 0 then\r
48712     Inc( fLVColCount );\r
48713 end;\r
48714 {$ENDIF _D2}\r
48715 {$ENDIF _FPC}\r
48717 //[function TControl.GetLVColText]\r
48718 function TControl.GetLVColText(Idx: Integer): String;\r
48719 var Buf: array[ 0..4095 ] of Char;\r
48720     LC: TLVColumn;\r
48721 begin\r
48722   LC.mask := LVCF_TEXT;\r
48723   LC.pszText := @ Buf[ 0 ];\r
48724   LC.cchTextMax := Sizeof( Buf );\r
48725   Buf[ 0 ] := #0;\r
48726   Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );\r
48727   Result := Buf;\r
48728 end;\r
48730 //[procedure TControl.SetLVColText]\r
48731 procedure TControl.SetLVColText(Idx: Integer; const Value: String);\r
48732 var LC: TLVColumn;\r
48733 begin\r
48734   FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}\r
48735   LC.mask := LVCF_TEXT;\r
48736   LC.pszText := '';\r
48737   if Value <> '' then\r
48738     LC.pszText := @ Value[ 1 ];\r
48739   Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );\r
48740 end;\r
48742 {$IFNDEF _FPC}\r
48743 {$IFNDEF _D2}\r
48744 //[function TControl.GetLVColTextW]\r
48745 function TControl.GetLVColTextW(Idx: Integer): WideString;\r
48746 var Buf: array[ 0..4095 ] of WideChar;\r
48747     LC: TLVColumnW;\r
48748 begin\r
48749   LC.mask := LVCF_TEXT;\r
48750   LC.pszText := @ Buf[ 0 ];\r
48751   LC.cchTextMax := High( Buf ) + 1;\r
48752   Buf[ 0 ] := #0;\r
48753   Perform( LVM_GETCOLUMNW, Idx, Integer( @ LC ) );\r
48754   Result := Buf;\r
48755 end;\r
48757 //[procedure TControl.SetLVColTextW]\r
48758 procedure TControl.SetLVColTextW(Idx: Integer; const Value: WideString);\r
48759 var LC: TLVColumnW;\r
48760 begin\r
48761   FillChar( LC, Sizeof( LC ), 0 );\r
48762   LC.mask := LVCF_TEXT;\r
48763   LC.pszText := '';\r
48764   if Value <> '' then\r
48765     LC.pszText := @ Value[ 1 ];\r
48766   Perform( LVM_SETCOLUMNW, Idx, Integer( @ LC ) );\r
48767 end;\r
48768 {$ENDIF _D2}\r
48769 {$ENDIF _FPC}\r
48771 //[function TControl.GetLVColalign]\r
48772 function TControl.GetLVColalign(Idx: Integer): TTextAlign;\r
48773 const Formats: array[ 0..2 ] of TTextAlign = ( taLeft, taRight, taCenter );\r
48774 var LC: TLVColumn;\r
48775 begin\r
48776   FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}\r
48777   LC.mask := LVCF_FMT;\r
48778   Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );\r
48779   Result := Formats[ LC.fmt and LVCFMT_JUSTIFYMASK ];\r
48780 end;\r
48782 //[procedure TControl.SetLVColalign]\r
48783 procedure TControl.SetLVColalign(Idx: Integer; const Value: TTextAlign);\r
48784 const FormatFlags: array[ TTextAlign ] of BYTE = ( LVCFMT_LEFT, LVCFMT_RIGHT,\r
48785       LVCFMT_CENTER );\r
48786 var LC: TLVColumn;\r
48787 begin\r
48788   FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}\r
48789   LC.mask := LVCF_FMT;\r
48790   Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );\r
48791   LC.fmt := LC.fmt and not LVCFMT_JUSTIFYMASK or FormatFlags[ Value ];\r
48792   Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );\r
48793 end;\r
48795 //[function TControl.GetLVColEx]\r
48796 function TControl.GetLVColEx(Idx: Integer; const Index: Integer): Integer;\r
48797 var LC: TLVColumn;\r
48798 begin\r
48799   FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}\r
48800   LC.mask := LoWord( Index );\r
48801   Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );\r
48802   Result := PDWORD( Integer( @ LC ) + HiWord( Index ) )^;\r
48803 end;\r
48805 //********************** changed by Mike Gerasimov\r
48806 //[procedure TControl.SetLVColEx]\r
48807 procedure TControl.SetLVColEx(Idx: Integer; const Index: Integer;\r
48808   const Value: Integer);\r
48809 var LC: TLVColumn;\r
48810 begin\r
48811   FillChar(LC,SizeOf(LC),0);                                    // Added Line\r
48812   LC.mask := LoWord( Index );\r
48813   if HiWord( Index ) = 24 then                                  // Added Line\r
48814    begin                                                        // Added Line\r
48815     LC.mask := LC.mask or LVCF_FMT;                             // Added Line\r
48816     if Value <>-1 Then                                          // Added Line\r
48817     LC.fmt := LC.fmt or LVCFMT_IMAGE or LVCFMT_COL_HAS_IMAGES;  // Added Line\r
48818    end;\r
48819   PDWORD( Integer( @ LC ) + HiWord( Index ) )^ := Value;\r
48820   Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );\r
48821 end;\r
48823 //*\r
48824 //[function TControl.LVAdd]\r
48825 function TControl.LVAdd(const aText: String; ImgIdx: Integer;\r
48826   State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer;\r
48827   Data: DWORD): Integer;\r
48828 begin\r
48829   Result := LVInsert( MaxInt {Count}, aText, ImgIdx, State, StateImgIdx, OverlayImgIdx, Data );\r
48830 end;\r
48832 //*\r
48833 //[function TControl.LVInsert]\r
48834 function TControl.LVInsert(Idx: Integer; const aText: String;\r
48835   ImgIdx: Integer; State: TListViewItemState;  StateImgIdx, OverlayImgIdx: Integer;\r
48836   Data: DWORD): Integer;\r
48837 const\r
48838   LVM_REDRAWITEMS         = LVM_FIRST + 21;\r
48839 var LVI: TLVItem;\r
48840 begin\r
48841   LVI.mask := LVIF_TEXT or LVIF_IMAGE or LVIF_PARAM or LVIF_STATE\r
48842               or LVIF_DI_SETITEM;\r
48843   LVI.iItem := Idx;\r
48844   LVI.iSubItem := 0;\r
48845   LVI.state := 0;\r
48846   if lvisBlend in State then\r
48847      LVI.state := LVIS_CUT;\r
48848   if lvisHighlight in State then\r
48849      LVI.state := LVI.state or LVIS_DROPHILITED;\r
48850   if lvisFocus in State then\r
48851      LVI.state := LVI.state or LVIS_FOCUSED;\r
48852   if lvisSelect in State then\r
48853      LVI.state := LVI.state or LVIS_SELECTED;\r
48854   LVI.stateMask := $FFFF;\r
48855   if StateImgIdx <> 0 then\r
48856      LVI.state := LVI.state or ((StateImgIdx and $F) shl 12);\r
48857   if OverlayImgIdx <> 0 then\r
48858      LVI.state := LVI.state or ((OverlayImgIdx and $F) shl 8);\r
48859   LVI.pszText := PChar( aText );\r
48860   LVI.iImage := ImgIdx;\r
48861   LVI.lParam := Data;\r
48862   Result := Perform( LVM_INSERTITEM, 0, Integer( @LVI ) );\r
48863   //Perform( LVM_REDRAWITEMS, Idx, Idx );\r
48864 end;\r
48866 //*\r
48867 //[procedure TControl.LVSetItem]\r
48868 procedure TControl.LVSetItem(Idx, Col: Integer; const aText: String;\r
48869   ImgIdx: Integer; State: TListViewItemState; StateImgIdx,\r
48870   OverlayImgIdx: Integer; Data: DWORD);\r
48871 var LVI: TLVItem;\r
48872     I: Integer;\r
48873 begin\r
48874   LVI.mask := LVIF_TEXT or {LVIF_STATE or} LVIF_DI_SETITEM;\r
48875   if Col = 0 then\r
48876   begin\r
48877     LVI.mask := LVIF_TEXT or LVIF_STATE or LVIF_PARAM\r
48878               or LVIF_DI_SETITEM;\r
48879     if ImgIdx <> I_SKIP then\r
48880        LVI.mask := LVI.mask or LVIF_IMAGE;\r
48881   end;\r
48882   if ImgIdx < I_SKIP then\r
48883     LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;\r
48884   LVI.iItem := Idx;\r
48885   LVI.iSubItem := Col;\r
48886   LVI.state := 0;\r
48887   if lvisBlend in State then\r
48888      LVI.state := LVIS_CUT;\r
48889   if lvisHighlight in State then\r
48890      LVI.state := LVI.state or LVIS_DROPHILITED;\r
48891   if lvisFocus in State then\r
48892      LVI.state := LVI.state or LVIS_FOCUSED;\r
48893   if lvisSelect in State then\r
48894      LVI.state := LVI.state or LVIS_SELECTED;\r
48895   LVI.stateMask := $FFFF;\r
48896   if StateImgIdx <> 0 then\r
48897      LVI.state := LVI.state or ((StateImgIdx and $F) shl 12);\r
48898   if StateImgIdx < 0 {= I_SKIP} then\r
48899      LVI.stateMask := $F0FF;\r
48900   if OverlayImgIdx <> 0 then\r
48901      LVI.state := LVI.state or ((OverlayImgIdx and $F) shl 8);\r
48902   if OverlayImgIdx < 0 {=I_SKIP} then\r
48903      LVI.stateMask := LVI.stateMask and $FFF;\r
48904   LVI.pszText := PChar( aText );\r
48905   LVI.iImage := ImgIdx;\r
48906   LVI.lParam := Data;\r
48907   I := Perform( LVM_SETITEM, 0, Integer( @LVI ) );\r
48908   if (I = 0) and (Col = 0) then\r
48909     Assert( False, 'Can not set item ' );\r
48910 end;\r
48912 //*\r
48913 //[procedure LVGetItem]\r
48914 procedure LVGetItem( Sender: PControl; Idx, Col: Integer; var LVI: TLVItem;\r
48915           TextBuf: PChar; TextBufSize: Integer );\r
48916 begin\r
48917   LVI.mask := LVIF_STATE or LVIF_PARAM or LVIF_IMAGE;\r
48918   if Col > 0 then\r
48919   if not (lvoSubItemImages in Sender.fLVOptions) then\r
48920     LVI.mask := LVIF_STATE or LVIF_PARAM;\r
48921   LVI.iItem := Idx;\r
48922   LVI.iSubItem := Col;\r
48923   LVI.pszText := TextBuf;\r
48924   LVI.cchTextMax := TextBufSize;\r
48925   if TextBufSize <> 0 then\r
48926     LVI.mask := LVI.mask or LVIF_TEXT;\r
48927   Sender.Perform( LVM_GETITEM, 0, Integer( @LVI ) );\r
48928 end;\r
48930 {$IFNDEF _FPC}\r
48931 {$IFNDEF _D2}\r
48932 //[procedure LVGetItemW]\r
48933 procedure LVGetItemW( Sender: PControl; Idx, Col: Integer; var LVI: TLVItemW;\r
48934           TextBuf: PWideChar; TextBufSize: Integer );\r
48935 begin\r
48936   LVI.mask := LVIF_STATE or LVIF_PARAM or LVIF_IMAGE;\r
48937   if Col > 0 then\r
48938   if not (lvoSubItemImages in Sender.fLVOptions) then\r
48939     LVI.mask := LVIF_STATE or LVIF_PARAM;\r
48940   LVI.iItem := Idx;\r
48941   LVI.iSubItem := Col;\r
48942   LVI.pszText := TextBuf;\r
48943   LVI.cchTextMax := TextBufSize;\r
48944   if TextBufSize <> 0 then\r
48945     LVI.mask := LVI.mask or LVIF_TEXT;\r
48946   Sender.Perform( LVM_GETITEMW, 0, Integer( @LVI ) );\r
48947 end;\r
48948 {$ENDIF _D2}\r
48949 {$ENDIF _FPC}\r
48951 //*\r
48952 //[function TControl.LVGetItemImgIdx]\r
48953 function TControl.LVGetItemImgIdx(Idx: Integer): Integer;\r
48954 var LVI: TLVItem;\r
48955 begin\r
48956   LVI.iImage := -1;//= Result if image is not assigned {Andrzej Kubaszek}\r
48957   LVGetItem( @Self, Idx, 0, LVI, nil, 0 );\r
48958   Result := LVI.iImage;\r
48959 end;\r
48961 //*\r
48962 //[procedure TControl.LVSetItemImgIdx]\r
48963 procedure TControl.LVSetItemImgIdx(Idx: Integer; const Value: Integer);\r
48964 var LVI: TLVItem;\r
48965 begin\r
48966   LVGetItem( @Self, Idx, 0, LVI, nil, 0 );\r
48967   LVI.iImage := Value;\r
48968   Perform( LVM_SETITEM, 0, Integer( @LVI ) );\r
48969 end;\r
48971 //*\r
48972 //[function TControl.LVGetItemText]\r
48973 function TControl.LVGetItemText(Idx, Col: Integer): String;\r
48974 var LVI: TLVItem;\r
48975     TextBuf: PChar;\r
48976     BufSize: DWORD;\r
48977 begin\r
48978   BufSize := 0;\r
48979   TextBuf := nil;\r
48980   repeat\r
48981     if TextBuf <> nil then\r
48982        FreeMem( TextBuf );\r
48983     BufSize := BufSize * 2 + 100; // to vary in asm version\r
48984     GetMem( TextBuf, BufSize );\r
48985     TextBuf[ 0 ] := #0;\r
48986     LVGetItem( @Self, Idx, Col, LVI, TextBuf, BufSize );\r
48987   until StrLen( TextBuf ) < BufSize - 1;\r
48988   Result := TextBuf;\r
48989   FreeMem( TextBuf );\r
48990 end;\r
48992 //*\r
48993 //[procedure TControl.LVSetItemText]\r
48994 procedure TControl.LVSetItemText(Idx, Col: Integer; const Value: String);\r
48995 var LVI: TLVItem;\r
48996 begin\r
48997   LVI.iSubItem := Col;\r
48998   LVI.pszText := PChar( Value );\r
48999   Perform( LVM_SETITEMTEXT, Idx, Integer( @LVI ) );\r
49000 end;\r
49002 {$IFNDEF _FPC}\r
49003 {$IFNDEF _D2}\r
49004 //[function TControl.LVGetItemTextW]\r
49005 function TControl.LVGetItemTextW(Idx, Col: Integer): WideString;\r
49006 var LVI: TLVItemW;\r
49007     TextBuf: PWideChar;\r
49008     BufSize: DWORD;\r
49009 begin\r
49010   BufSize := 0;\r
49011   TextBuf := nil;\r
49012   repeat\r
49013     if TextBuf <> nil then\r
49014        FreeMem( TextBuf );\r
49015     BufSize := BufSize * 2 + 100; // to vary in asm version\r
49016     GetMem( TextBuf, BufSize * 2 );\r
49017     TextBuf[ 0 ] := #0;\r
49018     LVGetItemW( @Self, Idx, Col, LVI, TextBuf, BufSize );\r
49019   until DWORD( WStrLen( TextBuf ) ) < BufSize - 1;\r
49020   Result := TextBuf;\r
49021   FreeMem( TextBuf );\r
49022 end;\r
49024 //[procedure TControl.LVSetItemTextW]\r
49025 procedure TControl.LVSetItemTextW(Idx, Col: Integer;\r
49026   const Value: WideString);\r
49027 var LVI: TLVItemW;\r
49028 begin\r
49029   LVI.iSubItem := Col;\r
49030   LVI.pszText := PWideChar( Value );\r
49031   Perform( LVM_SETITEMTEXTW, Idx, Integer( @LVI ) );\r
49032 end;\r
49033 {$ENDIF _D2}\r
49034 {$ENDIF _FPC}\r
49036 //*\r
49037 //[procedure TControl.LVColDelete]\r
49038 procedure TControl.LVColDelete(ColIdx: Integer);\r
49039 begin\r
49040   Perform( LVM_DELETECOLUMN, ColIdx, 0 );\r
49041   if fLVColCount > 0 then\r
49042     Dec( fLVColCount );\r
49043 end;\r
49045 //*\r
49046 //[procedure TControl.SetLVOptions]\r
49047 procedure TControl.SetLVOptions(const Value: TListViewOptions);\r
49048 begin\r
49049   if fLVOptions = Value then Exit;\r
49050   fLVOptions := Value;\r
49051   ApplyImageLists2ListView( @Self );\r
49052   PostMessage( fHandle, WM_SIZE, 0, 0 ); // to restore scrollers (otherwise its are lost)\r
49053 end;\r
49055 //*\r
49056 //[procedure TControl.SetLVStyle]\r
49057 procedure TControl.SetLVStyle(const Value: TListViewStyle);\r
49058 begin\r
49059   if fLVStyle = Value then Exit;\r
49060   fLVStyle := Value;\r
49061   ApplyImageLists2ListView( @Self );\r
49062 end;\r
49064 {$IFDEF ASM_VERSION}\r
49065 //[function TControl.Perform]\r
49066 function TControl.Perform(msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;\r
49067 asm\r
49068         PUSH     [lParam]\r
49069         PUSH     [wParam]\r
49070         PUSH     [msgcode]\r
49071         MOV      EAX, [EBP+8]\r
49072         CALL     TControl.GetWindowHandle\r
49073         PUSH     EAX\r
49074         CALL     Windows.SendMessage\r
49075 end;\r
49076 {$ELSE ASM_VERSION} //Pascal\r
49077 function TControl.Perform(msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;\r
49078 begin\r
49079   Result := SendMessage( GetWindowHandle, msgcode, wParam, lParam );\r
49080 end;\r
49081 {$ENDIF ASM_VERSION}\r
49083 {$IFDEF ASM_VERSION}\r
49084 //[function TControl.GetChildCount]\r
49085 function TControl.GetChildCount: Integer;\r
49086 asm\r
49087         MOV      EAX, [EAX].fChildren\r
49088         MOV      EAX, [EAX].TList.fCount\r
49089 end;\r
49090 {$ELSE ASM_VERSION} //Pascal\r
49091 function TControl.GetChildCount: Integer;\r
49092 begin\r
49093   Result := fChildren.fCount;\r
49094 end;\r
49095 {$ENDIF ASM_VERSION}\r
49097 //[procedure TControl.LVDelete]\r
49098 procedure TControl.LVDelete(Idx: Integer);\r
49099 begin\r
49100   Perform( LVM_DELETEITEM, Idx, 0 );\r
49101 end;\r
49103 //[procedure TControl.LVEditItemLabel]\r
49104 procedure TControl.LVEditItemLabel(Idx: Integer);\r
49105 begin\r
49106   Perform( LVM_EDITLABEL, Idx, 0 );\r
49107 end;\r
49109 //*\r
49110 //[function TControl.LVItemRect]\r
49111 function TControl.LVItemRect(Idx: Integer; Part: TGetLVItemPart): TRect;\r
49112 const Parts: array[ TGetLVItemPart ] of Byte = (\r
49113              LVIR_BOUNDS, LVIR_ICON, LVIR_LABEL, LVIR_SELECTBOUNDS );\r
49114 begin\r
49115   Result := MakeRect( Parts[ Part ], 0, 0, 0 );\r
49116   if Perform( LVM_GETITEMRECT, Idx, Integer( @Result ) ) = 0 then\r
49117      Result := MakeRect( 0, 0, 0, 0 );\r
49118 end;\r
49120 //[function TControl.LVSubItemRect]\r
49121 function TControl.LVSubItemRect(Idx, ColIdx: Integer): TRect;\r
49122 var Hdr: HWnd;\r
49123     R, R1: TRect;\r
49124     ClassNameBuf: array[ 0..31 ] of Char;\r
49125     HdItem: THDItem;\r
49126 begin\r
49127   Result.Top := ColIdx; // + 1; error in MSDN ?\r
49128   Result.Left := LVIR_BOUNDS;\r
49129   if Perform( LVM_GETSUBITEMRECT, Idx, Integer( @Result ) ) <> 0 then\r
49130     Exit;\r
49131   Result := MakeRect( 0, 0, 0, 0 );\r
49132   if ColIdx > 0 then R := LVSubItemRect( Idx, ColIdx - 1 )\r
49133                 else R := LVItemRect( Idx, lvipBounds );\r
49134   if (R.Left = 0) and (R.Right = 0) and\r
49135      (R.Top = 0) and (R.Bottom = 0) then Exit;\r
49136   Hdr := GetWindow( GetWindowHandle, GW_CHILD );\r
49137   if Hdr <> 0 then\r
49138   begin\r
49139     if GetClassName( Hdr, ClassNameBuf, 32 ) > 0 then\r
49140     if ClassNameBuf = 'SysHeader32' then\r
49141     begin\r
49142       if ColIdx > 0 then R.Left := R.Right\r
49143                     else R.Left := 0;\r
49144       R1.Top := 0; R1.Left := 0;\r
49145       Windows.ClientToScreen( Hdr,{$IFDEF FPC} PPoint( @ R1.Left )^ {$ELSE} R1.TopLeft {$ENDIF} );\r
49146       Windows.ScreenToClient( fHandle, {$IFDEF FPC} PPoint( @ R1.Left )^ {$ELSE} R1.TopLeft {$ENDIF} );\r
49147       R1 := R;\r
49148       HdItem.Mask := HDI_WIDTH;\r
49149       if SendMessage( Hdr, HDM_GETITEM, ColIdx, Integer( @HdItem ) ) = 0 then Exit;\r
49150       R1.Right := R1.Left + HdItem.cxy;\r
49151       Result := R1;\r
49152     end;\r
49153   end;\r
49154 end;\r
49156 //*\r
49157 //[function TControl.LVGetItemPos]\r
49158 function TControl.LVGetItemPos(Idx: Integer): TPoint;\r
49159 begin\r
49160   Perform( LVM_GETITEMPOSITION, Idx, Integer( @Result ) );\r
49161 end;\r
49163 //*\r
49164 //[procedure TControl.LVSetItemPos]\r
49165 procedure TControl.LVSetItemPos(Idx: Integer; const Value: TPoint);\r
49166 begin\r
49167   Perform( LVM_SETITEMPOSITION32, Idx, Integer( @Value ) );\r
49168 end;\r
49170 //*\r
49171 //[function TControl.LVItemAtPos]\r
49172 function TControl.LVItemAtPos(X, Y: Integer): Integer;\r
49173 var Dummy: TWherePosLVItem;\r
49174 begin\r
49175   Result := LVItemAtPosEx( X, Y, Dummy );\r
49176 end;\r
49178 //*\r
49179 //[function TControl.LVItemAtPosEx]\r
49180 function TControl.LVItemAtPosEx(X, Y: Integer;\r
49181   var Where: TWherePosLVItem): Integer;\r
49182 var HTI: TLVHitTestInfo;\r
49183 begin\r
49184   HTI.pt.x := X;\r
49185   HTI.pt.y := Y;\r
49186   Perform( LVM_HITTEST, 0, Integer( @HTI ) );\r
49187   Result := HTI.iItem;\r
49188   Where := lvwpOnColumn;\r
49189   if HTI.flags = LVHT_ONITEMICON then\r
49190      Where := lvwpOnIcon\r
49191   else\r
49192   if HTI.flags = LVHT_ONITEMLABEL then\r
49193      Where := lvwpOnLabel\r
49194   else\r
49195   if HTI.flags = LVHT_ONITEMSTATEICON then\r
49196      Where := lvwpOnStateIcon\r
49197   else\r
49198   if HTI.flags = LVHT_ONITEM then\r
49199      Where := lvwpOnItem;\r
49200 end;\r
49202 //[procedure TControl.LVMakeVisible]\r
49203 procedure TControl.LVMakeVisible(Item: Integer; PartiallyOK: Boolean);\r
49204 begin\r
49205   if Item < 0 then Exit;\r
49206   Perform( LVM_ENSUREVISIBLE, Item, Integer( PartiallyOK ) );\r
49207 end;\r
49209 //*\r
49210 //[procedure TControl.LVSetColorByIdx]\r
49211 procedure TControl.LVSetColorByIdx(const Index: Integer;\r
49212   const Value: TColor);\r
49213 var MsgCode: Integer;\r
49214     ColorValue: TColor;\r
49215 begin\r
49216   MsgCode := Index + 1;\r
49217   case MsgCode of\r
49218   LVM_SETTEXTCOLOR:  fTextColor := Value;\r
49219   LVM_SETTEXTBKCOLOR: fLVTextBkColor := Value;\r
49220   LVM_SETBKCOLOR: fColor := Value;\r
49221   end;\r
49222   ColorValue := Color2RGB( Value );\r
49223   Perform( MsgCode, 0, ColorValue );\r
49224 end;\r
49226 {$IFDEF F_P}\r
49227 //[function TControl.LVGetColorByIdx]\r
49228 function TControl.LVGetColorByIdx(const Index: Integer): TColor;\r
49229 begin\r
49230   CASE Index OF\r
49231   LVM_SETTEXTCOLOR:   Result := fTextColor;\r
49232   LVM_SETTEXTBKCOLOR: Result := fLVTextBkColor;\r
49233   LVM_SETBKCOLOR:     Result := fColor;\r
49234   END;\r
49235 end;\r
49236 {$ENDIF F_P}\r
49238 //*\r
49239 //[function TControl.GetIntVal]\r
49240 function TControl.GetIntVal(const Index: Integer): Integer;\r
49241 begin\r
49242   Result := GetItemVal( 0, Index );\r
49243 end;\r
49245 //*\r
49246 //[procedure TControl.SetIntVal]\r
49247 procedure TControl.SetIntVal(const Index, Value: Integer);\r
49248 begin\r
49249   SetItemVal( Value, Index, 0 );\r
49250 end;\r
49252 //*\r
49253 //[function TControl.GetItemVal]\r
49254 function TControl.GetItemVal(Item: Integer; const Index: Integer): Integer;\r
49255 begin\r
49256   Result := Perform( LoWord(Index), Item, 0 );\r
49257 end;\r
49259 {$IFDEF ASM_VERSION}\r
49260 //[procedure TControl.SetItemVal]\r
49261 procedure TControl.SetItemVal(Item: Integer; const Index: Integer; const Value: Integer);\r
49262 asm\r
49263         PUSH     EAX\r
49264         PUSH     [Value]\r
49265         PUSH     EDX\r
49266         MOV      EDX, ECX\r
49267         SHR      EDX, 16\r
49268         JNZ      @@1\r
49269         MOV      EDX, ECX\r
49270         INC      EDX\r
49271 @@1:\r
49272         MOV      EBP, EDX\r
49273         AND      EDX, 7FFFh\r
49274         PUSH     EDX\r
49275         PUSH     EAX\r
49276         CALL     Perform\r
49277         MOV      EAX, EBP\r
49278         ADD      AX, AX\r
49279         POP      EAX\r
49280         JNB      @@2\r
49281         CALL     Invalidate\r
49282 @@2:\r
49283 end;\r
49284 {$ELSE ASM_VERSION} //Pascal\r
49285 procedure TControl.SetItemVal(Item: Integer; const Index: Integer; const Value: Integer);\r
49286 var MsgCode: Integer;\r
49287 begin\r
49288   MsgCode := HiWord( Index );\r
49289   if MsgCode = 0 then\r
49290     MsgCode := Index + 1;\r
49291   Perform( MsgCode and $7FFF, Item, Value );\r
49292   if (MsgCode and $8000) <> 0 then\r
49293     Invalidate;\r
49294 end;\r
49295 {$ENDIF ASM_VERSION}\r
49297 //[procedure TControl.GetSBMinMax]\r
49298 function TControl.GetSBMinMax: TPoint;\r
49299 {$IFDEF _D2}\r
49300 var X, Y: Integer;\r
49301 {$ENDIF}\r
49302 begin\r
49303   if (Handle <> 0) then begin\r
49304     {$IFDEF _D2}\r
49305     GetScrollRange(Handle, SB_CTL, X, Y);\r
49306     Result.X := X;\r
49307     Result.Y := Y;\r
49308     {$ELSE}\r
49309     GetScrollRange(Handle, SB_CTL, Result.X, Result.Y);\r
49310     {$ENDIF}\r
49311     Dec(Result.Y, SBPageSize - 1);\r
49312   end\r
49313   else\r
49314     Result := fSBMinMax;\r
49315 end;\r
49317 //[procedure TControl.GetSBPageSize]\r
49318 function TControl.GetSBPageSize: Integer;\r
49319 var\r
49320   SI: TScrollInfo;\r
49321 begin\r
49322   FillChar(SI, SizeOf(SI), 0);\r
49323   SI.cbSize := SizeOf(SI);\r
49324   SI.fMask := SIF_PAGE;\r
49325   SBGetScrollInfo(SI);\r
49326   Result := SI.nPage;\r
49327 end;\r
49329 //[procedure TControl.GetSBPosition]\r
49330 function TControl.GetSBPosition: Integer;\r
49331 begin\r
49332   Result := GetScrollPos(Handle, SB_CTL);\r
49333 end;\r
49335 //[procedure TControl.SetSBMax]\r
49336 procedure TControl.SetSBMax(Value: Longint);\r
49337 var\r
49338   P: TPoint;\r
49339 begin\r
49340   fSBMinMax.Y := Value;\r
49341   if (Handle <> 0) then begin\r
49342     P := SBMinMax;\r
49343     P.Y := Value;\r
49344     SBMinMax := P;\r
49345   end;\r
49346 end;\r
49348 //[procedure TControl.SetSBMin]\r
49349 procedure TControl.SetSBMin(Value: Longint);\r
49350 var\r
49351   P: TPoint;\r
49352 begin\r
49353   fSBMinMax.X := Value;\r
49354   if (Handle <> 0) then begin\r
49355     P := SBMinMax;\r
49356     P.X := Value;\r
49357     SBMinMax := P;\r
49358   end;\r
49359 end;\r
49361 //[procedure TControl.SetSBPageSize]\r
49362 procedure TControl.SetSBPageSize(Value: Integer);\r
49363 var\r
49364   SI: TScrollInfo;\r
49365 begin\r
49366   fSBPageSize := Value;\r
49367   if (Handle <> 0) then begin\r
49368     FillChar(SI, SizeOf(SI), 0);\r
49369     SI.cbSize := SizeOf(SI);\r
49370     SI.fMask := SIF_PAGE or SIF_RANGE;\r
49371     SBGetScrollInfo(SI);\r
49372     if (SI.nMax = 0) and (SI.nMin = 0) then\r
49373       SI.nMax := 1;\r
49374     SI.nMax := SI.nMax - Integer(SI.nPage) + Value;\r
49375     SI.nPage := Value;\r
49376     SBSetScrollInfo(SI);\r
49377   end;\r
49378 end;\r
49380 //[procedure TControl.SetSBPosition]\r
49381 procedure TControl.SetSBPosition(Value: Integer);\r
49382 begin\r
49383   fSBPosition := Value;\r
49384   if (Handle <> 0) then\r
49385     SetScrollPos(Handle, SB_CTL, Value, True);\r
49386 end;\r
49388 //[procedure TControl.SetSBMinMax]\r
49389 procedure TControl.SetSBMinMax(const Value: TPoint);\r
49390 begin\r
49391   GetSBMinMax;\r
49392   if (Handle <> 0) then\r
49393     SetScrollRange(Handle, SB_CTL, Value.X, Value.Y + SBPageSize - 1, True)\r
49394   else\r
49395     fSBMinMax := Value;\r
49396 end;\r
49398 //[procedure TControl.SBSetScrollInfo]\r
49399 function TControl.SBSetScrollInfo(const SI: TScrollInfo): Integer;\r
49400 begin\r
49401   Result := SetScrollInfo(Handle, SB_CTL, SI, True)\r
49402 end;\r
49404 //[procedure TControl.SBGetScrollInfo]\r
49405 function TControl.SBGetScrollInfo(var SI: TScrollInfo): Boolean;\r
49406 begin\r
49407   Result := Cardinal(GetScrollInfo(Handle, SB_CTL, SI)) <> 0;\r
49408 end;\r
49411 { -- OpenSaveDialog -- }\r
49413 //*\r
49414 //[function NewOpenSaveDialog]\r
49415 function NewOpenSaveDialog( const Title, StrtDir: String;\r
49416          Options: TOpenSaveOptions ): POpenSaveDialog;\r
49417 begin\r
49418   {-}\r
49419   New( Result, Create );\r
49420   {+}{++}(*Result := POpenSaveDialog.Create;*){--}\r
49421   Result.FOptions := Options;\r
49422   if Options = [] then\r
49423     Result.FOptions := DefOpenSaveDlgOptions;\r
49424   Result.fOpenDialog := True;\r
49425   Result.FTitle := Title;\r
49426   Result.FInitialDir := StrtDir;\r
49427 end;\r
49428 //[END NewOpenSaveDialog]\r
49430 { TOpenSaveDialog }\r
49432 {$IFDEF ASM_VERSION}\r
49433 //[destructor TOpenSaveDialog.Destroy]\r
49434 destructor TOpenSaveDialog.Destroy;\r
49435 asm     //cmd    //opd\r
49436         PUSH     EAX\r
49437         PUSH     0\r
49438         LEA      EDX, [EAX].FFilter\r
49439         PUSH     EDX\r
49440         LEA      EDX, [EAX].FInitialDir\r
49441         PUSH     EDX\r
49442         LEA      EDX, [EAX].FDefExtension\r
49443         PUSH     EDX\r
49444         LEA      EDX, [EAX].FFileName\r
49445         PUSH     EDX\r
49446         LEA      EAX, [EAX].FTitle\r
49447 @@loo:\r
49448         CALL     System.@LStrClr\r
49449         POP      EAX\r
49450         TEST     EAX, EAX\r
49451         JNZ      @@loo\r
49452         POP      EAX\r
49453         CALL     TObj.Destroy\r
49454 end;\r
49455 {$ELSE ASM_VERSION} //Pascal\r
49456 destructor TOpenSaveDialog.Destroy;\r
49457 begin\r
49458   FFilter := '';\r
49459   FInitialDir := '';\r
49460   FDefExtension := '';\r
49461   FFileName := '';\r
49462   FTitle := '';\r
49463   {$IFDEF OpenSaveDialog_Extended}\r
49464   TemplateName := '';\r
49465   {$ENDIF}\r
49466   inherited;\r
49467 end;\r
49468 {$ENDIF ASM_VERSION}\r
49470 {$IFDEF ASM_VERSION}\r
49471 //[function TOpenSaveDialog.Execute]\r
49472 function TOpenSaveDialog.Execute: Boolean;\r
49473 asm\r
49474         PUSH     EBX\r
49475         XCHG     EBX, EAX\r
49477         XOR      ECX, ECX\r
49478         {$IFDEF OpenSaveDialog_Extended}\r
49479         PUSH     [EBX].TemplateName\r
49480         PUSH     [EBX].HookProc\r
49481         {$ELSE}\r
49482         PUSH     ECX                      // prepare lpTemplateName = nil\r
49483         PUSH     ECX                      // prepare lpfnHook = nil\r
49484         {$ENDIF}\r
49485         PUSH     EBX                      // prepare lCustData = @Self\r
49486         MOV      EDX, [EBX].FDefExtension\r
49487         CALL     EDX2PChar\r
49488         PUSH     EDX                      // prepare lpstrDefExt = FDefExtension\r
49489         PUSH     ECX                      // prepare nFileExtension, nFileOffset: Word = 0, 0\r
49490         // prepare flags:\r
49491         LEA      EAX, [EBX].FOptions\r
49492         MOV      EDX, Offset[@@OpenSaveFlags]\r
49493         {$IFDEF OpenSaveDialog_Extended}\r
49494         MOV      CL, 14\r
49495         {$ELSE}\r
49496         MOV      CL, 12\r
49497         {$ENDIF}\r
49498         CALL     MakeFlags\r
49499         XOR      ECX, ECX\r
49500         OR       EAX, OFN_EXPLORER or OFN_LONGNAMES or OFN_ENABLESIZING\r
49501         PUSH     EAX                       // push Flags\r
49502         PUSH     [EBX].FTitle              // prepare lpstrTitle\r
49503         PUSH     [EBX].FInitialDir         // prepare lpstrInitialDir\r
49504         PUSH     ECX                       // prepare nMaxFileTitle = 0\r
49505         PUSH     ECX                       // prepare lpstrFileTitle = nil\r
49506         TEST     AH, 2      // MultiSelect?\r
49507         MOV      EAX, 65520\r
49508         JNZ      @@1\r
49509         MOV      AX, MAX_PATH+2\r
49510 @@1:    PUSH     EAX                       // prepare nMaxFile\r
49511         CALL     System.@GetMem\r
49512         POP      ECX\r
49513         PUSH     ECX\r
49514         PUSH     EAX                       // prepare lpStrFile\r
49515         XOR      EDX, EDX\r
49517 @@2:    //MOV      [EAX], DL  // clear it initially {Vadim Petrov: it is necessary}\r
49518         //INC      EAX\r
49519         //LOOP     @@2\r
49521         MOV      EDX, [EBX].fFileName // no, fill it initilly by FileName\r
49522         CALL     EDX2PChar\r
49523         DEC      ECX // added 5 october 2003 to prevent possible error if FileName too big\r
49524         CALL     StrLCopy\r
49525         XOR      EDX, EDX\r
49527         PUSH     [EBX].FFilterIndex        // prepare nFilterIndex\r
49528         PUSH     EDX                       // prepare nMaxCustFilter\r
49529         PUSH     EDX                       // prepare lpstrCustomFilter\r
49530         PUSH     EDX                       // prepare lpstrFilter = nil\r
49531         MOV      EAX, ESP\r
49532         OR       EDX, [EBX].FFilter\r
49533         JZ       @@5\r
49535         MOV      ECX, offset[@@0]\r
49536         CALL     System.@LStrCat3          // prepare lpStrFilter = FFilter + #0\r
49537         POP      EAX\r
49538         PUSH     EAX\r
49539         XOR      EDX, EDX\r
49540 @@3:    INC      EAX   // filter is not starting from ';' or '|'...\r
49541         CMP      [EAX], DL\r
49542         JZ       @@5\r
49543         CMP      byte ptr [EAX], '|'\r
49544         JNZ      @@3\r
49545 @@4:    MOV      [EAX], DL\r
49546         JMP      @@3\r
49547 @@OpenSaveFlags:\r
49548         DD OFN_CREATEPROMPT, OFN_EXTENSIONDIFFERENT, OFN_FILEMUSTEXIST\r
49549         DD OFN_HIDEREADONLY, OFN_NOCHANGEDIR, OFN_NODEREFERENCELINKS\r
49550         DD OFN_ALLOWMULTISELECT, OFN_NONETWORKBUTTON, OFN_NOREADONLYRETURN\r
49551         DD OFN_OVERWRITEPROMPT, OFN_PATHMUSTEXIST, OFN_READONLY, OFN_NOVALIDATE\r
49552         {$IFDEF OpenSaveDialog_Extended}\r
49553         DD OFN_ENABLETEMPLATE, OFN_ENABLEHOOK\r
49554         {$ENDIF}\r
49556         DD       -1, 1\r
49557 @@0:    DB       0\r
49560 @@5:\r
49561         PUSH     [hInstance]               // prepare hInstance\r
49563         MOV      ECX, [EBX].TControl.fWnd\r
49564         INC      ECX\r
49565         LOOP     @@6\r
49566         MOV      ECX, [Applet]\r
49567         JECXZ    @@6\r
49568         MOV      ECX, [ECX].TControl.fHandle\r
49569 @@6:    PUSH     ECX                       // prepare hWndOwner\r
49570         PUSH     76                        // prepare lStructSize\r
49572         PUSH     ESP\r
49573         CMP      [EBX].FOpenDialog, DL\r
49574         JZ       @@7\r
49575         CALL     GetOpenFileName\r
49576         JMP      @@8\r
49577 @@7:    CALL     GetSaveFileName\r
49578 @@8:\r
49579         PUSH     EAX\r
49580         XOR      EDX, EDX\r
49581         TEST     EAX, EAX\r
49582         JZ       @@10\r
49584         MOV      EAX, [ESP+4].TOpenFileName.nFilterIndex\r
49585         MOV      [EBX].FFilterIndex, EAX\r
49587         MOV      EAX, [ESP+4].TOpenFileName.lpstrFile\r
49588         MOV      EDX, EAX\r
49589         XOR      ECX, ECX\r
49591         TEST     [EBX].FOptions, 1 shl OSAllowMultiSelect\r
49592         JZ       @@10\r
49594         DEC      EAX\r
49595 @@9:    INC      EAX\r
49596         CMP      byte ptr [EAX], CL\r
49597         JNZ      @@9\r
49598         CMP      byte ptr [EAX+1], CL\r
49599         JZ       @@10\r
49600         MOV      byte ptr [EAX], 13\r
49601         JMP      @@9\r
49603 @@10:\r
49604         LEA      EAX, [EBX].FFileName\r
49605         CALL     System.@LStrFromPChar\r
49606         MOV      EAX, [ESP+4].TOpenFileName.lpstrFile\r
49607         CALL     System.@FreeMem // v1.86 +AK\r
49609         LEA      EAX, [ESP+4].TOpenFileName.lpstrFilter\r
49610         CALL     System.@LStrClr\r
49612         POP      EAX\r
49613         ADD      ESP, 76\r
49614         POP      EBX\r
49615 end;\r
49616 {$ELSE ASM_VERSION} //Pascal\r
49617 function TOpenSaveDialog.Execute: Boolean;\r
49618 const OpenSaveFlags: array[ TOpenSaveOption ] of Integer = (\r
49619       OFN_CREATEPROMPT,\r
49620       OFN_EXTENSIONDIFFERENT,\r
49621       OFN_FILEMUSTEXIST,\r
49622       OFN_HIDEREADONLY,\r
49623       OFN_NOCHANGEDIR,\r
49624       OFN_NODEREFERENCELINKS,\r
49625       OFN_ALLOWMULTISELECT,\r
49626       OFN_NONETWORKBUTTON,\r
49627       OFN_NOREADONLYRETURN,\r
49628       OFN_OVERWRITEPROMPT,\r
49629       OFN_PATHMUSTEXIST,\r
49630       OFN_READONLY,\r
49631       OFN_NOVALIDATE\r
49632       //{$IFDEF OpenSaveDialog_Extended}\r
49633       ,\r
49634       OFN_ENABLETEMPLATE,\r
49635       OFN_ENABLEHOOK\r
49636       //{$ENDIF}\r
49637       );\r
49638 var\r
49639   Ofn : TOpenFilename;\r
49640   Fltr : String;\r
49641   TempFilename : String;\r
49643   Function MakeFilter(s : string) : String;\r
49644   {\r
49645   format of filter for API call is following:\r
49646     'text files'#0'*.txt'#0\r
49647     'bitmap files'#0'*.bmp'#0#0\r
49648   }\r
49649   var Str: PChar;\r
49650   begin\r
49651     Result := s;\r
49652     if Result='' then\r
49653       exit;\r
49654     Result:=Result+#0; {Delphi string always end on #0 is this is #0#0}\r
49655     Str := PChar( Result );\r
49656     while Str^ <> #0 do\r
49657     begin\r
49658       if Str^ = '|' then\r
49659         Str^ := #0;\r
49660       Inc( Str );\r
49661     end;\r
49662   end;\r
49664 begin\r
49665   Fillchar( ofn, sizeof( ofn ), 0 );\r
49667   ofn.lStructSize:= 76; //to provide correct work in Win9x\r
49668   //sizeof(ofn); - by suggestion of Michael Morozov, 28-Nov-2001\r
49669   if fWnd <> 0 then\r
49670     ofn.hWndOwner := fWnd\r
49671   else\r
49672   if assigned(applet) then\r
49673     ofn.hwndOwner:=applet.Handle;\r
49675   ofn.hInstance:=HInstance;\r
49677   Fltr:=MakeFilter(FFilter);\r
49678   if Fltr <> '' then\r
49679     ofn.lpstrFilter:=pchar(Fltr);\r
49681   //ofn.lpstrCustomFilter:=nil;\r
49682   //ofn.nMaxCustFilter:=0;\r
49683   ofn.nFilterIndex:=FFilterIndex;\r
49685   if OSAllowMultiSelect in FOptions then\r
49686     ofn.nMaxFile:=High(word)-14    // by V.K. (exchanged condition)\r
49687   else\r
49688     ofn.nMaxFile:=MAX_PATH+2;\r
49690   TempFileName:=StringOfChar(#0,ofn.nMaxFile); {Vadim Petrov}\r
49691   ofn.lpstrFile:=StrLCopy(pchar(TempFileName), pchar(fFileName),\r
49692                    Min(ofn.nMaxFile,Length(fFileName)));\r
49694   ofn.lpstrInitialDir:=Pointer(FInitialDir);\r
49695   ofn.lpstrTitle:=Pointer(FTitle);\r
49696   ofn.Flags := MakeFlags( @FOptions, OpenSaveFlags )\r
49697             or OFN_EXPLORER or OFN_LONGNAMES or OFN_ENABLESIZING;\r
49699   ofn.lpstrDefExt:=PChar(FDefExtension);\r
49700   ofn.lCustData:=integer(@self);\r
49701   {$IFDEF OpenSaveDialog_Extended}\r
49702   ofn.lpTemplateName := PChar( TemplateName );\r
49703   ofn.lpfnHook := HookProc;\r
49704   {$ELSE}\r
49705   ofn.lpTemplateName:=nil;\r
49706   ofn.lpfnHook:=nil;\r
49707   {$ENDIF}\r
49708   if fOpenDialog then\r
49709     result:=GetOpenFileName(ofn)\r
49710   else\r
49711     result:=GetSaveFileName(ofn);\r
49712   if result then begin\r
49713     fFilterIndex := ofn.nFilterIndex; // by Vadim\r
49714     if OSAllowMultiSelect in foptions then begin\r
49715       FFileName:=copy(TempFileName, 1, pos(#0#0, tempfilename)-1);\r
49716       while pos(#0, ffilename) > 0 do begin\r
49717         FFilename[pos(#0, ffilename)]:=#13;\r
49718       end;\r
49719     end else\r
49720       FFileName:=copy(tempFileName, 1, pos(#0, TempFilename)\r
49721       -1 // by X.Y.B.\r
49722       );\r
49723   end else\r
49724     FFilename:='';\r
49725 end;\r
49726 {$ENDIF ASM_VERSION}\r
49728 { -- OpenDirDialog -- }\r
49730 //*\r
49731 //[function NewOpenDirDialog]\r
49732 function NewOpenDirDialog( const Title: String; Options: TOpenDirOptions ):\r
49733          POpenDirDialog;\r
49734 begin\r
49735   {-}\r
49736   New( Result, Create );\r
49737   {+}{++}(*Result := POpenDirDialog.Create;*){--}\r
49738   Result.FOptions := [ odOnlySystemDirs ];\r
49739   if Options <> [] then\r
49740     Result.FOptions := Options;\r
49741   Result.FTitle := Title;\r
49742 end;\r
49743 //[END NewOpenDirDialog]\r
49745 { TOpenDirDialog }\r
49747 {$IFDEF ASM_VERSION}\r
49748 //[destructor TOpenDirDialog.Destroy]\r
49749 destructor TOpenDirDialog.Destroy;\r
49750 asm     //cmd    //opd\r
49751         PUSH     EAX\r
49752         PUSH     0\r
49753         LEA      EDX, [EAX].FTitle\r
49754         PUSH     EDX\r
49755         LEA      EDX, [EAX].FInitialPath\r
49756         PUSH     EDX\r
49757         LEA      EAX, [EAX].FStatusText\r
49758 @@loo:  CALL     System.@LStrClr\r
49759         POP      EAX\r
49760         TEST     EAX, EAX\r
49761         JNZ      @@loo\r
49762         POP      EAX\r
49763         CALL     TObj.Destroy\r
49764 end;\r
49765 {$ELSE ASM_VERSION} //Pascal\r
49766 destructor TOpenDirDialog.Destroy;\r
49767 begin\r
49768   FTitle := '';\r
49769   FInitialPath := '';\r
49770   FStatusText := '';\r
49771   inherited;\r
49772 end;\r
49773 {$ENDIF ASM_VERSION}\r
49775 type\r
49776   {$IFNDEF _D2}\r
49777   (*IMalloc = interface(IUnknown)\r
49778     ['{00000002-0000-0000-C000-000000000046}']\r
49779     function Alloc(cb: Longint): Pointer; stdcall;\r
49780     function Realloc(pv: Pointer; cb: Longint): Pointer; stdcall;\r
49781     procedure Free(pv: Pointer); stdcall;\r
49782     function GetSize(pv: Pointer): Longint; stdcall;\r
49783     function DidAlloc(pv: Pointer): Integer; stdcall;\r
49784     procedure HeapMinimize; stdcall;\r
49785   end;*)\r
49786   {$ENDIF}\r
49788   PSHItemID = ^TSHItemID;\r
49789   TSHItemID = packed record\r
49790     cb: Word;                         { Size of the ID (including cb itself) }\r
49791     abID: array[0..0] of Byte;        { The item ID (variable length) }\r
49792   end;\r
49794   PItemIDList = ^TItemIDList;\r
49795   TItemIDList = record\r
49796      mkid: TSHItemID;\r
49797   end;\r
49799   PBrowseInfo = ^TBrowseInfo;\r
49800   TBrowseInfo = record\r
49801     hwndOwner: HWND;\r
49802     pidlRoot: PItemIDList;\r
49803     pszDisplayName: PAnsiChar;  { Return display name of item selected. }\r
49804     lpszTitle: PAnsiChar;      { text to go in the banner over the tree. }\r
49805     ulFlags: UINT;           { Flags that control the return stuff }\r
49806     lpfn: Pointer; //TFNBFFCallBack;\r
49807     lParam: LPARAM;          { extra info that's passed back in callbacks }\r
49808     iImage: Integer;         { output var: where to return the Image index. }\r
49809   end;\r
49811 //[API SHXXXXXXXXXX]\r
49812 function SHBrowseForFolder(var lpbi: TBrowseInfo): PItemIDList; stdcall;\r
49813   external 'shell32.dll' name 'SHBrowseForFolderA';\r
49814 function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall;\r
49815   external shell32 name 'SHGetPathFromIDListA';\r
49817 function CoTaskMemAlloc(cb : DWORD) : pointer; stdcall; external 'ole32.dll'\r
49818   name 'CoTaskMemAlloc';\r
49820 procedure CoTaskMemFree(pv: Pointer); stdcall; external 'ole32.dll'\r
49821   name 'CoTaskMemFree';\r
49823 const\r
49824   BIF_RETURNONLYFSDIRS   = $0001;  { For finding a folder to start document searching }\r
49825   BIF_DONTGOBELOWDOMAIN  = $0002;  { For starting the Find Computer }\r
49826   BIF_STATUSTEXT         = $0004;\r
49827   BIF_RETURNFSANCESTORS  = $0008;\r
49828   BIF_EDITBOX            = $0010;\r
49829   BIF_VALIDATE           = $0020;  { insist on valid result (or CANCEL) }\r
49830   BIF_BROWSEFORCOMPUTER  = $1000;  { Browsing for Computers. }\r
49831   BIF_BROWSEFORPRINTER   = $2000;  { Browsing for Printers }\r
49832   BIF_BROWSEINCLUDEFILES = $4000;  { Browsing for Everything }\r
49834   BFFM_INITIALIZED       = 1;\r
49835   BFFM_SELCHANGED        = 2;\r
49837   BFFM_SETSTATUSTEXT     = WM_USER + 100;\r
49838   BFFM_ENABLEOK          = WM_USER + 101;\r
49839   BFFM_SETSELECTION      = WM_USER + 102;\r
49842 {$IFDEF ASM_VERSION} // WndOwner\r
49843 //[function TOpenDirDialog.Execute]\r
49844 function TOpenDirDialog.Execute: Boolean;\r
49845 asm\r
49846         PUSH     EBX\r
49847         XCHG     EBX, EAX\r
49849         XOR      ECX, ECX\r
49850         PUSH     ECX             // prepare iImage = 0\r
49851         PUSH     EBX             // prepare lParam = @Self\r
49852         PUSH     [EBX].FCallBack // prepare lpfn = FCallBack\r
49853         LEA      EAX, [EBX].FOptions\r
49854         MOV      EDX, Offset[@@FlagsArray]\r
49855         MOV      CL, 5\r
49856         CALL     MakeFlags\r
49857         PUSH     EAX             // prepare ulFlags = Options\r
49858         PUSH     [EBX].FTitle    // prepare lpszTitle\r
49859         LEA      EAX, [EBX].FBuf\r
49860         PUSH     EAX             // prepare pszDisplayName\r
49861         PUSH     0               // prepare pidlRoot\r
49862         MOV      ECX, [EBX].fWnd\r
49863         INC      ECX\r
49864         LOOP     @@1\r
49865         MOV      ECX, Applet\r
49866         JECXZ    @@1\r
49867         MOV      ECX, [ECX].TControl.fHandle\r
49868 @@1:    PUSH     ECX             // prepare hwndOwner\r
49870         PUSH     ESP\r
49871         CALL     SHBrowseForFolder\r
49872         ADD      ESP, 32\r
49873         TEST     EAX, EAX\r
49874         JZ       @@exit\r
49876         PUSH     EAX\r
49878         LEA      EDX, [EBX].FBuf\r
49879         PUSH     EDX\r
49880         PUSH     EAX\r
49881         CALL     SHGetPathFromIDList\r
49883         CALL     CoTaskMemFree\r
49885         MOV      AL, 1\r
49886         JMP      @@fin\r
49888 @@FlagsArray:\r
49889         DD BIF_BROWSEFORCOMPUTER, BIF_BROWSEFORPRINTER, BIF_DONTGOBELOWDOMAIN\r
49890         DD BIF_RETURNFSANCESTORS, BIF_RETURNONLYFSDIRS, BIF_STATUSTEXT, BIF_BROWSEINCLUDEFILES\r
49892 @@exit: XOR      EAX, EAX\r
49893 @@fin:\r
49894         POP      EBX\r
49895 end;\r
49896 {$ELSE ASM_VERSION} //Pascal\r
49897 function TOpenDirDialog.Execute: Boolean;\r
49898 const FlagsArray: array[ TOpenDirOption ] of Integer =\r
49899       ( BIF_BROWSEFORCOMPUTER, BIF_BROWSEFORPRINTER, BIF_DONTGOBELOWDOMAIN,\r
49900         BIF_RETURNFSANCESTORS, BIF_RETURNONLYFSDIRS, BIF_STATUSTEXT,\r
49901         BIF_BROWSEINCLUDEFILES );\r
49902 var BI : TBrowseInfo;\r
49903     Browse : PItemIdList;\r
49904 begin\r
49905   Result := False;\r
49906   if WndOwner <> 0 then\r
49907     BI.hwndOwner := WndOwner\r
49908   else\r
49909   if assigned( Applet ) then\r
49910     BI.hwndOwner := Applet.Handle\r
49911   else\r
49912     BI.hwndOwner := 0;\r
49913   BI.pidlRoot  := nil;\r
49914   BI.pszDisplayName := @FBuf[ 0 ];\r
49915   BI.lpszTitle := PChar( Title );\r
49916   BI.ulFlags   := MakeFlags( @FOptions, FlagsArray );\r
49917   BI.lpfn := FCallBack;\r
49918   BI.lParam := Integer( @Self );\r
49919   Browse := SHBrowseForFolder( BI );\r
49920   if Browse <> nil then\r
49921   begin\r
49922     SHGetPathFromIDList( Browse, @FBuf[ 0 ] );\r
49923     CoTaskMemFree( Browse );\r
49924     Result := True;\r
49925   end;\r
49926 end;\r
49927 {$ENDIF ASM_VERSION}\r
49929 //[function TOpenDirDialog.GetInitialPath]\r
49930 function TOpenDirDialog.GetInitialPath: String;\r
49931 begin\r
49932   Result := IncludeTrailingPathDelimiter( fInitialPath );\r
49933 end;\r
49935 //[function TOpenDirDialog.GetPath]\r
49936 function TOpenDirDialog.GetPath: String;\r
49937 begin\r
49938   Result := FBuf;\r
49939 end;\r
49941 //[FUNCTION OpenDirSelChangeCallBack]\r
49942 {$IFDEF ASM_VERSION}\r
49943 function OpenDirSelChangeCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ):\r
49944          Integer; stdcall;\r
49945 asm\r
49946         MOV      EAX, [lpData]\r
49947         MOV      ECX, [EAX].TOpenDirDialog.FOnSelChanged.TMethod.Code\r
49948         JECXZ    @@exit\r
49950         LEA      EDX, [EAX].TOpenDirDialog.FBuf\r
49951         PUSH     EDX\r
49952         PUSH     [lParam]\r
49953         CALL     SHGetPathFromIDList\r
49955         //EnableOK := 0;\r
49956         //Self_.FOnSelChanged( Self_, Self_.FBuf, EnableOK, Self_.FStatusText );\r
49958         MOV      EDX, [lpData]\r
49959         LEA      ECX, [EDX].TOpenDirDialog.FBuf\r
49960         PUSH     0\r
49961         PUSH     ESP\r
49962         LEA      EAX, [EDX].TOpenDirDialog.FStatusText\r
49963         PUSH     EAX\r
49964         MOV      EAX, [EDX].TOpenDirDialog.FOnSelChanged.TMethod.Data\r
49965         CALL     dword ptr [EDX].TOpenDirDialog.FOnSelChanged.TMethod.Code\r
49966         POP      ECX\r
49967         JECXZ    @@1\r
49969         INC      ECX\r
49970         PUSH     ECX\r
49971         PUSH     0\r
49972         PUSH     BFFM_ENABLEOK\r
49973         PUSH     [Wnd]\r
49974         CALL     SendMessage\r
49975 @@1:\r
49976         MOV      EDX, [lpData]\r
49977         MOV      ECX, [EDX].TOpenDirDialog.FStatusText\r
49978         JECXZ    @@exit\r
49980         PUSH     ECX\r
49981         PUSH     0\r
49982         PUSH     BFFM_SETSTATUSTEXT\r
49983         PUSH     [Wnd]\r
49984         CALL     SendMessage\r
49986 @@exit: XOR      EAX, EAX\r
49987 end;\r
49988 {$ELSE ASM_VERSION} //Pascal\r
49989 function OpenDirSelChangeCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ):\r
49990          Integer; stdcall;\r
49991 var _Self_: POpenDirDialog;\r
49992     EnableOK: Integer;\r
49993 begin\r
49994   _Self_ := Pointer( lpData );\r
49995   if assigned( _Self_.FOnSelChanged ) then\r
49996   begin\r
49997     SHGetPathFromIDList( PItemIDList( lParam ), @ _Self_.FBuf[ 0 ] );\r
49998     EnableOK := 0;\r
49999     _Self_.FOnSelChanged( _Self_, _Self_.FBuf, EnableOK, _Self_.FStatusText );\r
50000     if EnableOK <> 0 then\r
50001        SendMessage( Wnd, BFFM_ENABLEOK, 0, EnableOK + 1 );\r
50002     if _Self_.FStatusText <> '' then\r
50003        SendMessage( Wnd, BFFM_SETSTATUSTEXT, 0, Integer( PChar( _Self_.FStatusText ) ) );\r
50004   end;\r
50005   Result := 0;\r
50006 end;\r
50007 {$ENDIF ASM_VERSION}\r
50008 //[END OpenDirSelChangeCallBack]\r
50010 //[FUNCTION OpenDirCallBack]\r
50011 {$IFDEF ASM_VERSION}\r
50012 function OpenDirCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ): Integer;\r
50013          stdcall;\r
50014 asm\r
50015         MOV      EAX, [Wnd]\r
50016         MOV      EDX, [lpData]\r
50017         MOV      ECX, [Msg]\r
50018         LOOP     @@chk_sel_chg\r
50019         // Msg = 1 -> BFFM_Initialized\r
50021         MOV      ECX, [EDX].TOpenDirDialog.FCenterProc\r
50022         JECXZ    @@1\r
50023         PUSH     EDX\r
50024         CALL     ECX\r
50025         POP      EDX\r
50026 @@1:    MOV      ECX, [EDX].TOpenDirDialog.FInitialPath\r
50027         JECXZ    @@exit\r
50028         PUSH     ECX\r
50029         PUSH     1\r
50030         PUSH     BFFM_SETSELECTION\r
50031         PUSH     [Wnd]\r
50032         CALL     SendMessage\r
50033         JMP      @@exit\r
50035 @@chk_sel_chg:\r
50036         LOOP     @@exit\r
50037         // Msg = 2 -> BFFM_SelChanged\r
50039         MOV      ECX, [EDX].TOpenDirDialog.FDoSelChanged\r
50040         JECXZ    @@exit\r
50041         POP      EBP\r
50042         JMP      ECX\r
50044 @@exit: XOR      EAX, EAX\r
50045 end;\r
50046 {$ELSE ASM_VERSION} //Pascal\r
50047 function OpenDirCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ): Integer;\r
50048          stdcall;\r
50049 var Self_ : POpenDirDialog;\r
50050 begin\r
50051   Self_ := Pointer( lpData );\r
50052   if Msg = BFFM_INITIALIZED then\r
50053   begin\r
50054     if assigned( Self_.FCenterProc ) then\r
50055        Self_.FCenterProc( Wnd );\r
50056     if Self_.FInitialPath <> '' then\r
50057       SendMessage( Wnd, BFFM_SETSELECTION, 1, Integer( PChar( Self_.FInitialPath ) ) );\r
50058   end\r
50059      else\r
50060   if Msg = BFFM_SELCHANGED then\r
50061   begin\r
50062     if assigned( Self_.FDoSelChanged ) then\r
50063       Self_.FDoSelChanged( Wnd, Msg, lParam, lpData );\r
50064   end;\r
50065   Result := 0;\r
50066 end;\r
50067 {$ENDIF ASM_VERSION}\r
50068 //[END OpenDirCallBack]\r
50070 //[PROCEDURE OpenDirDlgCenter]\r
50071 {$IFDEF ASM_VERSION}\r
50072 procedure OpenDirDlgCenter( Wnd: HWnd );\r
50073 asm\r
50074         PUSH     EBX\r
50075         MOV      EBX, EAX\r
50077         ADD      ESP, -16\r
50078         PUSH     ESP\r
50079         PUSH     EAX\r
50080         CALL     GetWindowRect\r
50081         POP      EDX          // EDX = Left\r
50082         POP      ECX          // ECX = Top\r
50083         POP      EAX          // EAX = Right\r
50084         SUB      EAX, EDX     // EAX = W\r
50085         POP      EDX          // EDX = Bottom\r
50086         SUB      EDX, ECX     // EDX = H\r
50087         XOR      ECX, ECX\r
50088         INC      ECX\r
50089         PUSH     ECX  // prepare True\r
50090         PUSH     EDX  // prepare H\r
50091         PUSH     EAX  // prepare W\r
50093         INC      ECX\r
50094 @@1:\r
50095         PUSH     ECX\r
50097         DEC      ECX\r
50098         PUSH     ECX\r
50099         CALL     GetSystemMetrics\r
50101         POP      ECX\r
50102         SUB      EAX, [ESP+4]\r
50103         SAR      EAX, 1\r
50104         PUSH     EAX\r
50106         LOOP     @@1\r
50108         {\r
50109         PUSH     SM_CYSCREEN\r
50110         CALL     GetSystemMetrics\r
50111         SUB      EAX, [ESP+4]\r
50112         SAR      EAX, 1\r
50113         PUSH     EAX\r
50115         PUSH     SM_CXSCREEN\r
50116         CALL     GetSystemMetrics\r
50117         SUB      EAX, [ESP+4]\r
50118         SAR      EAX, 1\r
50119         PUSH     EAX\r
50120         }\r
50122         PUSH     EBX\r
50123         CALL     MoveWindow\r
50124         POP      EBX\r
50125 end;\r
50126 {$ELSE ASM_VERSION} //Pascal\r
50127 procedure OpenDirDlgCenter( Wnd: HWnd );\r
50128 var R: TRect;\r
50129     W, H: Integer;\r
50130 begin\r
50131   GetWindowRect( Wnd, R );\r
50132   W := R.Right - R.Left;\r
50133   H := R.Bottom - R.Top;\r
50134   R.Left := (GetSystemMetrics( SM_CXSCREEN ) - W) div 2;\r
50135   R.Top := (GetSystemMetrics( SM_CYSCREEN ) - H) div 2;\r
50136   MoveWindow( Wnd, R.Left, R.Top, W, H, True );\r
50137 end;\r
50138 {$ENDIF ASM_VERSION}\r
50139 //[END OpenDirDlgCenter]\r
50141 {$IFDEF ASM_VERSION}\r
50142 //[procedure TOpenDirDialog.SetCenterOnScreen]\r
50143 procedure TOpenDirDialog.SetCenterOnScreen(const Value: Boolean);\r
50144 asm\r
50145         MOV      [EAX].FCenterOnScreen, DL\r
50146         MOVZX    ECX, DL\r
50147         JECXZ    @@1\r
50148         MOV      ECX, Offset[OpenDirDlgCenter]\r
50149 @@1:    MOV      [EAX].FCenterProc, ECX\r
50150 end;\r
50151 {$ELSE ASM_VERSION} //Pascal\r
50152 procedure TOpenDirDialog.SetCenterOnScreen(const Value: Boolean);\r
50153 var P: procedure( Wnd: HWnd );\r
50154 begin\r
50155   FCenterOnScreen := Value;\r
50156   P := nil;\r
50157   if Value then\r
50158     P := @OpenDirDlgCenter;\r
50159   FCenterProc := P;\r
50160 end;\r
50161 {$ENDIF ASM_VERSION}\r
50163 //[procedure TOpenDirDialog.SetInitialPath]\r
50164 procedure TOpenDirDialog.SetInitialPath(const Value: String);\r
50165 begin\r
50166   FCallBack := @OpenDirCallBack;\r
50167   FInitialPath := ExcludeTrailingPathDelimiter( Value );\r
50168 end;\r
50170 //[procedure TOpenDirDialog.SetOnSelChanged]\r
50171 procedure TOpenDirDialog.SetOnSelChanged(const Value: TOnODSelChange);\r
50172 begin\r
50173   FOnSelChanged := Value;\r
50174   FCallBack := @OpenDirCallBack;\r
50175   FDoSelChanged := @OpenDirSelChangeCallBack;\r
50176 end;\r
50179 type\r
50180   PByteArray    =^TByteArray;\r
50181   TByteArray    = array[Word]of Byte;\r
50183 //[API CreateMappedBitmap]\r
50184 function CreateMappedBitmap(Instance: THandle; Bitmap: Integer;\r
50185   Flags: UINT; ColorMap: PColorMap; NumMaps: Integer): HBitmap; stdcall;\r
50186   external cctrl name 'CreateMappedBitmap';\r
50188 //[function CreateMappedBitmapEx]\r
50189 function CreateMappedBitmapEx(Instance: THandle; BmpRsrcName: PChar; Flags:\r
50190 Cardinal; ColorMap: PColorMap; NumMaps: Integer): HBitmap;\r
50191 var bi: TBITMAPINFO;\r
50192     DC, tmcl: Cardinal;\r
50193     Bits: PByteArray;\r
50194     i, j, k, CO, bps: Integer;\r
50195     tm: array [1..4] of byte absolute tmcl;\r
50196     bm: Windows.TBITMAP;\r
50197     CM: PColorMap;\r
50198     DW: HWnd;\r
50199 begin\r
50200   Result := LoadBitmap( Instance, BmpRsrcName );\r
50201   if Result = 0 then\r
50202   begin\r
50203     {$IFDEF DEBUG}\r
50204     ShowMessage( 'Can not load bitmap ' + BmpRsrcName + ', error ' +\r
50205                  Int2Str( GetLastError ) + ': ' + SysErrorMessage( GetLastError ) );\r
50206     {$ENDIF}\r
50207     Exit;\r
50208   end;\r
50209   DW := GetDesktopWindow;\r
50210   DC := GetDC(DW);\r
50211   FillChar( bm, SizeOf(bm), 0 );\r
50212   GetObject( Result, SizeOf( bm ), @bm );\r
50214   FillChar( bi, SizeOf( bi ), 0 );\r
50215   bi.bmiHeader.biSize := SizeOf( bi.bmiHeader );\r
50216   bi.bmiHeader.biWidth := bm.bmWidth;\r
50217   bi.bmiHeader.biHeight := -bm.bmHeight;\r
50218   bi.bmiHeader.biPlanes := 1;\r
50219   bi.bmiHeader.biBitCount := 24;\r
50220 // BitCout - always 24 for easy algorythm\r
50221   bi.bmiHeader.biCompression:=BI_RGB;\r
50222   bps := CalcScanLineSize( @bi.bmiHeader );\r
50224   GetMem( Bits, bps * bm.bmHeight );\r
50225   GetDIBits( DC, Result, 0, bm.bmHeight, @Bits[0], bi, DIB_RGB_COLORS );\r
50226   DeleteObject( Result );\r
50228   for i := 0 to bm.bmHeight - 1 do begin\r
50229       for j := 0 to bm.bmWidth - 1 do begin\r
50230           CO := bps * i + 3 * j;\r
50231           for k := 0 to NumMaps - 1 do begin\r
50232               CM := Pointer( Integer( ColorMap ) + SizeOf( TColorMap ) * k );\r
50233               if RGB( Bits[CO+2], Bits[CO+1], Bits[CO] ) = CM.cFrom then\r
50234               begin\r
50235                   tmcl := CM.cTo;\r
50236                   tm[4]:=tm[1];\r
50237                   tm[1]:=tm[3];\r
50238                   tm[3]:=tm[4];\r
50239                   Move( tmcl, Bits[CO], 3);\r
50240               end;\r
50241           end;\r
50242       end;\r
50243   end;\r
50244   Result := CreateDIBitmap( DC, bi.bmiHeader, CBM_INIT, @Bits[0], bi,\r
50245     DIB_RGB_COLORS );\r
50246   ReleaseDC( DW, DC );\r
50247   FreeMem( Bits );\r
50248 end;\r
50250 //*\r
50251 //[function LoadMappedBitmap]\r
50252 function LoadMappedBitmap( hInst: THandle; BmpResID: Integer; const Map: array of TColor )\r
50253          : HBitmap;\r
50254 var Map2Pass: Pointer;\r
50255 begin\r
50256   Map2Pass := nil;\r
50257   if High( Map ) > 0 then\r
50258     Map2Pass := PColorMap( @Map[ 0 ] );\r
50259   Result := CreateMappedBitmap( hInst, BmpResID, 0, Map2Pass, (High( Map ) + 1) div 2 );\r
50260 end;\r
50262 //[function LoadMappedBitmapEx]\r
50263 function LoadMappedBitmapEx( MasterObj: PObj; hInst: THandle; BmpResName: PChar; const Map: array of TColor )\r
50264          : HBitmap;\r
50265 var Map2Pass: Pointer;\r
50266 begin\r
50267   Map2Pass := nil;\r
50268   if High( Map ) > 0 then\r
50269     Map2Pass := PColorMap( @Map[ 0 ] );\r
50270   Result := CreateMappedBitmapEx( hInst, BmpResName, 0, Map2Pass, (High( Map ) + 1) div 2 );\r
50271   if MasterObj <> nil then\r
50272     MasterObj.Add2AutoFreeEx( TObjectMethod( MakeMethod( Pointer( Result ), @ FreeBmp ) ) );\r
50273 end;\r
50275 { -- Toolbar -- }\r
50277 {$IFDEF ASM_noVERSION} // width\r
50278 //[procedure TControl.TBAddBitmap]\r
50279 procedure TControl.TBAddBitmap(Bitmap: HBitmap);\r
50280 const szBI = sizeof(TBitmapInfo);\r
50281 asm\r
50282         TEST     EDX, EDX\r
50283         JZ       @@exit\r
50284         JGE      @@1\r
50285         CMP      EDX, -6\r
50286         JL       @@1\r
50288         NEG      EDX\r
50289         DEC      EDX\r
50290         PUSH     EDX\r
50291         PUSH     -1\r
50292         XOR      EDX, EDX\r
50293         JMP      @@2\r
50295 @@1:    PUSH     EDX    // AB.hInst = Bitmap\r
50296         PUSH     0      // AB.nID = 0\r
50298         PUSH     EAX    // > @Self\r
50299         ADD      ESP, -szBI\r
50300         PUSH     ESP\r
50301         PUSH     szBI\r
50302         PUSH     EDX\r
50303         CALL     GetObject\r
50304         TEST     EAX, EAX\r
50305         JG       @@11\r
50307         ADD      ESP, szBI\r
50308         JMP      @@exit\r
50310 @@11:   MOV      EAX, [ESP].TBitmapInfo.bmiHeader.biWidth\r
50311         MOV      ECX, [ESP].TBitmapInfo.bmiHeader.biHeight\r
50312         TEST     ECX, ECX\r
50313         JGE      @@12\r
50314         NEG      ECX\r
50315 @@12:   ADD      ESP, szBI\r
50316         CDQ                  // EDX = 0\r
50317         DIV      ECX         // EAX = N\r
50318         XCHG     EAX, [ESP]  // > N\r
50319         PUSH     EAX         // > @Self\r
50321         MOV      EDX, ECX\r
50322         SHL      EDX, 16\r
50323         OR       ECX, EDX\r
50324         CDQ\r
50325         PUSH     EDX\r
50326         PUSH     EDX\r
50327         PUSH     TB_AUTOSIZE\r
50328         PUSH     EAX\r
50330         PUSH     ECX\r
50331         PUSH     EDX\r
50332         PUSH     TB_SETBITMAPSIZE\r
50333         PUSH     EAX\r
50334         CALL     Perform\r
50335         CALL     Perform\r
50336         POP      EAX\r
50337         POP      EDX\r
50339 @@2:    PUSH     ESP\r
50340         PUSH     EDX\r
50341         PUSH     TB_ADDBITMAP\r
50342         PUSH     EAX\r
50343         CALL     Perform\r
50344         POP      ECX\r
50345         POP      ECX\r
50346 @@exit:\r
50347 end;\r
50348 {$ELSE ASM_VERSION} //Pascal\r
50349 procedure TControl.TBAddBitmap(Bitmap: HBitmap);\r
50350 const NstdBitmaps: array[ 0..5 ] of DWORD = ( 15, 15, 0, 0, 13, 13 );\r
50351 var BI: TBitmapInfo;\r
50352     AB: TTBAddBitmap;\r
50353     N, W: Integer;\r
50354 begin\r
50355   if Bitmap = 0 then Exit;\r
50356   if (Integer( Bitmap ) >= -10) and (Integer( Bitmap ) <= -1) then\r
50357   begin\r
50358     AB.hInst := THandle(-1);\r
50359     AB.nID := -Integer(Bitmap) - 1;\r
50360     N := 0; //NstdBitmaps[ AB.nID ]; // (this value is ignored)\r
50361   end\r
50362      else\r
50363   if GetObject( Bitmap, sizeof( TBitmapInfo ), @BI ) > 0 then\r
50364   begin\r
50365     AB.hInst := 0;\r
50366     AB.nID := Bitmap;\r
50367     W := fTBBtnImgWidth;\r
50368     if W = 0 then\r
50369       W := Abs( BI.bmiHeader.biHeight );\r
50370     N := BI.bmiHeader.biWidth div W;\r
50371     Perform( TB_SETBITMAPSIZE, 0, MAKELONG( W, Abs(BI.bmiHeader.biHeight )) );\r
50372     Perform( TB_AUTOSIZE, 0, 0 );\r
50373   end\r
50374     else Exit;\r
50375   Perform( TB_ADDBITMAP, N, Integer( @AB ) );\r
50376 end;\r
50377 {$ENDIF ASM_VERSION}\r
50379 var ToolbarsIDcmd: Integer = 100;\r
50380 {$IFDEF ASM_VERSION}\r
50381 //[function TControl.TBAddInsButtons]\r
50382 function TControl.TBAddInsButtons(Idx: Integer; const Buttons: array of PChar;\r
50383   const BtnImgIdxArray: array of Integer): Integer; stdcall;\r
50384 asm\r
50385         { [EBP+$8] = @Self\r
50386           [EBP+$C] = Idx\r
50387           [EBP+$10] = Buttons\r
50388           [EBP+$14] = High(Butons)\r
50389           [EBP+$18] = BtnImgIdxArray\r
50390           [EBP+$1C] = High(BtnImgIdxArray)\r
50391         }\r
50392         PUSH     EBX\r
50393         PUSH     ESI\r
50394         PUSH     EDI\r
50395         OR       EBX, -1\r
50396         MOV      EAX, 20\r
50397         MOV      ECX, [EBP+$14]\r
50398         CMP      ECX, EBX\r
50399         JLE      @@fin\r
50400         INC      ECX\r
50401         MUL      ECX\r
50402         CALL     System.@GetMem\r
50403         PUSH     EAX           // save AB to FreeMem after\r
50404         MOV      EDX, EBX\r
50405         DEC      EDX           // nBmp := -2\r
50407         MOV      ECX, [EBP+$14]\r
50408         INC      ECX\r
50409         JZ       @@exit\r
50411         MOV      ECX, [EBP+$1C]\r
50412         INC      ECX\r
50413         JZ       @@1\r
50414         MOV      ECX, [BtnImgIdxArray]\r
50415         MOV      EDX, [ECX]\r
50416         DEC      EDX           // nBmp := BtnImgIdxArray[ 0 ] - 1\r
50417 @@1:    MOV      ECX, [EBP+$14]\r
50418         INC      ECX\r
50419         MOV      ESI, [Buttons]\r
50420         MOV      EDI, EAX      // EDI = PAB\r
50421         PUSH     0             // N:=0 in [EBP-$14]\r
50422         // -- impossible?-- JZ       @@break\r
50423 @@loop:\r
50424         LODSD\r
50425         TEST     EAX, EAX\r
50426         JZ       @@break\r
50427         //CMP      byte ptr [EAX], 0\r
50428         //JZ       @@break\r
50429         PUSH     ECX\r
50431         CMP      word ptr [EAX], '-'\r
50432         JNE      @@2\r
50434         OR       EAX, -1\r
50435         STOSD\r
50436         //INC      EAX   //=0\r
50437         MOV      EAX, [ToolbarsIDcmd]\r
50438         TEST     EBX, EBX\r
50439         {$IFDEF USE_CMOV}\r
50440         CMOVL    EBX, EAX\r
50441         {$ELSE}\r
50442         JGE      @@b0\r
50443         MOV      EBX, EAX\r
50444 @@b0:   {$ENDIF}\r
50446         //INC      [ToolbarsIDcmd]\r
50447         STOSD\r
50448         XOR      EAX, EAX\r
50449         INC      AH  // TBSTYLE_SEP = 1\r
50450         STOSD\r
50451         DEC      AH\r
50452         STOSD\r
50453         DEC      EAX\r
50454         JMP      @@3\r
50456         DD       -1, 1\r
50457 @@0:    DB       0\r
50459 @@2:\r
50460         INC      EDX  // Inc( nBmp )\r
50461         PUSH     EAX\r
50463         MOV      EAX, [EBP+$1C]\r
50464         MOV      ECX, [EBP-$14]\r
50465         CMP      EAX, ECX\r
50466         MOV      EAX, EDX\r
50467         JL       @@21\r
50468         MOV      EAX, [BtnImgIdxArray]\r
50469         MOV      EAX, [EAX+ECX*4]\r
50470 @@21:   STOSD\r
50472         TEST     EDX, EDX\r
50473         JGE      @@2a\r
50474         DEC      EDX\r
50475 @@2a:\r
50477         MOV      EAX, [ToolbarsIDcmd]\r
50478         //INC      [ToolbarsIDcmd]\r
50479         STOSD\r
50480         TEST     EBX, EBX\r
50481         {$IFDEF USE_CMOV}\r
50482         CMOVL    EBX, EAX\r
50483         {$ELSE}\r
50484         JGE      @@210\r
50485         MOV      EBX, EAX\r
50486 @@210:  {$ENDIF}\r
50488         POP      ECX\r
50489         MOV      AX, $1004 // AL=fsState=_ENABLED, AH=fsStyle=_AUTOSIZE\r
50490         CMP      byte ptr [ECX], '^'\r
50491         JNE      @@22\r
50492         MOV      AH, TBSTYLE_DROPDOWN or TBSTYLE_AUTOSIZE\r
50493         INC      ECX\r
50494 @@22:   CMP      byte ptr [ECX], '-'\r
50495         JZ       @@23\r
50496         CMP      byte ptr [ECX], '+'\r
50497         JNZ      @@24\r
50498         MOV      AL, TBSTATE_ENABLED or TBSTATE_CHECKED\r
50499 @@23:   INC      ECX\r
50500         OR       AH, TBSTYLE_CHECK\r
50501         CMP      byte ptr [ECX], '!'\r
50502         JNZ      @@24\r
50503         OR       AH, TBSTYLE_GROUP\r
50504         INC      ECX\r
50505 @@24:   STOSD\r
50506         MOV      EAX, [EBP+8]\r
50507         STOSD\r
50508         OR       EAX, -1\r
50509         CMP      word ptr [ECX], ' '\r
50510         JZ       @@3\r
50511         CMP      byte ptr [ECX], 0\r
50512         JZ       @@3\r
50514         PUSH     EDX\r
50515         PUSH     0\r
50516         MOV      EDX, ECX\r
50517         MOV      EAX, ESP\r
50518         CALL     System.@LStrFromPChar\r
50519         MOV      EAX, ESP\r
50520         MOV      EDX, offset[@@0]\r
50521         CALL     System.@LStrCat\r
50522         PUSH     dword ptr [ESP]\r
50523         PUSH     0\r
50524         PUSH     TB_ADDSTRING\r
50525         PUSH     dword ptr [EBP+8]\r
50526         CALL     Perform\r
50527         STOSD\r
50529         CALL     RemoveStr\r
50530         POP      EDX\r
50531         JMP      @@30\r
50533 @@3:    STOSD\r
50534 @@30:   INC      dword ptr [EBP-$14]\r
50535         INC      [ToolbarsIDcmd]\r
50536         POP      ECX\r
50537         DEC      ECX\r
50538         JNZ      @@loop\r
50539 @@break:\r
50540         POP      ECX\r
50541         JECXZ    @@exit\r
50542         PUSH     dword ptr [ESP]\r
50543         MOV      EAX, [Idx]\r
50544         TEST     EAX, EAX\r
50545         JGE      @@31\r
50547         PUSH     ECX\r
50548         PUSH     TB_ADDBUTTONS\r
50549         JMP      @@32\r
50550 @@31:\r
50551         PUSH     EAX\r
50552         PUSH     TB_INSERTBUTTON\r
50553 @@32:\r
50554         PUSH     dword ptr [EBP+8]\r
50555         CALL     Perform\r
50556 @@exit:\r
50557         POP      EAX\r
50558         //TEST     EAX, EAX\r
50559         //JZ       @@fin\r
50560         CALL     System.@FreeMem\r
50562 @@fin:\r
50563         POP      EDI\r
50564         POP      ESI\r
50565         XCHG     EAX, EBX\r
50566         POP      EBX\r
50567 end;\r
50568 {$ELSE ASM_VERSION} //Pascal\r
50569 function TControl.TBAddInsButtons(Idx: Integer; const Buttons: array of PChar;\r
50570   const BtnImgIdxArray: array of Integer): Integer; stdcall;\r
50572       function AddInsButtons: Integer;\r
50573       type TTBBtnArray = array[ 0..100000 ] of TTBButton;\r
50574            PTBBtnArray = ^TTBBtnArray;\r
50575       var AB: PTBBtnArray;\r
50576           I, N, nBmp: Integer;\r
50577           PAB: PTBButton;\r
50578           Str: PChar;\r
50579       begin\r
50580         Result := -1;\r
50581         AB := nil;\r
50582         if High( Buttons ) >= 0 then\r
50583           GetMem( AB, Sizeof( TTBButton ) * (High(Buttons) + 1) );\r
50584         N := 0;\r
50585         PAB := @AB[ 0 ];\r
50586         nBmp := -2;\r
50587         if High(BtnImgIdxArray) >= 0 then\r
50588           nBmp := BtnImgIdxArray[ 0 ] - 1;\r
50589         for I:= 0 to High( Buttons ) do\r
50590         begin\r
50591           if Buttons[ I ] = nil then break;\r
50593           {if High( BtnImgIdxArray ) >= 0 then\r
50594             if I > High( BtnImgIdxArray ) then\r
50595               nBmp := -3;}\r
50597           if Buttons[ I ] = {$IFDEF F_P}''+{$ENDIF} '-' then\r
50598           begin\r
50599             PAB.iBitmap := -1;\r
50600             //PAB.idCommand := 0;\r
50601             PAB.fsState := 0;\r
50602             PAB.fsStyle := TBSTYLE_SEP;\r
50603             PAB.iString := -1;\r
50604           end\r
50605              else\r
50606           begin\r
50607             Str := Buttons[ I ];\r
50608             Inc( nBmp );\r
50609             PAB.iBitmap := nBmp;\r
50610             if nBmp < 0 then\r
50611               Dec( nBmp );\r
50612             if High( BtnImgIdxArray ) >= N then\r
50613               PAB.iBitmap := BtnImgIdxArray[ N ];\r
50614             {PAB.idCommand := ToolbarsIDcmd;\r
50615             if Result < 0 then Result := PAB.idCommand;\r
50616             Inc( ToolbarsIDcmd );}\r
50617             PAB.fsState := TBSTATE_ENABLED;\r
50618             PAB.fsStyle := TBSTYLE_BUTTON or TBSTYLE_AUTOSIZE;\r
50619             if Str^ = '^' then\r
50620             begin\r
50621               PAB.fsStyle := TBSTYLE_DROPDOWN or TBSTYLE_AUTOSIZE;\r
50622               Inc( Str );\r
50623             end;\r
50624             if Str^ in [ '-', '+' ] then\r
50625             begin\r
50626               PAB.fsStyle := PAB.fsStyle or TBSTYLE_CHECK;\r
50627               if Str^ = '+' then\r
50628                 PAB.fsState := PAB.fsState or TBSTATE_CHECKED;\r
50629               Inc( Str );\r
50630               if Str^ = '!' then\r
50631               begin\r
50632                 PAB.fsStyle := PAB.fsStyle or TBSTYLE_GROUP;\r
50633                 Inc( Str );\r
50634               end;\r
50635             end;\r
50636             if (Str =  {$IFDEF F_P}''+{$ENDIF} ' ') or (Str^ = #0) then\r
50637               PAB.iString := -1\r
50638                 //Perform( TB_ADDSTRING, 0, Integer( PChar( '' + #0 ) ) )\r
50639                 // an experiment: is it possible to remove space right to image\r
50640                 // without setting tboTextBottom option (non compatible with FixFlatXP)\r
50641                 // answer: seems not possible.\r
50642             else\r
50643               PAB.iString :=\r
50644                 Perform( TB_ADDSTRING, 0, Integer( PChar( '' + Str + #0 ) ) );\r
50645           end;\r
50647           PAB.idCommand := ToolbarsIDcmd;\r
50648           if Result < 0 then Result := PAB.idCommand;\r
50649           Inc( ToolbarsIDcmd );\r
50651           PAB.dwData := Integer( @Self );\r
50652           Inc( N );\r
50653           Inc( PAB );\r
50654         end;\r
50655         if N > 0 then\r
50656         begin\r
50657           if Idx < 0 then\r
50658             Perform( TB_ADDBUTTONS, N, Integer( @AB[ 0 ] ) )\r
50659           else\r
50660             Perform( TB_INSERTBUTTON, Idx, Integer( @AB[ 0 ] ) );\r
50661         end;\r
50662         if AB <> nil then\r
50663           FreeMem( AB );\r
50664       end;\r
50665 begin\r
50666   if High( Buttons ) < 0 then\r
50667     Result := -1\r
50668   else\r
50669     Result := AddInsButtons;\r
50670 end;\r
50671 {$ENDIF ASM_VERSION}\r
50673 {$IFDEF ASM_VERSION}\r
50674 //[function TControl.TBAddButtons]\r
50675 function TControl.TBAddButtons(const Buttons: array of PChar;\r
50676          const BtnImgIdxArray: array of Integer): Integer;\r
50677 asm\r
50678         PUSH     dword ptr [EBP+8]\r
50679         PUSH     dword ptr [EBP+12]\r
50680         PUSH     ECX\r
50681         PUSH     EDX\r
50682         PUSH     -1\r
50683         PUSH     EAX\r
50684         CALL     TBAddInsButtons\r
50685 end;\r
50686 {$ELSE ASM_VERSION} //Pascal\r
50687 function TControl.TBAddButtons(const Buttons: array of PChar;\r
50688          const BtnImgIdxArray: array of Integer): Integer;\r
50689 begin\r
50690   Result := TBAddInsButtons( -1, Buttons, BtnImgIdxArray );\r
50691 end;\r
50692 {$ENDIF ASM_VERSION}\r
50694 //*\r
50695 //[function TControl.TBInsertButtons]\r
50696 function TControl.TBInsertButtons(BeforeIdx: Integer;\r
50697   Buttons: array of PChar; BtnImgIdxArray: array of Integer): Integer;\r
50698 var I, J, K: Integer;\r
50699 begin\r
50700   J := -1;\r
50701   Result := -1;\r
50702   for I := 0 to High( Buttons ) do\r
50703   begin\r
50704     if I <= High( BtnImgIdxArray ) then\r
50705       J := BtnImgIdxArray[ I ]\r
50706     else\r
50707       if J >= 0 then Inc( J );\r
50708     K := TBAddInsButtons( BeforeIdx, [ Buttons[ I ], '' ], [ J ] );\r
50709     if Result < 0 then Result := K;\r
50710   end;\r
50711 end;\r
50713 //[function GetTBBtnGoodID]\r
50714 function GetTBBtnGoodID( Toolbar: PControl; BtnIDorIdx: Integer ): Integer;\r
50715 // change by Alexander Pravdin (to fix toolbar with separator first):\r
50716 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
50717 var Btn1st, i: Integer; btn: TTBButton;\r
50718 begin\r
50719   Result := BtnIDorIdx;\r
50720   Btn1st := 0;\r
50721   for i := 0 to Toolbar.TBButtonCount - 1 do begin\r
50722     Toolbar.Perform( TB_GETBUTTON, i, Integer( @btn ) );\r
50723     if btn.fsStyle <> TBSTYLE_SEP then begin\r
50724         Btn1st := i;\r
50725         Break;\r
50726     end;\r
50727   end;\r
50728   if Result < Toolbar.TBIndex2Item( Btn1st ) then\r
50729     Result := Toolbar.TBIndex2Item( Result );\r
50730 end;\r
50732 type\r
50733   TTBButtonEvent = packed Record\r
50734     BtnID: DWORD;\r
50735     Event: TOnToolbarButtonClick;\r
50736   end;\r
50737   PTBButtonEvent = ^TTBButtonEvent;\r
50739 //[procedure TControl.TBFreeTBevents]\r
50740 procedure TControl.TBFreeTBevents;\r
50741 begin\r
50742   fTBevents.Release;\r
50743 end;\r
50745 //[function WndProcToolbarButtonsClicks]\r
50746 function WndProcToolbarButtonsClicks( TB: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
50747 var Notify: PTBNotify;\r
50748     I: Integer;\r
50749     Event: PTBButtonEvent;\r
50750 begin\r
50751   Result := FALSE;\r
50752   if Msg.message = WM_NOTIFY then\r
50753   begin\r
50754     Notify := Pointer( Msg.lParam );\r
50755     if Notify.hdr.code = NM_CLICK then\r
50756     begin\r
50757       for I := TB.fTBevents.fCount-1 downto 0 do\r
50758       begin\r
50759         Event := TB.fTBevents.fItems[ I ];\r
50760         if Integer( Event.BtnID ) = Notify.iItem then\r
50761         begin\r
50762           if Assigned( Event.Event ) then\r
50763           begin\r
50764             TB.RefInc;\r
50765             Rslt := DefWindowProc( Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam );\r
50766             Event.Event( TB, Event.BtnID );\r
50767             //Rslt := TB.CallDefWndProc( Msg );\r
50768             TB.RefDec;\r
50769             Result := TRUE;\r
50770             Exit;\r
50771           end;\r
50772           break;\r
50773         end;\r
50774       end;\r
50775     end;\r
50776   end;\r
50777 end;\r
50779 //[procedure TControl.TBAssignEvents]\r
50780 procedure TControl.TBAssignEvents(BtnID: Integer;\r
50781   Events: array of TOnToolbarButtonClick);\r
50782 var I: Integer;\r
50783     EventRec: PTBButtonEvent;\r
50784 begin\r
50785   if fTBevents = nil then\r
50786   begin\r
50787     fTBevents := NewList;\r
50788     Add2AutoFreeEx( TBFreeTBevents );\r
50789     AttachProc( WndProcToolbarButtonsClicks );\r
50790   end;\r
50791   BtnID := GetTBBtnGoodID( @Self, BtnID );\r
50792   for I := 0 to High( Events ) do\r
50793   begin\r
50794     GetMem( EventRec, Sizeof( TTBButtonEvent ) );\r
50795     fTBevents.Add( EventRec );\r
50796     EventRec.Event := Events[ I ];\r
50797     EventRec.BtnID := BtnID;\r
50798     Inc( BtnID );\r
50799   end;\r
50800 end;\r
50802 //[procedure TControl.TBResetImgIdx]\r
50803 procedure TControl.TBResetImgIdx( BtnID, BtnCount: Integer );\r
50804 begin\r
50805   while BtnCount > 0 do\r
50806   begin\r
50807     TBButtonImage[ BtnID ] := -2;\r
50808     Inc( BtnID );\r
50809     Dec( BtnCount );\r
50810   end;\r
50811 end;\r
50813 //*\r
50814 //[function TControl.TBGetButtonVisible]\r
50815 function TControl.TBGetButtonVisible(BtnID: Integer): Boolean;\r
50816 begin\r
50817   Result := Perform( TB_ISBUTTONHIDDEN, GetTBBtnGoodID( @ Self, BtnID ), 0 ) = 0;\r
50818 end;\r
50820 //*\r
50821 //[function TControl.TBItem2Index]\r
50822 function TControl.TBItem2Index(BtnID: Integer): Integer;\r
50823 begin\r
50824   Result := Perform( TB_COMMANDTOINDEX, BtnID, 0 );\r
50825 end;\r
50827 //*\r
50828 //[procedure TControl.TBSetButtonVisible]\r
50829 procedure TControl.TBSetButtonVisible(BtnID: Integer;\r
50830   const Value: Boolean);\r
50831 begin\r
50832   BtnID := GetTBBtnGoodID( @Self, BtnID );\r
50833   Perform( TB_HIDEBUTTON, BtnID, Integer( not Value ) );\r
50834 end;\r
50836 {$IFDEF ASM_VERSION}\r
50837 //[function TControl.TBGetBtnStt]\r
50838 function TControl.TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;\r
50839 asm\r
50840         PUSH     0\r
50841         PUSH     ECX\r
50842         PUSH     EAX\r
50843         CALL     GetTBBtnGoodID\r
50844         POP      EDX\r
50845         POP      ECX\r
50846         PUSH     EAX\r
50847         ADD      ECX, 8\r
50848         PUSH     ECX\r
50849         PUSH     EDX\r
50850         CALL     Perform\r
50851         TEST     EAX, EAX\r
50852         SETNZ    AL\r
50853 end;\r
50854 {$ELSE ASM_VERSION} //Pascal\r
50855 function TControl.TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;\r
50856 begin\r
50857   BtnID := GetTBBtnGoodID( @Self, BtnID );\r
50858   Result := Perform( Index + 8, BtnID, 0 ) <> 0;\r
50859 end;\r
50860 {$ENDIF ASM_VERSION}\r
50862 //+\r
50863 //[procedure TControl.TBSetBtnStt]\r
50864 procedure TControl.TBSetBtnStt(BtnID: Integer; const Index: Integer; const Value: Boolean);\r
50865 begin\r
50866   BtnID := GetTBBtnGoodID( @Self, BtnID );\r
50867   Perform( Index, BtnID, Integer( Value ) );\r
50868 end;\r
50870 {$IFDEF ASM_VERSION}\r
50871 //[function TControl.TBIndex2Item]\r
50872 function TControl.TBIndex2Item(Idx: Integer): Integer;\r
50873 //*/////////////////////////////////////////////////////\r
50874 const                                                 //\r
50875   _sizeof_TTBButton = sizeof( TTBButton );            //\r
50876 //*/////////////////////////////////////////////////////\r
50877 asm\r
50878 //*/////////////////////////////////////////////////////\r
50879 //        ADD      ESP, -sizeof(TTBButton)\r
50880 //*/////////////////////////////////////////////////////\r
50881         ADD      ESP, -_sizeof_TTBButton              //\r
50882 //*/////////////////////////////////////////////////////\r
50883         PUSH     ESP\r
50884         PUSH     EDX\r
50885         PUSH     TB_GETBUTTON\r
50886         PUSH     EAX\r
50887         CALL     Perform\r
50888         TEST     EAX, EAX\r
50889         MOV      EAX, [ESP].TTBButton.idCommand\r
50890         JNZ      @@1\r
50891         OR       EAX, -1\r
50892 //*/////////////////////////////////////////////////////\r
50893 //@@1:    ADD      ESP, sizeof( TTBButton )\r
50894 //*/////////////////////////////////////////////////////\r
50895 @@1:    ADD      ESP, _sizeof_TTBButton               //\r
50896 //*/////////////////////////////////////////////////////\r
50897 end;\r
50898 {$ELSE ASM_VERSION} //Pascal\r
50899 function TControl.TBIndex2Item(Idx: Integer): Integer;\r
50900 var ButtonInfo: TTBButton;\r
50901 begin\r
50902   Result := -1;\r
50903   if Perform( TB_GETBUTTON, Idx, Integer( @ButtonInfo ) ) <> 0 then\r
50904     Result := ButtonInfo.idCommand;\r
50905 end;\r
50906 {$ENDIF ASM_VERSION}\r
50908 {$IFDEF ASM_VERSION}\r
50909 //[function TControl.TBGetButtonText]\r
50910 function TControl.TBGetButtonText( BtnID: Integer ): String;\r
50911 asm\r
50912         PUSH     ECX\r
50913         ADD      ESP, -1024\r
50914         PUSH     ESP\r
50915         PUSH     EAX\r
50916         CALL     GetTBBtnGoodID\r
50917         POP      EDX\r
50918         PUSH     EAX\r
50919         PUSH     TB_GETBUTTONTEXT\r
50920         PUSH     EDX\r
50921         CALL     Perform\r
50922         TEST     EAX, EAX\r
50923         JLE      @@2\r
50924         MOV      EDX, ESP\r
50925         JMP      @@1\r
50926 @@2:    XOR      EDX, EDX\r
50927 @@1:    MOV      EAX, [ESP+1024]\r
50928         CALL     System.@LStrFromPChar\r
50929         ADD      ESP, 1028\r
50930 end;\r
50931 {$ELSE ASM_VERSION} //Pascal\r
50932 function TControl.TBGetButtonText( BtnID: Integer ): String;\r
50933 var Buffer: array[ 0..1023 ] of Char;\r
50934 begin\r
50935   BtnID := GetTBBtnGoodID( @Self, BtnID );\r
50936   if Perform( TB_GETBUTTONTEXT, BtnID, Integer( @Buffer[ 0 ] ) ) > 0 then\r
50937     Result := Buffer\r
50938   else\r
50939   Result := '';\r
50940 end;\r
50941 {$ENDIF ASM_VERSION}\r
50943 //*\r
50944 //[function TControl.TBGetButtonRect]\r
50945 function TControl.TBGetButtonRect(BtnID: Integer): TRect;\r
50946 begin\r
50947   BtnID := GetTBBtnGoodID( @Self, BtnID );\r
50948   Perform( TB_GETITEMRECT, TBItem2Index( BtnID ), Integer( @Result ) );\r
50949 end;\r
50951 //*\r
50952 //[function TControl.TBGetRows]\r
50953 function TControl.TBGetRows: Integer;\r
50954 begin\r
50955   Result := 1;\r
50956   UpdateWndStyles;\r
50957   if (TBSTYLE_WRAPABLE and fStyle) <> 0 then\r
50958     Result := Perform( TB_GETROWS, 0, 0 );\r
50959 end;\r
50961 //*\r
50962 //[procedure TControl.TBSetRows]\r
50963 procedure TControl.TBSetRows(const Value: Integer);\r
50964 begin\r
50965   Perform( TB_SETROWS, Value, 0 );\r
50966 end;\r
50968 {$IFDEF ASM_VERSION}\r
50969 //[procedure TControl.TBSetTooltips]\r
50970 procedure TControl.TBSetTooltips(BtnID1st: Integer;\r
50971   Tooltips: array of PChar);\r
50972 asm\r
50973         PUSH     EBX\r
50974         PUSH     ESI\r
50975         MOV      ESI, ECX\r
50976         MOV      EBX, EAX\r
50977         PUSHAD\r
50978         MOV      ECX, [EBX].fTBttCmd\r
50979         INC      ECX\r
50980         LOOP     @@1\r
50981         CALL     NewList\r
50982         MOV      [EBX].fTBttCmd, EAX\r
50983         CALL     NewStrList\r
50984         MOV      [EBX].fTBttTxt, EAX\r
50985 @@1:    POPAD\r
50986         MOV      ECX, [EBP+8]\r
50987         INC      ECX\r
50988         JZ       @@exit\r
50989 @@loop:\r
50990         PUSH     ECX\r
50991         PUSH     EDX\r
50992         PUSH     0\r
50993         LODSD\r
50994         MOV      EDX, EAX\r
50995         MOV      EAX, ESP\r
50996         CALL     System.@LStrFromPChar\r
50998         MOV      EDX, [ESP+4]\r
50999         MOV      EAX, [EBX].fTBttCmd\r
51000         CALL     TList.IndexOf\r
51001         TEST     EAX, EAX\r
51002         JGE      @@2\r
51004         MOV      EDX, [ESP+4]\r
51005         MOV      EAX, [EBX].fTBttCmd\r
51006         CALL     TList.Add\r
51007         POP      EDX\r
51008         PUSH     EDX\r
51009         MOV      EAX, [EBX].fTBttTxt\r
51010         CALL     TStrList.Add\r
51011         JMP      @@3\r
51013 @@2:\r
51014         MOV      EDX, EAX\r
51015         POP      ECX\r
51016         PUSH     ECX\r
51017         MOV      EAX, [EBX].fTBttTxt\r
51018         CALL     TStrList.Put\r
51019 @@3:\r
51020         CALL     RemoveStr\r
51022         POP      EDX\r
51023         POP      ECX\r
51024         INC      EDX\r
51025         LOOP     @@loop\r
51026 @@exit:\r
51027         POP      ESI\r
51028         POP      EBX\r
51029 end;\r
51030 {$ELSE ASM_VERSION} //Pascal\r
51031 procedure TControl.TBSetTooltips(BtnID1st: Integer;\r
51032   Tooltips: array of PChar);\r
51033 var I, J: Integer;\r
51034 begin\r
51035   if not assigned( fTBttCmd ) then\r
51036   begin\r
51037     fTBttCmd := NewList;\r
51038     fTBttTxt := NewStrList;\r
51039   end;\r
51040   for I:= 0 to High( Tooltips ) do\r
51041   begin\r
51042     J := fTBttCmd.IndexOf( Pointer( BtnID1st ) );\r
51043     if J < 0 then\r
51044     begin\r
51045       fTBttCmd.Add( Pointer( BtnID1st ) );\r
51046       fTBttTxt.Add( Tooltips[ I ] );\r
51047     end\r
51048        else\r
51049       fTBttTxt.Items[ J ] := Tooltips[ I ];\r
51050     Inc( BtnID1st );\r
51051   end;\r
51052 end;\r
51053 {$ENDIF ASM_VERSION}\r
51055 {$IFDEF ASM_VERSION}\r
51056 //[function TControl.TBButtonAtPos]\r
51057 function TControl.TBButtonAtPos(X, Y: Integer): Integer;\r
51058 asm\r
51059         PUSH     EAX\r
51060         CALL     TBBtnIdxAtPos\r
51061         TEST     EAX, EAX\r
51062         MOV      EDX, EAX\r
51063         POP      EAX\r
51064         JGE      TBIndex2Item\r
51065         MOV      EAX, EDX\r
51066 end;\r
51067 {$ELSE ASM_VERSION} //Pascal\r
51068 function TControl.TBButtonAtPos(X, Y: Integer): Integer;\r
51069 var I: Integer;\r
51070 begin\r
51071   I := TBBtnIdxAtPos( X, Y );\r
51072   if I >= 0 then\r
51073      I := TBIndex2Item( I );\r
51074   Result := I;\r
51075 end;\r
51076 {$ENDIF ASM_VERSION}\r
51078 {$IFDEF ASM_VERSION}\r
51079 //[function TControl.TBBtnIdxAtPos]\r
51080 function TControl.TBBtnIdxAtPos(X, Y: Integer): Integer;\r
51081 asm\r
51082         PUSH     EBX\r
51083         PUSH     ECX\r
51084         PUSH     EDX\r
51085         MOV      EBX, EAX\r
51086         CALL     GetItemsCount\r
51087         MOV      ECX, EAX\r
51088         JECXZ    @@fin\r
51089 @@1:    PUSH     ECX\r
51090         ADD      ESP, -16\r
51091         PUSH     ESP\r
51092         DEC      ECX\r
51093         PUSH     ECX\r
51094         PUSH     TB_GETITEMRECT\r
51095         PUSH     EBX\r
51096         CALL     Perform\r
51097         MOV      EDX, ESP\r
51098         LEA      EAX, [ESP+20]\r
51099         CALL     PointInRect\r
51100         ADD      ESP, 16\r
51101         POP      ECX\r
51102         TEST     AL, AL\r
51103         {$IFDEF USE_CMOV}\r
51104         CMOVNZ   EAX, ECX\r
51105         {$ELSE}\r
51106         JZ       @@2\r
51107         MOV      EAX, ECX\r
51108         JMP      @@fin\r
51109 @@2:    {$ENDIF}\r
51110         JNZ      @@fin\r
51112         LOOP     @@1\r
51113 @@fin:  DEC      EAX\r
51114         POP      EDX\r
51115         POP      EDX\r
51116         POP      EBX\r
51117 end;\r
51118 {$ELSE ASM_VERSION} //Pascal\r
51119 function TControl.TBBtnIdxAtPos(X, Y: Integer): Integer;\r
51120 var I: Integer;\r
51121     R: TRect;\r
51122     P: TPoint;\r
51123 begin\r
51124   P := MakePoint( X, Y );\r
51125   for I := TBButtonCount - 1 downto 0 do\r
51126   begin\r
51127     Perform( TB_GETITEMRECT, I, Integer( @R ) );\r
51128     if PointInRect( P, R ) then\r
51129     begin\r
51130       Result := I;\r
51131       Exit;\r
51132     end;\r
51133   end;\r
51134   Result := -1;\r
51135 end;\r
51136 {$ENDIF ASM_VERSION}\r
51138 //*\r
51139 //[procedure TControl.TBDeleteButton]\r
51140 procedure TControl.TBDeleteButton(BtnID: Integer);\r
51141 begin\r
51142   BtnID := GetTBBtnGoodID( @Self, BtnID );\r
51143   Perform( TB_DELETEBUTTON, TBItem2Index( BtnID ), 0 );\r
51144 end;\r
51146 //*\r
51147 //[procedure TControl.TBDeleteBtnByIdx]\r
51148 procedure TControl.TBDeleteBtnByIdx(Idx: Integer);\r
51149 begin\r
51150   Perform( TB_DELETEBUTTON, Idx, 0 );\r
51151 end;\r
51153 //*\r
51154 //[procedure TControl.Clear]\r
51155 procedure TControl.Clear;\r
51156 begin\r
51157   fCommandActions.aClear( @Self );\r
51158 end;\r
51160 {$IFDEF ASM_noVERSION}\r
51161 //[function TControl.TBGetBtnImgIdx]\r
51162 function TControl.TBGetBtnImgIdx(BtnID: Integer): Integer;\r
51163 const szTBButton = sizeof( TTBButton );\r
51164 asm\r
51165         ADD      ESP, -szTBButton\r
51166         PUSH     ESP\r
51167         PUSH     EAX\r
51168         CALL     TBItem2Index\r
51169         POP      EDX\r
51170         PUSH     EAX\r
51171         PUSH     TB_GETBUTTON\r
51172         PUSH     EDX\r
51173         CALL     Perform\r
51174         POP      EAX\r
51175         ADD      ESP, szTBButton-4\r
51176 end;\r
51177 {$ELSE ASM_VERSION} //Pascal\r
51178 function TControl.TBGetBtnImgIdx(BtnID: Integer): Integer;\r
51179 var B: TTBButton;\r
51180 begin\r
51181   Perform( TB_GETBUTTON, TBItem2Index( GetTBBtnGoodID( @Self, BtnID ) ), Integer( @B ) );\r
51182   Result := B.iBitmap;\r
51183 end;\r
51184 {$ENDIF ASM_VERSION}\r
51186 //*\r
51187 //[procedure TControl.TBSetBtnImgIdx]\r
51188 procedure TControl.TBSetBtnImgIdx(BtnID: Integer; const Value: Integer);\r
51189 begin\r
51190   Perform( TB_CHANGEBITMAP, GetTBBtnGoodID( @Self, BtnID ), Value );\r
51191 end;\r
51193 {$IFDEF ASM_VERSION}\r
51194 //[procedure TControl.TBSetButtonText]\r
51195 procedure TControl.TBSetButtonText(BtnID: Integer; const Value: String);\r
51196 asm\r
51197         PUSH     0\r
51198         PUSH     ECX\r
51199         PUSH     EAX\r
51200         CALL     GetTBBtnGoodID\r
51201         POP      EDX\r
51203         ADD      ESP, -16\r
51204         PUSH     TBIF_TEXT\r
51205         PUSH     32 //Sizeof( TTBButtonInfo )\r
51206         PUSH     ESP\r
51207         PUSH     EAX\r
51208         PUSH     TB_SETBUTTONINFO\r
51209         PUSH     EDX\r
51210         CALL     Perform\r
51211         ADD      ESP, 32 //sizeof( TTBButtonInfo )\r
51212 end;\r
51213 {$ELSE ASM_VERSION} //Pascal\r
51214 procedure TControl.TBSetButtonText(BtnID: Integer; const Value: String);\r
51215 var BI: TTBButtonInfo;\r
51216 begin\r
51217   BtnID := GetTBBtnGoodID( @Self, BtnID );\r
51218   BI.cbSize := Sizeof( BI );\r
51219   BI.dwMask := TBIF_TEXT;\r
51220   BI.pszText := PChar( Value );\r
51221   Perform( TB_SETBUTTONINFO, BtnID, Integer( @BI ) );\r
51222 end;\r
51223 {$ENDIF ASM_VERSION}\r
51225 {$IFDEF ASM_VERSION}\r
51226 //[function TControl.TBGetBtnWidth]\r
51227 function TControl.TBGetBtnWidth(BtnID: Integer): Integer;\r
51228 asm\r
51229         ADD      ESP, -16\r
51230         MOV      ECX, ESP\r
51231         CALL     TBGetButtonRect\r
51232         POP      EDX\r
51233         POP      ECX\r
51234         POP      EAX\r
51235         SUB      EAX, EDX\r
51236         POP      EDX\r
51237 end;\r
51238 {$ELSE ASM_VERSION} //Pascal\r
51239 function TControl.TBGetBtnWidth(BtnID: Integer): Integer;\r
51240 var R: TRect;\r
51241 begin\r
51242   R := TBButtonRect[ BtnID ];\r
51243   Result := R.Right - R.Left;\r
51244 end;\r
51245 {$ENDIF ASM_VERSION}\r
51247 {$IFDEF ASM_VERSION}\r
51248 //[procedure TControl.TBSetBtnWidth]\r
51249 procedure TControl.TBSetBtnWidth(BtnID: Integer; const Value: Integer);\r
51250 asm\r
51251         PUSH     EBX\r
51252         MOV      EBX, ECX\r
51254         PUSH     EAX\r
51255         CALL     GetTBBtnGoodID\r
51256         POP      EDX\r
51258         ADD      ESP, -24\r
51259         PUSH     TBIF_SIZE or TBIF_STYLE\r
51260         PUSH     32\r
51261         MOV      ECX, ESP\r
51263         PUSH     ECX\r
51264         PUSH     EAX\r
51265         PUSH     TB_SETBUTTONINFO\r
51266         PUSH     EDX\r
51268         PUSH     ECX\r
51269         PUSH     EAX\r
51270         PUSH     TB_GETBUTTONINFO\r
51271         PUSH     EDX\r
51272         CALL     Perform\r
51274         MOV      [ESP+16+18], BX\r
51275         AND      byte ptr [ESP+16].TTBButtonInfo.fsStyle, not TBSTYLE_AUTOSIZE\r
51276         CALL     Perform\r
51277         ADD      ESP, 32\r
51278         POP      EBX\r
51279 end;\r
51280 {$ELSE ASM_VERSION} //Pascal\r
51281 procedure TControl.TBSetBtnWidth(BtnID: Integer; const Value: Integer);\r
51282 var BI: TTBButtonInfo;\r
51283 begin\r
51284   BI.cbSize := Sizeof( BI );\r
51285   BI.dwMask := TBIF_SIZE or TBIF_STYLE;\r
51286   BtnID := GetTBBtnGoodID( @Self, BtnID );\r
51287   Perform( TB_GETBUTTONINFO, BtnID, Integer( @BI ) );\r
51288   BI.cx := Value;\r
51289   BI.fsStyle := BI.fsStyle and not TBSTYLE_AUTOSIZE;\r
51290   Perform( TB_SETBUTTONINFO, BtnID, Integer( @BI ) );\r
51291 end;\r
51292 {$ENDIF ASM_VERSION}\r
51294 //[procedure TControl.TBSetBtMinMaxWidth]\r
51295 procedure TControl.TBSetBtMinMaxWidth(const Idx: Integer; const Value: Integer);\r
51296 begin\r
51297   case Idx of\r
51298   0: FTBBtMinWidth := Value;\r
51299   1: FTBBtMaxWidth := Value;\r
51300   end;\r
51301   Perform( TB_SETBUTTONWIDTH, 0, FTBBtMaxWidth or (FTBBtMinWidth shl 16) );\r
51302 end;\r
51304 {$IFDEF F_P}\r
51305 //[function TControl.TBGetBtMinMaxWidth]\r
51306 function TControl.TBGetBtMinMaxWidth(const Idx: Integer): Integer;\r
51307 begin\r
51308   CASE Idx OF\r
51309   0: Result := FTBBtMinWidth;\r
51310   1: Result := FTBBtMaxWidth;\r
51311   END;\r
51312 end;\r
51313 {$ENDIF F_P}\r
51315 //[procedure TControl.SetDroppedDown]\r
51316 procedure TControl.SetDroppedDown(const Value: Boolean);\r
51317 begin\r
51318   //fDropped := Value;\r
51319   Perform( CB_SHOWDROPDOWN, Integer( Value ), 0 );\r
51320 end;\r
51322 {$IFDEF ASM_VERSION}\r
51323 //[procedure TControl.AddDirList]\r
51324 procedure TControl.AddDirList(const Filemask: String; Attrs: DWORD);\r
51325 asm\r
51326         CALL     EDX2PChar\r
51327         PUSH     EDX\r
51328         PUSH     ECX\r
51329         MOVZX    ECX, [EAX].fCommandActions.aDir\r
51330         JECXZ    @@exit\r
51331         PUSH     ECX\r
51332         PUSH     EAX\r
51333         CALL     Perform\r
51334         RET\r
51335 @@exit:\r
51336         POP      ECX\r
51337         POP      ECX\r
51338 end;\r
51339 {$ELSE ASM_VERSION} //Pascal\r
51340 procedure TControl.AddDirList(const Filemask: String; Attrs: DWORD);\r
51341 begin\r
51342   if fCommandActions.aDir <> 0 then\r
51343   Perform( fCommandActions.aDir, Attrs, Integer( PChar( Filemask ) ) );\r
51344 end;\r
51345 {$ENDIF ASM_VERSION}\r
51347 //[FUNCTION WndProcShowModal]\r
51348 {$IFDEF ASM_VERSION}\r
51349 function WndProcShowModal( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
51350 asm\r
51351         CMP      word ptr [EDX].TMsg.message, WM_CLOSE\r
51352         JNZ      @@ret_false\r
51353 {//++++++ AP\r
51354         PUSH     EBX\r
51355         MOV      EBX, 1\r
51356         CMP      [EAX].TControl.fOnClose.TMethod.Code, 0\r
51357         JZ       @@AP1\r
51358         PUSH     EAX\r
51359         PUSH     EDX\r
51360         PUSH     ECX\r
51361         XCHG     EDX, EAX\r
51362         PUSH     EBX\r
51363         MOV      ECX, ESP\r
51364         MOV      EAX, [EDX].TControl.fOnClose.TMethod.Data\r
51365         CALL     dword ptr [EDX].TControl.fOnClose.TMethod.Code\r
51366         POP      EBX\r
51367         POP      ECX\r
51368         POP      EDX\r
51369         POP      EAX\r
51370 @@AP1:\r
51371 //------ AP}\r
51373         XCHG     EDX, EAX\r
51374         XOR      EAX, EAX\r
51375         CMP      [EDX].TControl.fModalResult, EAX\r
51376         JNZ      @@1\r
51377         OR       [EDX].TControl.fModalResult, -1\r
51378 @@1:\r
51379 {//++++++ AP\r
51380         TEST     BL, BL\r
51381         JNZ      @@AP2\r
51382         MOV      [EDX].TControl.fModalResult, 0\r
51383 @@AP2:\r
51384         POP      EBX\r
51385 //------ AP}\r
51387         MOV      [ECX], EAX\r
51388         INC      EAX\r
51389         RET\r
51390 @@ret_false:\r
51391         XOR      EAX, EAX\r
51393 end;\r
51394 {$ELSE ASM_VERSION} //Pascal\r
51395 function WndProcShowModal( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
51396 //var Accept: Boolean; // {Alexander Pravdin, AP}\r
51397 begin\r
51398   if Msg.message = WM_CLOSE then\r
51399   begin\r
51400     //++++++++ {AP} +++++++++++++++++++++++++++++++++++++++++++++++++++++++//\r
51401     {Accept := True;                                                       //\r
51402     if Assigned( Self_.fOnClose ) then Self_.fOnClose( Self_, Accept );  //\r
51403     }//-------- {AP} ----------------------------------------------------//\r
51404     if Self_.ModalResult = 0 then { (Sergey Shishmintzev) }\r
51405       Self_.ModalResult := -1;\r
51406     //++++++++ {AP} +++++++++++++++++++++++++++++++++++++++++++++++++++++++//\r
51407     {if not Accept then                     //\r
51408       Self_.ModalResult := 0; //íå çàêðûâàåì ôîðìó, îñòàâëÿÿ å¸ íà ýêðàíå//\r
51409     }//-------- {AP} ----------------------------------------------------//\r
51410     Rslt := 0;\r
51411     Result := True; // Do not process !\r
51412   end\r
51413     else\r
51414     Result := False;\r
51415 end;\r
51416 {$ENDIF ASM_VERSION}\r
51417 //[END WndProcShowModal]\r
51419 {$IFDEF ASM_noVERSION}\r
51420 //[function TControl.ShowModal]\r
51421 function TControl.ShowModal: Integer;\r
51422 asm\r
51423         MOV      ECX, [EAX].fParent\r
51424         JECXZ    @@show\r
51425         MOVZX    ECX, [EAX].fIsControl\r
51426         JECXZ    @@show_modal\r
51427 @@show:\r
51428         CALL     Show\r
51429         XOR      EAX, EAX\r
51430         RET\r
51431 @@show_modal:\r
51432         PUSHAD\r
51434         MOV      EBX, EAX\r
51435         MOV      EDI, [Applet]\r
51437         XOR      EBP, EBP  // CurCtl = nil\r
51439         MOV      EAX, [EDI].fCurrentControl\r
51440         CMP      [EDI].TControl.FIsApplet, 0\r
51441         {$IFDEF USE_CMOV}\r
51442         CMOVZ    EAX, EDI\r
51443         {$ELSE}\r
51444         JNZ      @@curctrl_save\r
51445         MOV      EAX, EDI\r
51446 @@curctrl_save:\r
51447         {$ENDIF}\r
51449         PUSH     EAX\r
51451         MOV      EDX, offset[WndProcShowModal]\r
51452         PUSH     EDX\r
51454         MOV      EAX, EBX\r
51455         CALL     TControl.AttachProc\r
51456         XOR      EDX, EDX\r
51457         MOV      [EBX].fModalResult, EDX\r
51459         CALL     NewList\r
51460         XCHG     EAX, EBP\r
51462         XOR      ECX, ECX\r
51463         INC      ECX\r
51464         MOV      ESI, EDI\r
51466         CMP      [EDI].TControl.FIsApplet, 0\r
51467         JZ       @@isapplet\r
51469         MOV      EBP, [EDI].fCurrentControl // CurCtl = Applet.fCurrentControl\r
51471         MOV      ESI, [EDI].fChildren\r
51472         MOV      ECX, [ESI].TList.fCount\r
51473         MOV      ESI, [ESI].TList.fItems\r
51475 @@1loo: LODSD\r
51477 @@isapplet:\r
51479         PUSH     ECX\r
51480         CMP      EAX, EBX\r
51481         JE       @@1nx\r
51482         PUSH     EAX\r
51483         CALL     GetEnabled\r
51484         TEST     AL, AL\r
51485         POP      EAX\r
51486         JZ       @@1nx\r
51487         PUSH     EAX\r
51488         MOV      DL, 0\r
51489         CALL     SetEnabled\r
51490         POP      EDX\r
51491         MOV      EAX, EBP\r
51492         CALL     TList.Add\r
51493 @@1nx:  POP      ECX\r
51494         LOOP     @@1loo\r
51496         INC      [EBX].fModal\r
51497         MOV      EAX, [Applet]\r
51498         MOV      [EAX].fModalForm, EBX\r
51500         MOV      EAX, EBX\r
51501         CALL     Show\r
51503 @@msgloo:\r
51504         MOVZX    ECX, [AppletTerminated]\r
51505         OR       ECX, [EBX].fModalResult\r
51506         JNZ      @@e_msgloo\r
51507         CALL     WaitMessage\r
51508         MOV      EAX, EDI\r
51509         CALL     ProcessMessages\r
51510         {$IFNDEF NOT_USE_OnIdle}\r
51511         MOV      EAX, EBX\r
51512         CALL     [ProcessIdle]\r
51513         {$ENDIF}\r
51514         JMP      @@msgloo\r
51516 @@e_msgloo:\r
51517         POP      EDX\r
51518         MOV      EAX, EBX\r
51519         CALL     TControl.DetachProc\r
51521         DEC      [EBX].fModal\r
51522         MOV      EAX, [Applet]\r
51523         XOR      ECX, ECX\r
51524         MOV      [EAX].fModalForm, ECX\r
51526         MOV      ECX, [EBP].TList.fCount\r
51527         JECXZ    @@2end\r
51528         MOV      ESI, [EBP].TList.fItems\r
51530 @@2loo: LODSD\r
51531         PUSH     ECX\r
51532         MOV      DL, 1\r
51533         CALL     TControl.SetEnabled\r
51534         POP      ECX\r
51535         LOOP     @@2loo\r
51537 @@2end:\r
51538         MOV      EAX, EBP\r
51539         CALL     TObj.Free\r
51541         POP      ECX\r
51542         JECXZ    @@exit\r
51543         PUSH     0\r
51544         PUSH     WA_ACTIVE\r
51545         PUSH     WM_ACTIVATE\r
51546         PUSH     [ECX].fHandle\r
51547         CALL     PostMessage\r
51549         TEST     EBP, EBP  // CurCtl = nil ?\r
51550         JZ       @@exit\r
51551         MOV      EAX, EBP\r
51552         MOV      DL, 1\r
51553         CALL     TControl.SetFocused\r
51555 @@exit:\r
51556         POPAD\r
51557         MOV      EAX, [EAX].fModalResult\r
51558 end;\r
51559 {$ELSE ASM_VERSION} //Pascal\r
51560 {$IFDEF USE_SHOWMODALPARENTED_ALWAYS}\r
51561 function TControl.ShowModal: Integer;\r
51562 begin\r
51563   Result := ShowModalParented(Applet);\r
51564 end;\r
51565 {$ELSE not USE_SHOWMODALPARENTED_ALWAYS}\r
51566 function TControl.ShowModal: Integer;\r
51567 var FL: PList;\r
51568 var CurForm: PControl;\r
51569     I: Integer;\r
51570     F: PControl;\r
51571     CurCtl: PControl; // { Alexander Pravdin }\r
51572 begin\r
51573   Result := 0;\r
51574   if (fIsControl) or (fParent = nil) then\r
51575   begin\r
51576     Show;\r
51577     Exit;\r
51578   end;\r
51579   AttachProc( WndProcShowModal );\r
51580   CurForm := Applet.fCurrentControl;\r
51581   FL := NewList;\r
51582   CurCtl := nil; // { Alexander Pravdin }\r
51584   if Applet.IsApplet then\r
51585   for I := 0 to Applet.ChildCount - 1 do\r
51586   begin\r
51587     F := Applet.fChildren.Items[ I ];\r
51588     if F <> @Self then\r
51589     if F.Enabled then\r
51590     begin\r
51591        FL.Add( F );\r
51592        F.Enabled := FALSE;\r
51593     end;\r
51594   end\r
51595   else\r
51596     begin\r
51597       CurForm := Applet;\r
51598       if Applet.Enabled then\r
51599       begin\r
51600         FL.Add( Applet );\r
51601         CurCtl := Applet.fCurrentControl; { Alexander Pravdin }\r
51602         Applet.Enabled := FALSE;\r
51603       end;\r
51604     end;\r
51606   Inc( fModal );\r
51607   Applet.fModalForm := @ Self;\r
51608   Enabled := TRUE;\r
51610   Show;\r
51611   ModalResult := 0;\r
51612   while not AppletTerminated and (ModalResult = 0) do\r
51613   begin\r
51614     WaitMessage;\r
51615     Applet.ProcessMessages;\r
51616     {$IFNDEF NOT_USE_OnIdle}\r
51617     ProcessIdle( @Self );\r
51618     {$ENDIF}\r
51619   end;\r
51621   Dec( fModal );\r
51622   Applet.fModalForm := nil;\r
51624   DetachProc( WndProcShowModal );\r
51625   for I := 0 to FL.Count - 1 do\r
51626   begin\r
51627     F := FL.Items[ I ];\r
51628     F.Enabled := TRUE;\r
51629     //EnableWindow( F.Handle, TRUE );\r
51630     //F.Perform( WM_ENABLE, 1, 0 );\r
51631   end;\r
51632   FL.Free;\r
51634   if CurForm <> nil then\r
51635     PostMessage( CurForm.Handle, WM_ACTIVATE, WA_ACTIVE, 0 );\r
51636   if CurCtl <> nil then CurCtl.SetFocused( TRUE ); { Alexander Pravdin }\r
51638   Result := ModalResult;\r
51639 end;\r
51640 {$ENDIF USE_SHOWMODALPARENTED_ALWAYS}\r
51641 {$ENDIF ASM_VERSION}\r
51643 //[function TControl.ShowModalParented]\r
51644 {$IFNDEF NEW_MODAL}\r
51645 function TControl.ShowModalParented( const AParent: PControl ): Integer;\r
51646 begin\r
51647   Result := 0;\r
51648 end;\r
51649 {$ELSE NEW_MODAL defined}\r
51650 function TControl.ShowModalParented( const AParent: PControl ): Integer;\r
51651 var\r
51652   FL: PList;\r
51653   OldMF, F: PControl;\r
51654   I: Integer;\r
51655 begin\r
51656   Result := 0;\r
51657   if ( AParent = nil ) then Exit;\r
51659   Inc( fModal );\r
51660   FL := NewList;\r
51661   OldMF := AParent.fModalForm;\r
51662   AParent.fModalForm := @Self;\r
51664   if AParent.fIsApplet or ( AParent.IsMainWindow and AParent.fIsForm ) then\r
51665   begin\r
51666     for I := 0 to AParent.ChildCount - 1 do\r
51667     begin\r
51668       F := AParent.fChildren.Items[ I ];\r
51669       if ( F <> @Self ) and F.fIsForm and F.fEnabled and F.fVisible then\r
51670       begin\r
51671         FL.Add( F );\r
51672         F.Enabled := FALSE;\r
51673       end;\r
51674     end;\r
51675   end;\r
51677   if AParent.fIsForm and AParent.Enabled then\r
51678   begin\r
51679     FL.Add( AParent );\r
51680     AParent.Enabled := FALSE;\r
51681   end;\r
51683   ModalResult := 0;\r
51684   Show;\r
51685   while not AppletTerminated and ( ModalResult = 0 ) do\r
51686   begin\r
51687     WaitMessage;\r
51688     AParent.ProcessMessages;\r
51689 {$IFNDEF NOT_USE_OnIdle}\r
51690     ProcessIdle( @Self );\r
51691 {$ENDIF}\r
51692   end;\r
51694   AParent.fModalForm := OldMF;\r
51695   Dec( fModal );\r
51696   for I := 0 to FL.Count - 1 do\r
51697     PControl( FL.Items[ I ] ).Enabled := True;\r
51698   FL.Free;\r
51699   Hide;\r
51700   Result := ModalResult;\r
51701 end;\r
51702 {$ENDIF NEW_MODAL}\r
51704 //[function DisableWindows]\r
51705 function DisableWindows( W: hwnd; LPARAM: Integer ): Bool; stdcall;\r
51706 var FL: PList;\r
51707     Buf: array[ 0..127 ] of Char;\r
51708 begin\r
51709   FL := Pointer( LPARAM );\r
51710   if IsWindowEnabled( W ) and (W <> FL.Tag) then\r
51711   begin\r
51712     GetClassName( W, @ Buf[ 0 ], Sizeof( Buf ) );\r
51713     if Buf <> 'ComboLBox' then\r
51714     begin\r
51715       FL.Add( Pointer( W ) );\r
51716       EnableWindow( W, FALSE );\r
51717     end;\r
51718   end;\r
51719   Result := TRUE;\r
51720 end;\r
51722 //[function TControl.ShowModalEx]\r
51723 function TControl.ShowModalEx: Integer;\r
51724 var FL: PList;\r
51725 var CurForm: PControl;\r
51726     I: Integer;\r
51727     W: HWnd;\r
51728     CurCtl: PControl; { Alexander Pravdin }\r
51729 begin\r
51730   Result := 0;\r
51731   if (fIsControl) or (fParent = nil) then\r
51732   begin\r
51733     Show;\r
51734     Exit;\r
51735   end;\r
51736   AttachProc( WndProcShowModal );\r
51737   CurForm := Applet.fCurrentControl;\r
51738   FL := NewList;\r
51739   FL.Tag := fHandle;\r
51741   // ++++ { Alexander Pravdin }\r
51742   if not Applet.fIsApplet then CurCtl := Applet.fCurrentControl\r
51743                           else CurCtl := nil;\r
51744   // ----\r
51745   CreateWindow;\r
51747   EnumThreadWindows( GetCurrentThreadID, @ DisableWindows, Integer( FL ) );\r
51748   Enabled := TRUE;\r
51750   Inc( fModal );\r
51751   Applet.fModalForm := @ Self;\r
51752   Show;\r
51753   ModalResult := 0;\r
51754   while not AppletTerminated and (ModalResult = 0) do\r
51755   begin\r
51756     WaitMessage;\r
51757     Applet.ProcessMessages;\r
51758     {$IFNDEF NOT_USE_OnIdle}\r
51759     ProcessIdle( @Self );\r
51760     {$ENDIF}\r
51761   end;\r
51763   Dec( fModal );\r
51764   Applet.fModalForm := @ Self;\r
51766   DetachProc( WndProcShowModal );\r
51768   for I := 0 to FL.Count - 1 do\r
51769   begin\r
51770     W := THandle( FL.Items[ I ] );\r
51771     EnableWindow( W, TRUE );\r
51772   end;\r
51773   FL.Free;\r
51775   if CurForm <> nil then\r
51776     PostMessage( CurForm.Handle, WM_ACTIVATE, WA_ACTIVE, 0 );\r
51777   if CurCtl <> nil then CurCtl.SetFocused( True ); { Alexander Pravdin }\r
51778   Result := ModalResult;\r
51779 end;\r
51781 //[function TControl.GetModal]\r
51782 function TControl.GetModal: Boolean;\r
51783 begin\r
51784   Result := fModal > 0;\r
51785 end;\r
51787 {$IFDEF USE_SETMODALRESULT}\r
51788 //[procedure TControl.SetModalResult]\r
51789 procedure TControl.SetModalResult( const Value: Integer );\r
51790 begin\r
51791   //if fModal <= 0 then Exit;\r
51792   fModalResult := Value;\r
51793   if Value <> 0 then\r
51794     PostMessage( GetWindowHandle, 0, 0, 0 );\r
51795 end;\r
51796 {$ENDIF}\r
51799 //////////////////////////////////////////////////////////////////\r
51800 //\r
51801 //                          T  I  M  E  R\r
51802 //\r
51803 //////////////////////////////////////////////////////////////////\r
51805 var TimerOwnerWnd: PControl;\r
51806     TimerCount: Integer = 0;\r
51808 { -- Constructor of timer -- }\r
51810 //[function NewTimer]\r
51811 function NewTimer( Interval: Integer ): PTimer;\r
51812 begin\r
51813   {-}\r
51814   New( Result, Create );\r
51815   {+}{++}(*Result := PTimer.Create;*){--}\r
51816   if Interval <= 0 then Interval := 1000;\r
51817   Result.fInterval := Interval;\r
51818   Inc( TimerCount );\r
51819 end;\r
51820 //[END NewTimer]\r
51822 { -- Timer procedure -- }\r
51824 //[FUNCTION TimerProc]\r
51825 {$IFDEF ASM_VERSION}\r
51826 function TimerProc( Wnd : HWnd; Msg : Integer; T : PTimer; CurrentTime : DWord ): Integer;\r
51827           stdcall;\r
51828 asm     //cmd    //opd\r
51829         MOV      EDX, T\r
51830         MOV      ECX, [EDX].TTimer.fOnTimer.TMethod.Code\r
51831         JECXZ    @@exit\r
51832         MOV      EAX, [EDX].TTimer.fOnTimer.TMethod.Data\r
51833         CALL     ECX\r
51834 @@exit: XOR      EAX, EAX\r
51835 end;\r
51836 {$ELSE ASM_VERSION} //Pascal\r
51837 function TimerProc( Wnd : HWnd; Msg : Integer; T : PTimer; CurrentTime : DWord ): Integer;\r
51838           stdcall;\r
51839 begin\r
51840   if Assigned( T.fOnTimer ) then\r
51841      T.fOnTimer( T );\r
51842    Result := 0;\r
51843 end;\r
51844 {$ENDIF ASM_VERSION}\r
51845 //[END TimerProc]\r
51847 { TTimer }\r
51849 {$IFDEF ASM_VERSION}\r
51850 //[destructor TTimer.Destroy]\r
51851 destructor TTimer.Destroy;\r
51852 asm\r
51853         PUSH     EAX\r
51854         XOR      EDX, EDX\r
51855         CALL     TTimer.SetEnabled\r
51856         POP      EAX\r
51857         CALL     TObj.Destroy\r
51858         DEC      [TimerCount]\r
51859         JNZ      @@exit\r
51860         XOR      EAX, EAX\r
51861         XCHG     EAX, [TimerOwnerWnd]\r
51862         CALL     TObj.Free\r
51863 @@exit:\r
51864 end;\r
51865 {$ELSE ASM_VERSION} //Pascal\r
51866 destructor TTimer.Destroy;\r
51867 begin\r
51868   Enabled := False;\r
51869   inherited;\r
51870   Dec( TimerCount );\r
51871   if TimerCount = 0 then\r
51872   begin\r
51873     TimerOwnerWnd.Free;\r
51874     TimerOwnerWnd := nil;\r
51875   end;\r
51876 end;\r
51877 {$ENDIF ASM_VERSION}\r
51879 {$IFDEF ASM_VERSION}\r
51880 //[procedure TTimer.SetEnabled]\r
51881 procedure TTimer.SetEnabled(const Value: Boolean);\r
51882 asm\r
51883         PUSH     EBX\r
51884         XCHG     EBX, EAX\r
51886         CMP      [EBX].fEnabled, DL\r
51887         JZ       @@exit\r
51889         MOV      [EBX].fEnabled, DL\r
51891         TEST     DL, DL\r
51892         JZ       @@disable\r
51894         MOV      ECX, [TimerOwnerWnd]\r
51895         INC      ECX\r
51896         LOOP     @@owner_ready\r
51898         INC      ECX\r
51899         MOV      EDX, offset[EmptyString]\r
51900         XOR      EAX, EAX\r
51901         CALL     _NewWindowed\r
51902         MOV      [TimerOwnerWnd], EAX\r
51903         MOV      [EAX].TControl.fStyle, 0\r
51904         INC      [EAX].TControl.fIsControl\r
51905         XCHG     ECX, EAX\r
51907 @@owner_ready:\r
51909         PUSH     offset[TimerProc]\r
51910         PUSH     [EBX].fInterval\r
51911         PUSH     EBX\r
51912         XCHG     EAX, ECX\r
51913         CALL     TControl.GetWindowHandle\r
51914         PUSH     EAX\r
51915         CALL     SetTimer\r
51916         MOV      [EBX].fHandle, EAX\r
51918         JMP      @@exit\r
51920 @@disable:\r
51921         XOR      ECX, ECX\r
51922         XCHG     ECX, [EBX].TTimer.fHandle\r
51923         JECXZ    @@exit\r
51925         PUSH     ECX\r
51926         MOV      EAX, [TimerOwnerWnd]\r
51927         PUSH     [EAX].TControl.fHandle\r
51928         CALL     KillTimer\r
51930 @@exit:\r
51931         POP      EBX\r
51932 end;\r
51933 {$ELSE ASM_VERSION} //Pascal\r
51934 procedure TTimer.SetEnabled(const Value: Boolean);\r
51935 begin\r
51936   if FEnabled = Value then Exit;\r
51937   fEnabled := Value;\r
51938   if Value then\r
51939   begin\r
51940     if TimerOwnerWnd = nil then\r
51941     begin\r
51942       TimerOwnerWnd := _NewWindowed( nil, '', TRUE );\r
51943       TimerOwnerWnd.fStyle := 0;\r
51944       TimerOwnerWnd.fIsControl := TRUE;\r
51945     end;\r
51946     fHandle := SetTimer( TimerOwnerWnd.GetWindowHandle, Integer( @Self ),\r
51947                          fInterval, @TimerProc );\r
51948   end\r
51949      else\r
51950   begin\r
51951     if fHandle <> 0 then\r
51952     begin\r
51953       KillTimer( TimerOwnerWnd.fHandle, fHandle );\r
51954       fHandle := 0;\r
51955     end;\r
51956   end;\r
51957 end;\r
51958 {$ENDIF ASM_VERSION}\r
51960 {$IFDEF ASM_VERSION}\r
51961 //[procedure TTimer.SetInterval]\r
51962 procedure TTimer.SetInterval(const Value: Integer);\r
51963 asm\r
51964         CMP      EDX, [EAX].fInterval\r
51965         JE       @@exit\r
51966         MOV      [EAX].fInterval, EDX\r
51967         PUSH     dword ptr [EAX].fEnabled\r
51968         PUSH     EAX\r
51969         XOR      EDX, EDX\r
51970         CALL     SetEnabled\r
51971         POP      EAX\r
51972         POP      EDX\r
51973         CALL     SetEnabled\r
51974 @@exit:\r
51975 end;\r
51976 {$ELSE ASM_VERSION} //Pascal\r
51977 procedure TTimer.SetInterval(const Value: Integer);\r
51978 var WasEnabled : Boolean;\r
51979 begin\r
51980   if fInterval = Value then Exit;\r
51981   fInterval := Value;\r
51982   WasEnabled := Enabled;\r
51983   Enabled := False;\r
51984   Enabled := WasEnabled;\r
51985 end;\r
51986 {$ENDIF ASM_VERSION}\r
51989 { TMMTimer }\r
51991 { ------------ declarations moved here from MMSystem -------------------- }\r
51992 const\r
51993   TIME_ONESHOT    = 0;   { program timer for single event }\r
51994   TIME_PERIODIC   = 1;   { program for continuous periodic event }\r
51995   TIME_CALLBACK_FUNCTION    = $0000;  { callback is function }\r
51996   TIME_CALLBACK_EVENT_SET   = $0010;  { callback is event - use SetEvent }\r
51997   TIME_CALLBACK_EVENT_PULSE = $0020;  { callback is event - use PulseEvent }\r
51999 type\r
52000   TFNTimeCallBack = procedure(uTimerID, uMessage: UINT;\r
52001     dwUser, dw1, dw2: DWORD) stdcall;\r
52002 //[API timeSetEvent]\r
52003 function timeSetEvent(uDelay, uResolution: UINT;\r
52004   lpFunction: TFNTimeCallBack; dwUser: DWORD; uFlags: UINT): THandle; stdcall;\r
52005   external 'winmm.dll' name 'timeSetEvent';\r
52006 function timeKillEvent(uTimerID: UINT): Integer; stdcall;\r
52007   external 'winmm.dll' name 'timeKillEvent';\r
52008 { ----------------------------------------------------------------------- }\r
52010 //[procedure MMTimerCallback]\r
52011 procedure MMTimerCallback(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD);\r
52012           stdcall;\r
52013 var MMTimer: PMMTimer;\r
52014 begin\r
52015   MMTimer := Pointer( dwUser );\r
52016   if Assigned( MMTimer.FOnTimer ) then\r
52017     MMTimer.fOnTimer( MMTimer );\r
52018 end;\r
52020 //[function NewMMTimer]\r
52021 function NewMMTimer( Interval: Integer ): PMMTimer;\r
52022 begin\r
52023   {-}\r
52024   New( Result, Create );\r
52025   {+} {++}(* Result := PMMTimer.Create; *){--}\r
52026   Result.fInterval := Interval;\r
52027   Result.FPeriodic := TRUE;\r
52028 end;\r
52029 //[END NewMMTimer]\r
52031 //[destructor TMMTimer.Destroy]\r
52032 destructor TMMTimer.Destroy;\r
52033 begin\r
52034   Enabled := FALSE;\r
52035   Inc( TimerCount );\r
52036   inherited;\r
52037 end;\r
52039 //[procedure TMMTimer.SetEnabled]\r
52040 procedure TMMTimer.SetEnabled(const Value: Boolean);\r
52041 begin\r
52042   if Value xor (fHandle <> 0) then\r
52043   begin\r
52044     if fHandle = 0 then\r
52045       fHandle := timeSetEvent( Interval, Resolution, MMTimerCallback, DWORD( @ Self ),\r
52046               Integer( Periodic ) or TIME_CALLBACK_FUNCTION )\r
52047     else\r
52048     begin\r
52049       timeKillEvent( fHandle );\r
52050       fHandle := 0;\r
52051     end;\r
52052   end;\r
52053   fEnabled := Value;\r
52054 end;\r
52066 ////////////////////////////////////////////////////////////////////////\r
52067 //\r
52068 //\r
52069 //                         t  B  I  T  M  A  P\r
52070 //\r
52071 //\r
52072 ///////////////////////////////////////////////////////////////////////\r
52074 { -- bitmap -- }\r
52076 //[FUNCTION PrepareBitmapHeader]\r
52077 {$IFDEF ASM_VERSION}\r
52078 function PrepareBitmapHeader( W, H, BitsPerPixel: Integer ): PBitmapInfo;\r
52079 const szIH = sizeof(TBitmapInfoHeader);\r
52080       szHd = szIH + 256 * Sizeof(TRGBQuad);\r
52081 asm\r
52082         PUSH     EDI\r
52084           PUSH     ECX  // BitsPerPixel\r
52085         PUSH     EDX    // H\r
52086         PUSH     EAX    // W\r
52088         MOV      EAX, szHd\r
52089         CALL     AllocMem\r
52091         MOV      EDI, EAX\r
52092         XCHG     ECX, EAX\r
52094         XOR      EAX, EAX\r
52095         MOV      AL, szIH\r
52096         STOSD           // biSize = Sizeof( TBitmapInfoHeader )\r
52097         POP      EAX    // ^ W\r
52098         STOSD           // -> biWidth\r
52099         POP      EAX    // ^ H\r
52100         STOSD           // -> biHeight\r
52101         XOR      EAX, EAX\r
52102         INC      EAX\r
52103         STOSW           // 1 -> biPlanes\r
52104           POP      EAX  // ^ BitsPerPixel\r
52105         STOSW           // -> biBitCount\r
52107         XCHG     EAX, ECX // EAX = Result\r
52108         POP      EDI\r
52109 end;\r
52110 {$ELSE ASM_VERSION} //Pascal\r
52111 function PrepareBitmapHeader( W, H, BitsPerPixel: Integer ): PBitmapInfo;\r
52112 begin\r
52113   Assert( W > 0, 'Width must be >0' );\r
52114   Assert( H > 0, 'Height must be >0' );\r
52116   Result := AllocMem( 256*Sizeof(TRGBQuad)+Sizeof(TBitmapInfoHeader) );\r
52117   Assert( Result <> nil, 'No memory' );\r
52119   Result.bmiHeader.biSize := Sizeof( TBitmapInfoHeader );\r
52120   Result.bmiHeader.biWidth := W;\r
52121   Result.bmiHeader.biHeight := H; // may be, -H ?\r
52122   Result.bmiHeader.biPlanes := 1;\r
52123   Result.bmiHeader.biBitCount := BitsPerPixel;\r
52124   //Result.bmiHeader.biCompression := BI_RGB; // BI_RGB = 0\r
52125 end;\r
52126 {$ENDIF ASM_VERSION}\r
52127 //[END PrepareBitmapHeader]\r
52129 const\r
52130   BitsPerPixel_By_PixelFormat: array[ TPixelFormat ] of Byte =\r
52131                                ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );\r
52133 //[FUNCTION Bits2PixelFormat]\r
52134 {$IFDEF ASM_VERSION}\r
52135 function Bits2PixelFormat( BitsPerPixel: Integer ): TPixelFormat;\r
52136 asm\r
52137         PUSH     ESI\r
52138         MOV      ESI, offset[ BitsPerPixel_By_PixelFormat + 1 ]\r
52139         XOR      ECX, ECX\r
52140         XCHG     EDX, EAX\r
52141 @@loo:  INC      ECX\r
52142         LODSB\r
52143         CMP      AL, DL\r
52144         JZ       @@exit\r
52145         TEST     AL, AL\r
52146         JNZ      @@loo\r
52147 @@exit: XCHG     EAX, ECX\r
52148         POP      ESI\r
52149 end;\r
52150 {$ELSE ASM_VERSION} //Pascal\r
52151 function Bits2PixelFormat( BitsPerPixel: Integer ): TPixelFormat;\r
52152 var I: TPixelFormat;\r
52153 begin\r
52154   for I := High(I) downto Low(I) do\r
52155     if BitsPerPixel = BitsPerPixel_By_PixelFormat[ I ] then\r
52156     begin\r
52157       Result := I;\r
52158       Exit;\r
52159     end;\r
52160   Result := pfDevice;\r
52161 end;\r
52162 {$ENDIF ASM_VERSION}\r
52163 //[END Bits2PixelFormat]\r
52165 //[procedure DummyDetachCanvas]\r
52166 procedure DummyDetachCanvas( Sender: PBitmap );\r
52167 begin\r
52168 end;\r
52170 //[FUNCTION _NewBitmap]\r
52171 {$IFDEF ASM_VERSION}\r
52172 function _NewBitmap( W, H: Integer ): PBitmap;\r
52173 begin\r
52174   New( Result, Create );\r
52175   Result.fDetachCanvas := DummyDetachCanvas;\r
52176   Result.fWidth := W;\r
52177   Result.fHeight := H;\r
52178 end;\r
52179 {$ENDIF ASM_VERSION}\r
52180 //[END _NewBitmap]\r
52182 //[FUNCTION NewBitmap]\r
52183 {$IFDEF ASM_VERSION}\r
52184 function NewBitmap( W, H: Integer ): PBitmap;\r
52185 asm\r
52186         PUSH     EAX\r
52187         PUSH     EDX\r
52188         CALL     _NewBitmap\r
52189         POP      EDX\r
52190         POP      ECX\r
52191         PUSH     EAX\r
52192         INC      [EAX].TBitmap.fHandleType\r
52193         JECXZ    @@exit\r
52194         TEST     EDX, EDX\r
52195         JZ       @@exit\r
52196         PUSH     EBX\r
52197         PUSH     EAX\r
52198         PUSH     EDX\r
52199         PUSH     ECX\r
52200         PUSH     0\r
52201         CALL     GetDC\r
52202         PUSH     EAX\r
52203         XCHG     EBX, EAX\r
52204         CALL     CreateCompatibleBitmap\r
52205         POP      EDX\r
52206         MOV      [EDX].TBitmap.fHandle, EAX\r
52207         PUSH     EBX\r
52208         PUSH     0\r
52209         CALL     ReleaseDC\r
52210         POP      EBX\r
52211 @@exit: POP      EAX\r
52212 end;\r
52213 {$ELSE ASM_VERSION} //Pascal\r
52214 function NewBitmap( W, H: Integer ): PBitmap;\r
52215 var DC: HDC;\r
52216 begin\r
52217   {-}\r
52218   New( Result, Create );\r
52219   {+}{++}(*Result := PBitmap.Create;*){--}\r
52220   Result.fHandleType := bmDDB;\r
52221   Result.fDetachCanvas := DummyDetachCanvas;\r
52222   Result.fWidth := W;\r
52223   Result.fHeight := H;\r
52224   if (W <> 0) and (H <> 0) then\r
52225   begin\r
52226     //DC := CreateCompatibleDC( 0 );\r
52227     DC := GetDC( 0 );\r
52228     Result.fHandle := CreateCompatibleBitmap( DC, W, H );\r
52229     Assert( Result.fHandle <> 0, 'Can not create bitmap handle' );\r
52230     //DeleteDC( DC );\r
52231     ReleaseDC( 0, DC );\r
52232   end;\r
52233 end;\r
52234 {$ENDIF ASM_VERSION}\r
52235 //[END NewBitmap]\r
52237 const InitColors: array[ 0..17 ] of DWORD = ( $F800, $7E0, $1F, 0, $800000, $8000,\r
52238       $808000, $80, $800080, $8080, $808080, $C0C0C0, $FF0000, $FF00, $FFFF00, $FF,\r
52239       $FF00FF, $FFFF );\r
52240 //[PROCEDURE PreparePF16bit]\r
52241 {$IFDEF ASM_VERSION}\r
52242 procedure PreparePF16bit( DIBHeader: PBitmapInfo );\r
52243 const szBIH = sizeof(TBitmapInfoHeader);\r
52244 asm\r
52245         MOV      byte ptr [EAX].TBitmapInfoHeader.biCompression, BI_BITFIELDS\r
52246         ADD      EAX, szBIH\r
52247         XCHG     EDX, EAX\r
52248         MOV      EAX, offset[InitColors]\r
52249         XOR      ECX, ECX\r
52250         MOV      CL, 19*4\r
52251         CALL     System.Move\r
52252 end;\r
52253 {$ELSE ASM_VERSION} //Pascal\r
52254 procedure PreparePF16bit( DIBHeader: PBitmapInfo );\r
52255 begin\r
52256         DIBHeader.bmiHeader.biCompression := BI_BITFIELDS;\r
52257         Move( InitColors[ 0 ], DIBHeader.bmiColors[ 0 ], 19*Sizeof(TRGBQUAD) );\r
52258 end;\r
52259 {$ENDIF ASM_VERSION}\r
52260 //[END PreparePF16bit]\r
52262 //[FUNCTION NewDIBBitmap]\r
52263 {$IFDEF ASM_VERSION}\r
52264 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;\r
52265 asm\r
52266         PUSH     EBX\r
52268         PUSH     ECX\r
52269         PUSH     EDX\r
52270         PUSH     EAX\r
52271         CALL     _NewBitmap\r
52272         XCHG     EBX, EAX\r
52273         POP      EAX //W\r
52274         POP      EDX //H\r
52275         POP      ECX //PixelFormat\r
52277         TEST     EAX, EAX\r
52278         JZ       @@exit\r
52279         TEST     EDX, EDX\r
52280         JZ       @@exit\r
52282         PUSH     EAX\r
52283         MOVZX    EAX, CL\r
52284         JMP      @@loadBitsPixel\r
52285 @@loadDefault:\r
52286         MOVZX    EAX, [DefaultPixelFormat]\r
52287 @@loadBitsPixel:\r
52288         MOVZX    ECX, byte ptr [ BitsPerPixel_By_PixelFormat + EAX ]\r
52289         JECXZ    @@loadDefault\r
52290         MOV      [EBX].TBitmap.fNewPixelFormat, AL\r
52291         {$IFDEF PARANOIA}\r
52292         DB $3C, pf16bit\r
52293         {$ELSE}\r
52294         CMP      AL, pf16bit\r
52295         {$ENDIF}\r
52296         POP      EAX\r
52298         PUSHFD\r
52299         CALL     PrepareBitmapHeader\r
52300         MOV      [EBX].TBitmap.fDIBHeader, EAX\r
52301         POPFD\r
52302         JNZ      @@2\r
52304         CALL     PreparePF16bit\r
52306 @@2:\r
52307         MOV      EAX, EBX\r
52308         CALL     TBitmap.GetScanLineSize\r
52309         MOV      EDX, [EBX].TBitmap.fHeight\r
52310         MUL      EDX\r
52311         MOV      [EBX].TBitmap.fDIBSize, EAX\r
52312         CALL     AllocMem\r
52313         MOV      [EBX].TBitmap.fDIBBits, EAX\r
52314 @@exit:\r
52315         XCHG     EAX, EBX\r
52316         POP      EBX\r
52317 end;\r
52318 {$ELSE ASM_VERSION} //Pascal\r
52319 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;\r
52320 const BitsPerPixel: array[ TPixelFormat ] of Byte = ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );\r
52321 var BitsPixel: Integer;\r
52322     //AField: PDWORD;\r
52323     //DC0 : HDC;\r
52324 begin\r
52325   {-}\r
52326   New( Result, Create );\r
52327   {+}{++}(*Result := PBitmap.Create;*){--}\r
52328   Result.fDetachCanvas := DummyDetachCanvas;\r
52329   Result.fWidth := W;\r
52330   Result.fHeight := H;\r
52331   if (W <> 0) and (H <> 0) then\r
52332   begin\r
52333     BitsPixel := BitsPerPixel[ PixelFormat ];\r
52334     if BitsPixel = 0 then\r
52335     begin\r
52336        Result.fNewPixelFormat := DefaultPixelFormat;\r
52337        BitsPixel := BitsPerPixel[DefaultPixelFormat];\r
52338     end\r
52339        else\r
52340        Result.fNewPixelFormat := PixelFormat;\r
52341     ASSERT( Result.fNewPixelFormat in [ pf1bit..pf32bit ], 'Strange pixel format' );\r
52342     Result.fDIBHeader := PrepareBitmapHeader( W, H, BitsPixel );\r
52343     if PixelFormat = pf16bit then\r
52344     begin\r
52345       PreparePF16bit( Result.fDIBHeader );\r
52346       {\r
52347       Result.fDIBHeader.bmiHeader.biCompression := BI_BITFIELDS;\r
52348       AField := @Result.fDIBHeader.bmiColors[ 0 ];\r
52349       AField^ := $F800; Inc( AField );\r
52350       AField^ := $07E0; Inc( AField );\r
52351       AField^ := $001F; Inc( AField );\r
52352       DC0 := CreateCompatibleDC( 0 );\r
52353       GetSystemPaletteEntries( DC0, 0, 16, AField^ );\r
52354       DeleteDC( DC0 );\r
52355       }\r
52356     end;\r
52358     Result.fDIBSize := Result.ScanLineSize * H;\r
52359     Result.fDIBBits := AllocMem( Result.fDIBSize );\r
52360     ASSERT( Result.fDIBBits <> nil, 'No memory' );\r
52361   end;\r
52362 end;\r
52363 {$ENDIF ASM_VERSION}\r
52364 //[END NewDIBBitmap]\r
52366 { TBitmap }\r
52368 {$IFDEF ASM_VERSION}\r
52369 //[procedure TBitmap.ClearData]\r
52370 procedure TBitmap.ClearData;\r
52371 asm\r
52372         PUSH     EBX\r
52373         MOV      EBX, EAX\r
52374         CALL     [EBX].fDetachCanvas\r
52375         XOR      ECX, ECX\r
52376         XCHG     ECX, [EBX].fHandle\r
52377         JECXZ    @@1\r
52378         PUSH     ECX\r
52379         CALL     DeleteObject\r
52380         XOR      ECX, ECX\r
52381         MOV      [EBX].fDIBBits, ECX\r
52382 @@1:    XCHG     ECX, [EBX].fDIBBits\r
52383         JECXZ    @@2\r
52384         XCHG     EAX, ECX\r
52385         CALL     System.@FreeMem\r
52386 @@2:    XOR      ECX, ECX\r
52387         XCHG     ECX, [EBX].fDIBHeader\r
52388         JECXZ    @@3\r
52389         XCHG     EAX, ECX\r
52390         CALL     System.@FreeMem\r
52391 @@3:    XOR      EAX, EAX\r
52392         MOV      [EBX].fScanLineSize, EAX\r
52393         MOV      [EBX].fGetDIBPixels, EAX\r
52394         MOV      [EBX].fSetDIBPixels, EAX\r
52395         XCHG     EAX, EBX\r
52396         POP      EBX\r
52397         CALL     ClearTransImage\r
52398 end;\r
52399 {$ELSE ASM_VERSION} //Pascal\r
52400 procedure TBitmap.ClearData;\r
52401 begin\r
52402   fDetachCanvas( @Self );\r
52403   if fHandle <> 0 then\r
52404   begin\r
52405     DeleteObject( fHandle );\r
52406     fHandle := 0;\r
52407     fDIBBits := nil;\r
52408     //fDIBHeader := nil;\r
52409   end;\r
52410   if fDIBBits <> nil then\r
52411   begin\r
52412     FreeMem( fDIBBits );\r
52413     fDIBBits := nil;\r
52414   end;\r
52415   if fDIBHeader <> nil then\r
52416   begin\r
52417     FreeMem( fDIBHeader );\r
52418     fDIBHeader := nil;\r
52419   end;\r
52420   fScanLineSize := 0;\r
52421   fGetDIBPixels := nil;\r
52422   fSetDIBPixels := nil;\r
52423   ClearTransImage;\r
52424 end;\r
52425 {$ENDIF ASM_VERSION}\r
52427 {$IFDEF ASM_VERSION}\r
52428 //[procedure TBitmap.Clear]\r
52429 procedure TBitmap.Clear;\r
52430 asm\r
52431         PUSH     EAX\r
52432         CALL     RemoveCanvas\r
52433         POP      EAX\r
52434         PUSH     EAX\r
52435         CALL     ClearData\r
52436         POP      EAX\r
52437         XOR      EDX, EDX\r
52438         MOV      [EAX].fWidth, EDX\r
52439         MOV      [EAX].fHeight, EDX\r
52440         MOV      [EAX].fDIBAutoFree, DL\r
52441 end;\r
52442 {$ELSE ASM_VERSION} //Pascal\r
52443 procedure TBitmap.Clear;\r
52444 begin\r
52445   RemoveCanvas;\r
52446   ClearData;\r
52447   fWidth := 0;\r
52448   fHeight := 0;\r
52449   fDIBAutoFree := FALSE;\r
52450 end;\r
52451 {$ENDIF ASM_VERSION}\r
52453 //[function TBitmap.GetBoundsRect]\r
52454 function TBitmap.GetBoundsRect: TRect;\r
52455 begin\r
52456   Result := MakeRect( 0, 0, Width, Height );\r
52457 end;\r
52459 {$IFDEF ASM_VERSION}\r
52460 //[destructor TBitmap.Destroy]\r
52461 destructor TBitmap.Destroy;\r
52462 asm\r
52463         PUSH     EAX\r
52464         CALL     Clear\r
52465         POP      EAX\r
52466         CALL     TObj.Destroy\r
52467 end;\r
52468 {$ELSE ASM_VERSION} //Pascal\r
52469 destructor TBitmap.Destroy;\r
52470 begin\r
52471   Clear;\r
52472   inherited;\r
52473 end;\r
52474 {$ENDIF ASM_VERSION}\r
52476 //[function TBitmap.BitsPerPixel]\r
52477 function TBitmap.BitsPerPixel: Integer;\r
52478 var B: tagBitmap;\r
52479 begin\r
52480   CASE PixelFormat OF\r
52481   pf1bit: Result := 1;\r
52482   pf4bit: Result := 4;\r
52483   pf8bit: Result := 8;\r
52484   pf15bit: Result := 15;\r
52485   pf16bit: Result := 16;\r
52486   pf24bit: Result := 24;\r
52487   pf32bit: Result := 32;\r
52488   else begin\r
52489          Result := 0;\r
52490          if fHandle <> 0 then\r
52491          if GetObject( fHandle, Sizeof( B ), @B ) > 0 then\r
52492            Result := B.bmBitsPixel * B.bmPlanes;\r
52493        end;\r
52494   END;\r
52495 end;\r
52497 {$IFDEF ASM_VERSION}\r
52498 //[procedure TBitmap.Draw]\r
52499 procedure TBitmap.Draw(DC: HDC; X, Y: Integer);\r
52500 const szBitmap = sizeof( tagBitmap );\r
52501 asm                       // [EBP+8] = Y\r
52502         PUSH     EDX      // [EBP-4] = DC\r
52503         PUSH     ECX      // [EBP-8] = X\r
52504         PUSH     EBX\r
52505         PUSH     ESI\r
52506 @@try_again:\r
52507         MOV      EBX, EAX\r
52508         CALL     GetEmpty // GetEmpty must be assembler version !\r
52509         JZ       @@exit\r
52511         MOV      ECX, [EBX].fHandle\r
52512         JECXZ    @@2\r
52514         //MOV      EAX, EBX\r
52515         //CALL     [EBX].fDetachCanvas // detached in StartDC\r
52517         ADD      ESP, -szBitmap\r
52518         PUSH     ESP\r
52519         PUSH     szBitmap\r
52520         PUSH     [EBX].fHandle\r
52521         CALL     GetObject\r
52522         TEST     EAX, EAX\r
52523         MOV      ESI, [ESP].tagBitmap.bmHeight\r
52524         {$IFDEF USE_CMOV}\r
52525         CMOVZ    ESI, [EBX].fHeight\r
52526         {$ELSE}\r
52527         JNZ      @@1\r
52528         MOV      ESI, [EBX].fHeight\r
52529 @@1:    {$ENDIF}\r
52531         ADD      ESP, szBitmap\r
52532         CALL     StartDC\r
52534         PUSH     SRCCOPY\r
52535         PUSH     0\r
52536         PUSH     0\r
52537         PUSH     EAX\r
52538         CALL     @@prepare\r
52539         CALL     BitBlt\r
52540         CALL     FinishDC\r
52541         JMP      @@exit\r
52543 @@prepare:\r
52544         XCHG     ESI, [ESP]\r
52545         PUSH     [EBX].fWidth\r
52546         PUSH     Y\r
52547         PUSH     dword ptr [EBP-8]\r
52548         PUSH     dword ptr [EBP-4]\r
52549         JMP      ESI\r
52551 @@2:\r
52552         MOV      ECX, [EBX].fDIBHeader\r
52553         JECXZ    @@exit\r
52555         MOV      ESI, [ECX].TBitmapInfoHeader.biHeight\r
52556         TEST     ESI, ESI\r
52557         JGE      @@20\r
52558         NEG      ESI\r
52559 @@20:\r
52560         PUSH     SRCCOPY\r
52561         PUSH     DIB_RGB_COLORS\r
52562         PUSH     ECX\r
52563         PUSH     [EBX].fDIBBits\r
52564         PUSH     ESI\r
52565         PUSH     [EBX].fWidth\r
52566         PUSH     0\r
52567         PUSH     0\r
52568         CALL     @@prepare\r
52569         CALL     StretchDIBits\r
52570         TEST     EAX, EAX\r
52571         JNZ      @@exit\r
52572         MOV      EAX, EBX\r
52573         CALL     GetHandle\r
52574         TEST     EAX, EAX\r
52575         XCHG     EAX, EBX\r
52576         JNZ      @@try_again\r
52577 @@exit:\r
52578         POP      ESI\r
52579         POP      EBX\r
52580         MOV      ESP, EBP\r
52581 end;\r
52582 {$ELSE ASM_VERSION} //Pascal\r
52583 procedure TBitmap.Draw(DC: HDC; X, Y: Integer);\r
52584 var\r
52585     DCfrom, DC0: HDC;\r
52586     oldBmp: HBitmap;\r
52587     oldHeight: Integer;\r
52588     B: tagBitmap;\r
52589 label\r
52590     TRYAgain;\r
52591 begin\r
52592 TRYAgain:\r
52593   if Empty then Exit;\r
52594   if fHandle <> 0 then\r
52595   begin\r
52596     fDetachCanvas( @Self );\r
52597     oldHeight := fHeight;\r
52598     if GetObject( fHandle, sizeof( B ), @B ) <> 0 then\r
52599        oldHeight := B.bmHeight;\r
52600     ASSERT( oldHeight > 0, 'oldHeight must be > 0' );\r
52602     DC0 := GetDC( 0 );\r
52603     DCfrom := CreateCompatibleDC( DC0 );\r
52604     ReleaseDC( 0, DC0 );\r
52606     oldBmp := SelectObject( DCfrom, fHandle );\r
52607     ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );\r
52609     BitBlt( DC, X, Y, fWidth, oldHeight, DCfrom, 0, 0, SRCCOPY );\r
52610     {$IFDEF CHK_BITBLT} Chk_BitBlt; {$ENDIF}\r
52612     SelectObject( DCfrom, oldBmp );\r
52613     DeleteDC( DCfrom );\r
52614   end\r
52615      else\r
52616   if fDIBBits <> nil then\r
52617   begin\r
52618     oldHeight := Abs(fDIBHeader.bmiHeader.biHeight);\r
52619     ASSERT( oldHeight > 0, 'oldHeight must be > 0' );\r
52620     ASSERT( fWidth > 0, 'Width must be > 0' );\r
52621     if StretchDIBits( DC, X, Y, fWidth, oldHeight, 0, 0, fWidth, oldHeight,\r
52622                    fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY ) = 0 then\r
52623     begin\r
52624       if GetHandle <> 0 then\r
52625         goto TRYAgain;\r
52626     end;\r
52627   end;\r
52628 end;\r
52629 {$ENDIF ASM_VERSION}\r
52631 {$IFDEF ASM_VERSION}\r
52632 //[procedure TBitmap.StretchDraw]\r
52633 procedure TBitmap.StretchDraw(DC: HDC; const Rect: TRect);\r
52634 asm\r
52635         PUSH     EBX\r
52636         PUSH     EDI\r
52637         PUSH     EBP\r
52638         MOV      EBP, ESP\r
52639         PUSH     EDX\r
52640         PUSH     ECX\r
52641         MOV      EBX, EAX\r
52642         CALL     GetEmpty\r
52643         JZ       @@exit\r
52645         MOV      ECX, [EBX].fHandle\r
52646         JECXZ    @@2\r
52648 @@0:\r
52649         CALL     StartDC\r
52650         PUSH     SRCCOPY\r
52651         PUSH     [EBX].fHeight\r
52652         PUSH     [EBX].fWidth\r
52653         PUSH     0\r
52654         PUSH     0\r
52655         PUSH     EAX\r
52657         CALL     @@prepare\r
52658         CALL     StretchBlt\r
52659         CALL     FinishDC\r
52660         JMP      @@exit\r
52662 @@prepare:\r
52663         POP      EDI\r
52664         MOV      EAX, [EBP-8]\r
52665         MOV      EDX, [EAX].TRect.Bottom\r
52666         MOV      ECX, [EAX].TRect.Top\r
52667         SUB      EDX, ECX\r
52668         PUSH     EDX\r
52669         MOV      EDX, [EAX].TRect.Right\r
52670         MOV      EAX, [EAX].TRect.Left\r
52671         SUB      EDX, EAX\r
52672         PUSH     EDX\r
52673         PUSH     ECX\r
52674         PUSH     EAX\r
52675         PUSH     dword ptr [EBP-4]\r
52676         JMP      EDI\r
52679 @@2:    MOV      ECX, [EBX].fDIBHeader\r
52680         JECXZ    @@exit\r
52682         PUSH     SRCCOPY\r
52683         PUSH     DIB_RGB_COLORS\r
52684         PUSH     ECX\r
52685         PUSH     [EBX].fDIBBits\r
52686         PUSH     [EBX].fHeight\r
52687         PUSH     [EBX].fWidth\r
52688         PUSH     0\r
52689         PUSH     0\r
52690         CALL     @@prepare\r
52691         CALL     StretchDIBits\r
52692         TEST     EAX, EAX\r
52693         JG       @@exit\r
52695         MOV      EAX, EBX\r
52696         CALL     GetHandle\r
52697         MOV      ECX, [EBX].fHandle\r
52698         JECXZ    @@exit\r
52699         JMP      @@0\r
52701 @@exit: MOV      ESP, EBP\r
52702         POP      EBP\r
52703         POP      EDI\r
52704         POP      EBX\r
52705 end;\r
52706 {$ELSE ASM_VERSION} //Pascal\r
52707 procedure TBitmap.StretchDraw(DC: HDC; const Rect: TRect);\r
52708 var DCfrom: HDC;\r
52709     oldBmp: HBitmap;\r
52710 label DrawHandle;\r
52711 begin\r
52712   if Empty then Exit;\r
52713 DrawHandle:\r
52714   if fHandle <> 0 then\r
52715   begin\r
52716     fDetachCanvas( @Self );\r
52717     DCfrom := CreateCompatibleDC( 0 );\r
52718     oldBmp := SelectObject( DCfrom, fHandle );\r
52719     ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );\r
52720     StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left,\r
52721                 Rect.Bottom - Rect.Top, DCfrom, 0, 0, fWidth, fHeight,\r
52722                 SRCCOPY );\r
52723     SelectObject( DCfrom, oldBmp );\r
52724     DeleteDC( DCfrom );\r
52725   end\r
52726      else\r
52727   if fDIBBits <> nil then\r
52728   begin\r
52729     if StretchDIBits( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left,\r
52730                 Rect.Bottom - Rect.Top, 0, 0, fWidth, fHeight,\r
52731                 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY )<=0 then\r
52732     begin\r
52733       if GetHandle <> 0 then\r
52734         goto DrawHandle;\r
52735     end;\r
52736   end;\r
52737 end;\r
52738 {$ENDIF ASM_VERSION}\r
52740 //[procedure TBitmap.DrawMasked]\r
52741 procedure TBitmap.DrawMasked(DC: HDC; X, Y: Integer; Mask: HBitmap);\r
52742 begin\r
52743   StretchDrawMasked( DC, MakeRect( X, Y, X + fWidth, Y + fHeight ), Mask );\r
52744 end;\r
52746 {$IFDEF ASM_VERSION}\r
52747 //[procedure TBitmap.DrawTransparent]\r
52748 procedure TBitmap.DrawTransparent(DC: HDC; X, Y: Integer; TranspColor: TColor);\r
52749 asm\r
52750         PUSH     ECX\r
52751         MOV      ECX, TranspColor\r
52752         INC      ECX\r
52753         MOV      ECX, [Y]\r
52754         JNZ      @@2\r
52755         XCHG     ECX, [ESP]\r
52756         CALL     Draw\r
52757         JMP      @@exit\r
52758 @@2:\r
52759         ADD      ECX, [EAX].fHeight\r
52760         PUSH     ECX\r
52761         MOV      ECX, [EBP-4]\r
52762         ADD      ECX, [EAX].fWidth\r
52763         PUSH     ECX\r
52764         PUSH     [Y]\r
52765         PUSH     dword ptr [EBP-4]\r
52766         MOV      ECX, ESP\r
52767         PUSH     [TranspColor]\r
52768         CALL     StretchDrawTransparent\r
52769 @@exit:\r
52770         MOV      ESP, EBP\r
52771 end;\r
52772 {$ELSE ASM_VERSION} //Pascal\r
52773 procedure TBitmap.DrawTransparent(DC: HDC; X, Y: Integer; TranspColor: TColor);\r
52774 begin\r
52775   if TranspColor = clNone then\r
52776     Draw( DC, X, Y )\r
52777   else\r
52778     StretchDrawTransparent( DC, MakeRect( X, Y, X + fWidth, Y + fHeight ),\r
52779                             TranspColor );\r
52780 end;\r
52781 {$ENDIF ASM_VERSION}\r
52783 {$IFDEF ASM_VERSION}\r
52784 //[procedure TBitmap.StretchDrawTransparent]\r
52785 procedure TBitmap.StretchDrawTransparent(DC: HDC; const Rect: TRect; TranspColor: TColor);\r
52786 asm\r
52787         PUSH     EBX\r
52788         XCHG     EBX, EAX\r
52789         MOV      EAX, [TranspColor]\r
52790         INC      EAX\r
52791         MOV      EAX, EBX\r
52792         JNZ      @@2\r
52793         CALL     StretchDraw\r
52794         JMP      @@exit\r
52795 @@2:\r
52796         PUSH     EDX\r
52797         PUSH     ECX\r
52798         CALL     GetHandle\r
52799         TEST     EAX, EAX\r
52800         JZ       @@exit2\r
52802         MOV      EAX, [TranspColor]\r
52803         CALL     Color2RGB\r
52804         MOV      ECX, [EBX].fTransMaskBmp\r
52805         JECXZ    @@makemask0\r
52806         CMP      EAX, [EBX].fTransColor\r
52807         JE       @@3\r
52808 @@makemask0:\r
52809         MOV      [EBX].fTransColor, EAX\r
52810         INC      ECX\r
52811         LOOP     @@20\r
52812         //MOV      EAX, [EBX].fWidth\r
52813         //MOV      EDX, [EBX].fHeight\r
52814         XOR      EAX, EAX // pass height = 0\r
52815         // absolutely no matter what to pass as width\r
52816         CALL     NewBitmap\r
52817         MOV      [EBX].fTransMaskBmp, EAX\r
52818 @@20:\r
52819         MOV      EAX, [EBX].fTransMaskBmp\r
52820         PUSH     EAX\r
52821         MOV      EDX, EBX\r
52822         CALL     Assign\r
52823         POP      EAX\r
52824         MOV      EDX, [EBX].fTransColor\r
52825         CALL     Convert2Mask\r
52826 @@3:\r
52827         MOV      EAX, [EBX].fTransMaskBmp\r
52828         CALL     GetHandle\r
52829         POP      ECX\r
52830         POP      EDX\r
52831         PUSH     EAX\r
52832         XCHG     EAX, EBX\r
52833         CALL     StretchDrawMasked\r
52834         JMP      @@exit\r
52835 @@exit2:\r
52836         POP      ECX\r
52837         POP      EDX\r
52838 @@exit:\r
52839         POP      EBX\r
52840 end;\r
52841 {$ELSE ASM_VERSION} //Pascal\r
52842 procedure TBitmap.StretchDrawTransparent(DC: HDC; const Rect: TRect; TranspColor: TColor);\r
52843 begin\r
52844   if TranspColor = clNone then\r
52845      StretchDraw( DC, Rect )\r
52846   else\r
52847   begin\r
52848     if GetHandle = 0 then Exit;\r
52849     TranspColor := Color2RGB( TranspColor );\r
52850     if (fTransMaskBmp = nil) or (fTransColor <> TranspColor) then\r
52851     begin\r
52852       if fTransMaskBmp = nil then\r
52853         fTransMaskBmp := NewBitmap( 0, 0 {fWidth, fHeight} );\r
52854       fTransColor := TranspColor;\r
52855       // Create here mask bitmap:\r
52856       fTransMaskBmp.Assign( @Self );\r
52857       fTransMaskBmp.Convert2Mask( TranspColor );\r
52858     end;\r
52859     StretchDrawMasked( DC, Rect, fTransMaskBmp.Handle );\r
52860   end;\r
52861 end;\r
52862 {$ENDIF ASM_VERSION}\r
52864 const\r
52865   ROP_DstCopy = $00AA0029;\r
52866 {$IFDEF ASM_VERSION}\r
52867 //[procedure TBitmap.StretchDrawMasked]\r
52868 procedure TBitmap.StretchDrawMasked(DC: HDC; const Rect: TRect; Mask: HBitmap);\r
52869 asm\r
52870         PUSH     EDX                    // [EBP-4] = DC\r
52871         PUSH     ECX                    // [EBP-8] = Rect\r
52872         PUSH     EBX                    // save EBX\r
52873         MOV      EBX, EAX\r
52874         PUSH     ESI                    // save ESI\r
52875         CALL     GetHandle\r
52876         TEST     EAX, EAX\r
52877         JZ       @@to_exit\r
52879         PUSH     0\r
52880         CALL     CreateCompatibleDC\r
52881         PUSH     EAX                    // [EBP-20] = MaskDC\r
52883         PUSH     [Mask]\r
52884         PUSH     EAX\r
52885         CALL     SelectObject\r
52886         PUSH     EAX                    // [EBP-24] = Save4Mask\r
52888         CALL     StartDC                // [EBP-28] = DCfrom; [EBP-32] = Save4From\r
52890         PUSH     [EBX].fHeight\r
52891         PUSH     [EBX].fWidth\r
52892         PUSH     EAX\r
52893         CALL     CreateCompatibleBitmap\r
52894         PUSH     EAX                    // [EBP-36] = MemBmp\r
52896         PUSH     0\r
52897         CALL     CreateCompatibleDC\r
52898         PUSH     EAX                    // [EBP-40] = MemDC\r
52900         PUSH     dword ptr [EBP-36] //MemBmp\r
52901         PUSH     EAX\r
52902         CALL     SelectObject\r
52903         PUSH     EAX                    // [EBP-44] = Save4Mem\r
52905         PUSH     SRCCOPY\r
52906         MOV      EAX, [EBP-20] //MaskDC\r
52907         CALL     @@stretch1\r
52909         PUSH     SRCERASE\r
52910         MOV      EAX, [EBP-28] //DCfrom\r
52911         CALL     @@stretch1\r
52913         PUSH     0\r
52914         PUSH     dword ptr [EBP-4] //DC\r
52915         CALL     SetTextColor\r
52916         PUSH     EAX                    // [EBP-48] = crText\r
52918         PUSH     $FFFFFF\r
52919         PUSH     dword ptr [EBP-4] //DC\r
52920         CALL     Windows.SetBkColor\r
52921         PUSH     EAX                    // [EBP-52] = crBack\r
52923         PUSH     SRCAND\r
52924         MOV      EAX, [EBP-20] //MaskDC\r
52925         CALL     @@stretch2\r
52927         PUSH     SRCINVERT\r
52928         MOV      EAX, [EBP-40] //MemDC\r
52929         CALL     @@stretch2\r
52931         PUSH     dword ptr [EBP-4] //DC\r
52932         CALL     Windows.SetBkColor\r
52934         PUSH     dword ptr [EBP-4] //DC\r
52935         CALL     SetTextColor\r
52937         MOV      ESI, offset[FinishDC]\r
52938         CALL     ESI\r
52939         CALL     DeleteObject   // DeleteObject( MemBmp )\r
52941         CALL     ESI\r
52943         CALL     ESI\r
52944 @@to_exit:\r
52945         STC\r
52946         JC       @@exit\r
52948 @@stretch1:\r
52949         POP      ESI\r
52950         PUSH     [EBX].fHeight\r
52951         PUSH     [EBX].fWidth\r
52952         XOR      EDX, EDX\r
52953         PUSH     EDX\r
52954         PUSH     EDX\r
52955         PUSH     EAX\r
52956         PUSH     [EBX].fHeight\r
52957         PUSH     [EBX].fWidth\r
52958         PUSH     EDX\r
52959         PUSH     EDX\r
52960         PUSH     dword ptr [EBP-40] //MemDC\r
52961         JMP      @@stretch3\r
52963 @@stretch2:\r
52964         POP      ESI\r
52965         PUSH     [EBX].fHeight\r
52966         PUSH     [EBX].fWidth\r
52967         PUSH     0\r
52968         PUSH     0\r
52969         PUSH     EAX\r
52970         MOV      EAX, [EBP-8] //Rect\r
52971         MOV      EDX, [EAX].TRect.Bottom\r
52972         MOV      ECX, [EAX].TRect.Top\r
52973         SUB      EDX, ECX\r
52974         PUSH     EDX\r
52975         MOV      EDX, [EAX].TRect.Right\r
52976         MOV      EAX, [EAX].TRect.Left\r
52977         SUB      EDX, EAX\r
52978         PUSH     EDX\r
52979         PUSH     ECX\r
52980         PUSH     EAX\r
52981         PUSH     dword ptr [EBP-4] //DC\r
52982 @@stretch3:\r
52983         CALL     StretchBlt\r
52984         JMP      ESI\r
52986 @@exit:\r
52987         POP      ESI\r
52988         POP      EBX\r
52989         MOV      ESP, EBP\r
52990 end;\r
52991 {$ELSE ASM_VERSION} //Pascal\r
52992 procedure TBitmap.StretchDrawMasked(DC: HDC; const Rect: TRect; Mask: HBitmap);\r
52993 var\r
52994   DCfrom, MemDC, MaskDC: HDC;\r
52995   MemBmp: HBITMAP;\r
52996   Save4From, Save4Mem, Save4Mask: THandle;\r
52997   crText, crBack: TColorRef;\r
52998   //SavePal: HPALETTE;\r
52999 begin\r
53000   if GetHandle = 0 then Exit;\r
53001   fDetachCanvas( @Self );\r
53002     //SavePal := 0;\r
53004   DCfrom := CreateCompatibleDC( 0 );\r
53005   Save4From := SelectObject( DCfrom, fHandle );\r
53006   ASSERT( Save4From <> 0, 'Can not select source bitmap to DC' );\r
53007   MaskDC := CreateCompatibleDC( 0 );\r
53008   Save4Mask := SelectObject( MaskDC, Mask );\r
53009   ASSERT( Save4Mask <> 0, 'Can not select mask bitmap to DC' );\r
53010   MemDC := CreateCompatibleDC( 0 );\r
53011     //try\r
53012       MemBmp := CreateCompatibleBitmap( DCfrom, fWidth, fHeight );\r
53013       Save4Mem := SelectObject( MemDC, MemBmp );\r
53014       ASSERT( Save4Mem <> 0, 'Can not select memory bitmap to DC' );\r
53015       //SavePal := SelectPalette(DCfrom, SystemPalette16, False);\r
53016       //SelectPalette(DCfrom, SavePal, False);\r
53017       //if SavePal <> 0 then\r
53018       //  SavePal := SelectPalette(MemDC, SavePal, True)\r
53019       //else\r
53020       //  SavePal := SelectPalette(MemDC, SystemPalette16, True);\r
53021       //RealizePalette(MemDC);\r
53023       StretchBlt( MemDC, 0, 0, fWidth, fHeight, MaskDC, 0, 0, fWidth, fHeight, SrcCopy);\r
53024       StretchBlt( MemDC, 0, 0, fWidth, fHeight, DCfrom, 0, 0, fWidth, fHeight, SrcErase);\r
53025       crText := SetTextColor(DC, $0);\r
53026       crBack := Windows.SetBkColor(DC, $FFFFFF);\r
53027       StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,\r
53028                   MaskDC, 0, 0, fWidth, fHeight, SrcAnd);\r
53029       StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,\r
53030                   MemDC, 0, 0, fWidth, fHeight, SrcInvert);\r
53031       Windows.SetBkColor( DC, crBack);\r
53032       SetTextColor( DC, crText);\r
53034       if Save4Mem <> 0 then\r
53035          SelectObject( MemDC, Save4Mem );\r
53036       DeleteObject(MemBmp);\r
53037     //finally\r
53038       //if SavePal <> 0 then SelectPalette(MemDC, SavePal, False);\r
53039       DeleteDC(MemDC);\r
53040       SelectObject( DCfrom, Save4From );\r
53041       DeleteDC( DCfrom );\r
53042       SelectObject( MaskDC, Save4Mask );\r
53043       DeleteDC( MaskDC );\r
53044     //end;\r
53045 end;\r
53046 {$ENDIF ASM_VERSION}\r
53048 //[procedure ApplyBitmapBkColor2Canvas]\r
53049 procedure ApplyBitmapBkColor2Canvas( Sender: PBitmap );\r
53050 begin\r
53051   if Sender.fCanvas = nil then Exit;\r
53052   Sender.fCanvas.Brush.Color := Sender.BkColor;\r
53053 end;\r
53055 //[PROCEDURE DetachBitmapFromCanvas]\r
53056 {$IFDEF ASM_VERSION}\r
53057 procedure DetachBitmapFromCanvas( Sender: PBitmap );\r
53058 asm\r
53059         XOR      ECX, ECX\r
53060         XCHG     ECX, [EAX].TBitmap.fCanvasAttached\r
53061         JECXZ    @@exit\r
53062         PUSH     ECX\r
53063         MOV      EAX, [EAX].TBitmap.fCanvas\r
53064         PUSH     [EAX].TCanvas.fHandle\r
53065         CALL     SelectObject\r
53066 @@exit:\r
53067 end;\r
53068 {$ELSE ASM_VERSION} //Pascal\r
53069 procedure DetachBitmapFromCanvas( Sender: PBitmap );\r
53070 begin\r
53071   if Sender.fCanvasAttached = 0 then Exit;\r
53072   SelectObject( Sender.fCanvas.fHandle, Sender.fCanvasAttached );\r
53073   Sender.fCanvasAttached := 0;\r
53074 end;\r
53075 {$ENDIF ASM_VERSION}\r
53076 //[END DetachBitmapFromCanvas]\r
53078 {$IFDEF ASM_VERSION}\r
53079 //[function TBitmap.GetCanvas]\r
53080 function TBitmap.GetCanvas: PCanvas;\r
53081 asm\r
53082         PUSH     EBX\r
53083         MOV      EBX, EAX\r
53084         CALL     GetEmpty\r
53085         JZ       @@exit\r
53086         MOV      EAX, EBX\r
53087         CALL     GetHandle\r
53088         TEST     EAX, EAX\r
53089         JZ       @@exit\r
53090         MOV      ECX, [EBX].fCanvas\r
53091         INC      ECX\r
53092         LOOP     @@ret_Canvas\r
53094         MOV      [EBX].fApplyBkColor2Canvas, offset[ApplyBitmapBkColor2Canvas]\r
53095         PUSH     0\r
53096         CALL     CreateCompatibleDC\r
53097         CALL     NewCanvas\r
53098         MOV      [EBX].fCanvas, EAX\r
53099         MOV      [EAX].TCanvas.fOnChange.TMethod.Code, offset[CanvasChanged]\r
53100         MOV      [EAX].TCanvas.fOnChange.TMethod.Data, EBX\r
53101         CALL     TCanvas.GetBrush\r
53102         XOR      EDX, EDX\r
53103         MOV      ECX, [EBX].fBkColor\r
53104         CALL     TGraphicTool.SetInt\r
53105         \r
53106 @@ret_Canvas:\r
53107         MOV      EAX, [EBX].fCanvas\r
53108         MOV      ECX, [EAX].TCanvas.fHandle\r
53109         INC      ECX\r
53110         LOOP     @@attach_Canvas\r
53111         PUSH     EAX\r
53112         MOV      [EBX].fCanvasAttached, ECX\r
53113         PUSH     ECX\r
53114         CALL     CreateCompatibleDC\r
53115         XCHG     EDX, EAX\r
53116         POP      EAX\r
53117         CALL     TCanvas.SetHandle\r
53119 @@attach_Canvas:\r
53120         MOV      ECX, [EBX].fCanvasAttached\r
53121         INC      ECX\r
53122         LOOP     @@2\r
53123         PUSH     [EBX].fHandle\r
53124         MOV      EAX, [EBX].fCanvas\r
53125         CALL     TCanvas.GetHandle\r
53126         PUSH     EAX\r
53127         CALL     SelectObject\r
53128         MOV      [EBX].fCanvasAttached, EAX\r
53130 @@2:    MOV      [EBX].fDetachCanvas, offset[DetachBitmapFromCanvas]\r
53131         MOV      EAX, [EBX].fCanvas\r
53132 @@exit: POP      EBX\r
53133 end;\r
53134 {$ELSE ASM_VERSION} //Pascal\r
53135 function TBitmap.GetCanvas: PCanvas;\r
53136 var DC: HDC;\r
53137 begin\r
53138   Result := nil;\r
53139   if Empty then Exit;\r
53140   if GetHandle = 0 then Exit;\r
53141   if fCanvas = nil then\r
53142   begin\r
53143     fApplyBkColor2Canvas := ApplyBitmapBkColor2Canvas;\r
53144     DC := CreateCompatibleDC( 0 );\r
53145     fCanvas := NewCanvas( DC );\r
53146     fCanvas.fIsPaintDC := FALSE;\r
53147     fCanvas.OnChange := CanvasChanged;\r
53148     fCanvas.Brush.Color := fBkColor;\r
53149   end;\r
53150   Result := fCanvas;\r
53152   if fCanvas.fHandle = 0 then\r
53153   begin\r
53154     DC := CreateCompatibleDC( 0 );\r
53155     fCanvas.Handle := DC;\r
53156     fCanvasAttached := 0;\r
53157   end;\r
53159   if fCanvasAttached = 0 then\r
53160   begin\r
53161     fCanvasAttached := SelectObject( fCanvas.Handle, fHandle );\r
53162     ASSERT( fCanvasAttached <> 0, 'Can not select bitmap to DC of Canvas' );\r
53163   end;\r
53164   fDetachCanvas := DetachBitmapFromCanvas;\r
53165 end;\r
53166 {$ENDIF ASM_VERSION}\r
53168 {$IFDEF ASM_VERSION}\r
53169 //[function TBitmap.GetEmpty]\r
53170 function TBitmap.GetEmpty: Boolean;\r
53171 asm\r
53172         PUSH     ECX\r
53173         MOV      ECX, [EAX].fWidth\r
53174         JECXZ    @@1\r
53175         MOV      ECX, [EAX].fHeight\r
53176 @@1:    TEST     ECX, ECX\r
53177         POP      ECX\r
53178         SETZ     AL\r
53179 end;\r
53180 {$ELSE ASM_VERSION} //Pascal\r
53181 function TBitmap.GetEmpty: Boolean;\r
53182 begin\r
53183   Result := (fWidth = 0) or (fHeight = 0);\r
53184   ASSERT( (fWidth >= 0) and (fHeight >= 0), 'Bitmap dimensions can be negative' );\r
53185 end;\r
53186 {$ENDIF ASM_VERSION}\r
53188 {$IFDEF ASM_noVERSION}\r
53189 //[function TBitmap.GetHandle]\r
53190 function TBitmap.GetHandle: HBitmap;\r
53191 asm\r
53192         PUSH     EBX\r
53193         MOV      EBX, EAX\r
53194         CALL     GetEmpty\r
53195         JZ       @@exit\r
53196         MOV      ECX, [EBX].fHandle\r
53197         INC      ECX\r
53198         LOOP     @@exit\r
53200         MOV      ECX, [EBX].fDIBBits\r
53201         JECXZ    @@exit\r
53203         PUSH     ECX\r
53204         PUSH     0\r
53205         CALL     GetDC\r
53206         PUSH     EAX\r
53207         PUSH     0\r
53208         PUSH     0\r
53209         LEA      EDX, [EBX].fDIBBits\r
53210         PUSH     EDX\r
53211         PUSH     DIB_RGB_COLORS\r
53212         PUSH     [EBX].fDIBHeader\r
53213         PUSH     EAX\r
53214         CALL     CreateDIBSection\r
53215         MOV      [EBX].fHandle, EAX\r
53216         PUSH     0\r
53217         CALL     ReleaseDC\r
53218         POP      EAX\r
53219         PUSH     EAX\r
53220         MOV      EDX, [EBX].fDIBBits\r
53221         MOV      ECX, [EBX].fDIBSize\r
53222         CALL     System.Move\r
53223         POP      EAX\r
53224         CMP      [EBX].fDIBAutoFree, 0\r
53225         JNZ      @@freed\r
53226         CALL     System.@FreeMem\r
53227 @@freed:MOV      [EBX].fDIBAutoFree, 1\r
53228         XOR      EAX, EAX\r
53229         MOV      [EBX].fGetDIBPixels, EAX\r
53230         MOV      [EBX].fSetDIBPixels, EAX\r
53232 @@exit: MOV      EAX, [EBX].fHandle\r
53233         POP      EBX\r
53234 end;\r
53235 {$ELSE ASM_VERSION} //Pascal\r
53236 function TBitmap.GetHandle: HBitmap;\r
53237 var OldBits: Pointer;\r
53238     DC0: HDC;\r
53239     {$IFDEF DEBUG}\r
53240     B: tagBitmap;\r
53241     {$ENDIF}\r
53242 begin\r
53243   Result := 0;\r
53244   if Empty then Exit;\r
53245   if fHandle = 0 then\r
53246   begin\r
53247     if fDIBBits <> nil then\r
53248     begin\r
53249       OldBits := fDIBBits;\r
53250       DC0 := GetDC( 0 );\r
53252       fDIBBits := nil;\r
53253       //fDIBHeader.bmiHeader.biCompression := 0;\r
53254       fHandle := CreateDIBSection( DC0, fDIBHeader^, DIB_RGB_COLORS,\r
53255                     fDIBBits, 0, 0 );\r
53256       {$IFDEF DEBUG}\r
53257       if fHandle = 0 then\r
53258         ShowMessage( 'Can not create DIB section, error: ' + Int2Str( GetLastError ) +\r
53259         ', ' + SysErrorMessage( GetLastError ) );\r
53260       GetObject( fHandle, Sizeof( B ), @ B );\r
53261       {$ELSE}\r
53262       ASSERT( fHandle <> 0, 'Can not create DIB section, error: ' + Int2Str( GetLastError ) +\r
53263       ', ' + SysErrorMessage( GetLastError ) );\r
53264       {$ENDIF}\r
53265       ReleaseDC( 0, DC0 );\r
53266       if fHandle <> 0 then\r
53267       begin\r
53268         Move( OldBits^, fDIBBits^, fDIBSize );\r
53269         if not fDIBAutoFree then\r
53270           FreeMem( OldBits );\r
53271         fDIBAutoFree := TRUE;\r
53273         fGetDIBPixels := nil;\r
53274         fSetDIBPixels := nil;\r
53275       end\r
53276         else\r
53277         fDIBBits := OldBits;\r
53278     end;\r
53279   end;\r
53280   Result := fHandle;\r
53281 end;\r
53282 {$ENDIF ASM_VERSION}\r
53284 //[function TBitmap.GetHandleAllocated]\r
53285 function TBitmap.GetHandleAllocated: Boolean;\r
53286 begin\r
53287   Result := fHandle <> 0;\r
53288 end;\r
53290 {$IFDEF ASM_VERSION}\r
53291 //[procedure TBitmap.LoadFromFile]\r
53292 procedure TBitmap.LoadFromFile(const Filename: String);\r
53293 asm\r
53294         PUSH     EAX\r
53295         XCHG     EAX, EDX\r
53296         CALL     NewReadFileStream\r
53297         XCHG     EDX, EAX\r
53298         POP      EAX\r
53299         PUSH     EDX\r
53300         CALL     LoadFromStream\r
53301         POP      EAX\r
53302         CALL     TObj.Free\r
53303 end;\r
53304 {$ELSE ASM_VERSION} //Pascal\r
53305 procedure TBitmap.LoadFromFile(const Filename: String);\r
53306 var Strm: PStream;\r
53307 begin\r
53308   Strm := NewReadFileStream( Filename );\r
53309   LoadFromStream( Strm );\r
53310   Strm.Free;\r
53311 end;\r
53312 {$ENDIF ASM_VERSION}\r
53314 //[procedure TBitmap.LoadFromResourceID]\r
53315 procedure TBitmap.LoadFromResourceID(Inst: DWORD; ResID: Integer);\r
53316 begin\r
53317   LoadFromResourceName( Inst, MAKEINTRESOURCE( ResID ) );\r
53318 end;\r
53320 {$IFDEF ASM_VERSION}\r
53321 //[procedure TBitmap.LoadFromResourceName]\r
53322 procedure TBitmap.LoadFromResourceName(Inst: DWORD; ResName: PChar);\r
53323 asm\r
53324         PUSH     EBX\r
53325         MOV      EBX, EAX\r
53326         PUSHAD\r
53327         CALL     Clear\r
53328         POPAD\r
53329         XOR      EAX, EAX\r
53330         PUSH     ECX\r
53331         MOVZX    ECX, [EBX].fHandleType\r
53332         INC      ECX\r
53333         LOOP     @@1\r
53334         MOV      AH, LR_CREATEDIBSECTION shr 8 // = $2000\r
53335 @@1:    MOV      AL, LR_DEFAULTSIZE // = $40\r
53336         POP      ECX\r
53337         PUSH     EAX\r
53338         PUSH     0\r
53339         PUSH     0\r
53340         PUSH     IMAGE_BITMAP\r
53341         PUSH     ECX\r
53342         PUSH     EDX\r
53343         CALL     LoadImage\r
53344         TEST     EAX, EAX\r
53345         JZ       @@exit\r
53346         XCHG     EDX, EAX\r
53347         XCHG     EAX, EBX\r
53348         CALL     SetHandle\r
53349 @@exit: POP      EBX\r
53350 end;\r
53351 {$ELSE ASM_VERSION} //Pascal\r
53352 procedure TBitmap.LoadFromResourceName(Inst: DWORD; ResName: PChar);\r
53353 var ResHandle: HBitmap;\r
53354     Flg: DWORD;\r
53355 begin\r
53356   Clear;\r
53357   //ResHandle := LoadBitmap( Inst, ResName );\r
53358   Flg := 0;\r
53359   if fHandleType = bmDIB then\r
53360     Flg := LR_CREATEDIBSECTION;\r
53361   ResHandle := LoadImage( Inst, ResName, IMAGE_BITMAP, 0, 0,\r
53362              LR_DEFAULTSIZE or Flg );\r
53363   if ResHandle = 0 then Exit;\r
53364   //Handle := CopyImage( ResHandle, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG );\r
53365   Handle := ResHandle;\r
53366 end;\r
53367 {$ENDIF ASM_VERSION}\r
53369 {$IFDEF F_P}\r
53370 type\r
53371   TBITMAPFILEHEADER = packed record\r
53372     bfType: Word;\r
53373     bfSize: DWORD;\r
53374     bfReserved1: Word;\r
53375     bfReserved2: Word;\r
53376     bfOffBits: DWORD;\r
53377   end;\r
53378 {$ENDIF}\r
53380 {$IFDEF ASM_noVERSION} // error + 16Colors->swap(Gray,Silver) + Core\r
53381 //[procedure TBitmap.LoadFromStream]\r
53382 procedure TBitmap.LoadFromStream(Strm: PStream);\r
53383 type  tBFH = TBitmapFileHeader;\r
53384       tBIH = TBitmapInfoHeader;\r
53385 const szBIH = Sizeof( tBIH );\r
53386       szBFH = Sizeof( tBFH );\r
53387 asm\r
53388         PUSH     EBX\r
53389         PUSH     ESI\r
53390         MOV      EBX, EAX\r
53391         PUSH     EDX\r
53392         CALL     Clear\r
53393         POP      ESI\r
53394         MOV      EAX, ESI\r
53395         CALL     TStream.GetPosition\r
53396         PUSH     EAX     // [EBP+4] = Strm.Pos (starting pos)\r
53397         PUSH     EBP\r
53398         MOV      EBP, ESP\r
53399         ADD      ESP, -(szBIH + szBFH)\r
53401         // reading bitmap\r
53402         XOR      ECX, ECX\r
53403         MOV      [EBX].fHandleType, CL\r
53404         MOV      CL, szBFH\r
53405         MOV      EDX, ESP\r
53406         PUSH     ECX\r
53407         MOV      EAX, ESI\r
53408         CALL     TStream.Read\r
53409         POP      ECX\r
53410         SUB      ECX, EAX\r
53411         JNZ      @@eread1\r
53413         CMP      [ESP].tBFH.bfType, $4D42\r
53414         JE       @@1\r
53415         MOV      EDX, [EBP+4]\r
53416         MOV      EAX, ESI\r
53417         CALL     TStream.Seek\r
53418         XOR      EAX, EAX\r
53419         XOR      EDX, EDX\r
53420         JMP      @@2\r
53422 @@1:\r
53423         MOV      EDX, [ESP].tBFH.bfSize\r
53424         MOV      EAX, [ESP].tBFH.bfOffBits\r
53425 @@2:\r
53426         PUSH     EDX        // Push Size\r
53427         PUSH     EAX        // Push Off\r
53428         XOR      ECX, ECX\r
53429         MOV      CL, szBIH\r
53430         LEA      EDX, [EBP-szBIH]\r
53431         MOV      EAX, ESI\r
53432         PUSH     ECX\r
53433         CALL     TStream.Read   // read BIH\r
53434         POP      ECX\r
53435 @@eread1:\r
53436         XOR      ECX, EAX\r
53437         JNZ      @@eread\r
53439         MOVZX    EAX, [EBP-szBIH].tBIH.biBitCount\r
53440         MOVZX    EDX, [EBP-szBIH].tBIH.biPlanes\r
53441         MUL      EDX\r
53442         CALL     Bits2PixelFormat\r
53443         {$IFDEF PARANOIA}\r
53444         DB $3C, pf15bit\r
53445         {$ELSE}\r
53446         CMP      AL, pf15bit\r
53447         {$ENDIF}\r
53448         JNZ      @@no15bit\r
53449         CMP      [EBP-szBIH].tBIH.biCompression, 0\r
53450         JZ       @@no15bit\r
53451         INC      AL // AL = pf16bit\r
53452 @@no15bit:\r
53453         MOV      [EBX].fNewPixelFormat, AL\r
53455         MOV      EAX, szBIH + 1024\r
53456         CALL     System.@GetMem\r
53457         MOV      [EBX].fDIBHeader, EAX\r
53458         XCHG     EDX, EAX\r
53459         LEA      EAX, [EBP-szBIH]\r
53460         XOR      ECX, ECX\r
53461         MOV      CL, szBIH\r
53462         CALL     System.Move\r
53464         MOV      EAX, [EBP-szBIH].tBIH.biWidth\r
53465         MOV      [EBX].fWidth, EAX\r
53466         MOV      EAX, [EBP-szBIH].tBIH.biHeight\r
53467         TEST     EAX, EAX\r
53468         JGE      @@20\r
53469         NEG      EAX\r
53470 @@20:   MOV      [EBX].fHeight, EAX\r
53472         MOV      EAX, EBX\r
53473         CALL     GetScanLineSize\r
53474         MOV      EDX, [EBX].fHeight\r
53475         MUL      EDX\r
53476         MOV      [EBX].fDIBSize, EAX\r
53477         CALL     AllocMem\r
53478         MOV      [EBX].fDIBBits, EAX\r
53480         MOVZX    EAX, [EBP-szBIH].tBIH.biBitCount\r
53481         {$IFDEF PARANOIA}\r
53482         DB $3C, 8\r
53483         {$ELSE}\r
53484         CMP      AL, 8\r
53485         {$ENDIF}\r
53486         JA       @@3\r
53487         MOV      AL, 4\r
53488         MOVZX    ECX, [EBP-szBIH].tBIH.biBitCount\r
53489         SAL      EAX, CL\r
53490         XCHG     ECX, EAX\r
53491 @@3:\r
53492         CMP      [EBX].TBitmap.fNewPixelFormat, pf16bit\r
53493         JNE      @@30\r
53494         XOR      ECX, ECX\r
53495         MOV      CL, 12 // ColorCount = 12\r
53496 @@30:\r
53497         POP      EAX  // EAX = off\r
53498         TEST     EAX, EAX\r
53499         JLE      @@4\r
53500         SUB      EAX, szBFH + szBIH\r
53501         CMP      EAX, ECX\r
53502         JZ       @@4\r
53503         XCHG     ECX, EAX\r
53504 @@4:\r
53505         JECXZ    @@5\r
53506         PUSH     ECX\r
53507         MOV      EDX, [EBX].fDIBHeader\r
53508         ADD      EDX, szBIH\r
53509         MOV      EAX, ESI\r
53510         CALL     TStream.Read\r
53511         POP      ECX\r
53512         XOR      EAX, ECX\r
53513         JNZ      @@eread\r
53514 @@5:\r
53515         MOV      ECX, [EBX].fDIBSize\r
53516 @@7:\r
53517         PUSH     ECX\r
53518         MOV      EAX, ESI\r
53519         CALL     TStream.GetPosition\r
53520         PUSH     EAX\r
53521         MOV      EAX, ESI\r
53522         CALL     TStream.GetSize\r
53523         POP      EDX\r
53524         SUB      EAX, EDX\r
53525         POP      ECX      // Size = fDIBSize\r
53526         CMP      EAX, ECX // Strm.Size - Strm.Position > Size ?\r
53527         JL       @@8\r
53528         XCHG     ECX, EAX\r
53529 @@8:\r
53530         // ++++++++++++++ 26-Oct-2003 VK see comment in Pascal\r
53531         MOV      EAX, [EBX].fDIBSize\r
53532         CMP      ECX, EAX\r
53533         JGE      @@9\r
53534         SUB      EAX, ECX\r
53535         PUSH     EAX\r
53536         MOV      EAX, ESI\r
53537         PUSH     ECX\r
53538         CALL     TStream.GetPosition\r
53539         POP      ECX\r
53540         POP      EDX\r
53541         CMP      EDX, EAX\r
53542         JG       @@9\r
53544         MOV      EAX, ESI\r
53545         NEG      EDX\r
53546         XOR      ECX, ECX\r
53547         INC      ECX\r
53548         CALL     TStream.Seek\r
53550         MOV      ECX, [EBX].fDIBSize\r
53551 @@9:\r
53552         // ++++++++++++++\r
53554         PUSH     ECX\r
53555         MOV      EDX, [EBX].fDIBBits\r
53556         MOV      EAX, ESI\r
53557         CALL     TStream.Read\r
53558         POP      ECX\r
53559         XOR      EAX, ECX\r
53560         POP      EAX // Strm.Size - Position\r
53561         POP      ECX // fDIBSize\r
53562         //JNZ      @@eread\r
53564         // end of reading bitmap\r
53565 @@eread:\r
53566         MOV      ESP, EBP\r
53567         POP      EBP\r
53568         POP      EDX\r
53569         JZ       @@exit\r
53570         // not success:\r
53571         XCHG     EAX, ESI\r
53572         XOR      ECX, ECX // ECX = spBegin\r
53573         CALL     TStream.Seek\r
53574         XCHG     EAX, EBX\r
53575         CALL     Clear\r
53576 @@exit: POP      ESI\r
53577         POP      EBX\r
53578 end;\r
53579 {$ELSE ASM_VERSION} //Pascal\r
53580 procedure TBitmap.LoadFromStream(Strm: PStream);\r
53581 type\r
53582   TColorsArray = array[ 0..15 ] of TColor;\r
53583   PColorsArray = ^TColorsArray;\r
53584   PColor = ^TColor;\r
53585 var Pos : Integer;\r
53586     BFH : TBitmapFileHeader;\r
53588     function ReadBitmap : Boolean;\r
53589     var Size, Size1: Integer;\r
53590         BCH: TBitmapCoreHeader;\r
53591         RGBSize: DWORD;\r
53592         C: PColor;\r
53593         Off, HdSz, ColorCount: DWORD;\r
53594     begin\r
53595       fHandleType := bmDIB;\r
53596       Result := False;\r
53597       if Strm.Read( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;\r
53598       Off := 0; Size := 0;\r
53599       if BFH.bfType <> $4D42 then\r
53600          Strm.Seek( Pos, spBegin )\r
53601       else\r
53602       begin\r
53603          Off := BFH.bfOffBits - Sizeof( BFH );\r
53604          Size := BFH.bfSize; // don't matter, just <> 0 is good\r
53605          //Size := Min( BFH.bfSize, Strm.Size - Strm.Position );\r
53606       end;\r
53607       RGBSize := 4;\r
53608       HdSz := Sizeof( TBitmapInfoHeader );\r
53609       fDIBHeader := AllocMem( 256*sizeof(TRGBQuad) + HdSz );\r
53610       if Strm.Read( fDIBHeader.bmiHeader.biSize, Sizeof( DWORD ) ) <> Sizeof( DWORD ) then\r
53611          Exit;\r
53612       if fDIBHeader.bmiHeader.biSize = HdSz then\r
53613       begin\r
53614         if Strm.Read( fDIBHeader.bmiHeader.biWidth, HdSz - Sizeof( DWORD ) ) <>\r
53615            HdSz - Sizeof( DWORD ) then\r
53616            Exit;\r
53617       end\r
53618         else\r
53619       if fDIBHeader.bmiHeader.biSize = Sizeof( TBitmapCoreHeader ) then\r
53620       begin\r
53621         RGBSize := 3;\r
53622         HdSz := Sizeof( TBitmapCoreHeader );\r
53623         if Strm.Read( BCH.bcWidth, HdSz - Sizeof( DWORD ) ) <>\r
53624            HdSz - Sizeof( DWORD ) then\r
53625            Exit;\r
53626         fDIBHeader.bmiHeader.biSize := Sizeof( TBitmapInfoHeader );\r
53627         fDIBHeader.bmiHeader.biWidth := BCH.bcWidth;\r
53628         fDIBHeader.bmiHeader.biHeight := BCH.bcHeight;\r
53629         fDIBHeader.bmiHeader.biPlanes := BCH.bcPlanes;\r
53630         fDIBHeader.bmiHeader.biBitCount := BCH.bcBitCount;\r
53631       end\r
53632         else Exit;\r
53633       fNewPixelFormat := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount\r
53634                          * fDIBHeader.bmiHeader.biPlanes );\r
53635       if (fNewPixelFormat = pf15bit) and (fDIBHeader.bmiHeader.biCompression <> BI_RGB) then\r
53636       begin\r
53637         ASSERT( fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS, 'Unsupported bitmap format' );\r
53638         //fNewPixelFormat := pf16bit;\r
53639       end;\r
53640       fWidth := fDIBHeader.bmiHeader.biWidth;\r
53641       ASSERT( fWidth > 0, 'Bitmap width must be > 0' );\r
53642       fHeight := Abs(fDIBHeader.bmiHeader.biHeight);\r
53643       ASSERT( fHeight > 0, 'Bitmap height must be > 0' );\r
53645       fDIBSize := ScanLineSize * fHeight;\r
53646       fDIBBits := AllocMem( fDIBSize );\r
53647       ASSERT( fDIBBits <> nil, 'No memory' );\r
53649       ColorCount := 0;\r
53650       if fDIBHeader.bmiHeader.biBitCount <= 8 then\r
53651         ColorCount := (1 shl fDIBHeader.bmiHeader.biBitCount) * RGBSize\r
53652       else if fNewPixelFormat in [pf15bit,pf16bit] then\r
53653         ColorCount := 12;\r
53655       if Off > 0 then\r
53656       begin\r
53657          Off := Off - HdSz;\r
53658          if (Off <> ColorCount) then\r
53659          if not(fNewPixelFormat in [pf15bit,pf16bit])\r
53660          or (Off = 0) //+++ to fix loading 15- and 16-bit bmps with mask omitted\r
53661          then\r
53662             ColorCount := Off;\r
53663       end;\r
53664       if ColorCount <> 0 then\r
53665       begin\r
53666          if Off >= ColorCount then\r
53667            Off := Off - ColorCount;\r
53668          if RGBSize = 4 then\r
53669          begin\r
53670            if Strm.Read( fDIBheader.bmiColors[ 0 ], ColorCount )\r
53671               <> DWORD( ColorCount ) then Exit;\r
53672          end\r
53673            else\r
53674          begin\r
53675            C := @ fDIBHeader.bmiColors[ 0 ];\r
53676            while ColorCount > 0 do\r
53677            begin\r
53678              if Strm.Read( C^, RGBSize ) <> RGBSize then Exit;\r
53679              Dec( ColorCount, RGBSize );\r
53680              Inc( C );\r
53681            end;\r
53682          end;\r
53683       end;\r
53684       if Off > 0 then\r
53685         Strm.Seek( Off, spCurrent );\r
53687       if Size = 0 then\r
53688          Size := fDIBSize //ScanLineSize * fHeight\r
53689       else\r
53690          Size := Min( {Size - Sizeof( TBitmapFileHeader ) - Sizeof( TBitmapInfoHeader )\r
53691               - ColorCount} fDIBSize, Strm.Size - Strm.Position );\r
53693       Size1 := Min( Size, fDIBSize );\r
53695       // +++++++++++++++++++ 26-Oct-2003 by VK\r
53696       if (Size1 < fDIBSize)\r
53697          and (DWORD( fDIBSize - Size1 ) <= Strm.Position) then\r
53698       begin\r
53699         Strm.Seek( Size1 - fDIBSize, spCurrent );\r
53700         Size1 := fDIBSize;\r
53701       end;\r
53702       // +++++++++++++++++++ to fix some "incorrect" bitmaps while loading\r
53704       if Strm.Read( fDIBBits^, Size1 ) <> DWORD( Size1 ) then Exit;\r
53705       if Size > Size1 then\r
53706         Strm.Seek( Size - Size1, spCurrent );\r
53708       Result := True;\r
53709     end;\r
53710 {var ColorsArray: PColorsArray;\r
53711     DC: HDC;\r
53712     Old: HBitmap;}\r
53713 begin\r
53714   Clear;\r
53715   Pos := Strm.Position;\r
53716   if not ReadBitmap then\r
53717   begin\r
53718      Strm.Seek( Pos, spBegin );\r
53719      Clear;\r
53720   end;\r
53721     {else\r
53722   begin\r
53723     if (fDIBBits <> nil) and (fDIBHeader.bmiHeader.biBitCount >= 4) then\r
53724     begin\r
53725         ColorsArray := @ fDIBHeader.bmiColors[ 0 ];\r
53726         if ColorsArray[ 7 ] = $C0C0C0 then\r
53727         if ColorsArray[ 8 ] = $808080 then\r
53728         if GetHandle <> 0 then\r
53729         begin\r
53730           DC := CreateCompatibleDC( 0 );\r
53731           Old := SelectObject( DC, fHandle );\r
53732           SetDIBColorTable( DC, 0, 16, fDIBHeader.bmiColors[ 0 ] );\r
53733           SelectObject( DC, Old );\r
53734           DeleteDC( DC );\r
53735         end;\r
53736     end;\r
53737   end;}\r
53738 end;\r
53739 {$ENDIF ASM_VERSION}\r
53741 ////////////////// bitmap RLE-decoding and loading - by Vyacheslav A. Gavrik\r
53743 //[procedure DecodeRLE4]\r
53744 procedure DecodeRLE4(Bmp:PBitmap;Data:Pointer); // by Vyacheslav A. Gavrik\r
53745   procedure OddMove(Src,Dst:PByte;Size:Integer);\r
53746   begin\r
53747     if Size=0 then Exit;\r
53748     repeat\r
53749       Dst^:=(Dst^ and $F0)or(Src^ shr 4);\r
53750       Inc(Dst);\r
53751       Dst^:=(Dst^ and $0F)or(Src^ shl 4);\r
53752       Inc(Src);\r
53753       Dec(Size);\r
53754     until Size=0;\r
53755   end;\r
53756   procedure OddFill(Mem:PByte;Size,Value:Integer);\r
53757   begin\r
53758     Value:=(Value shr 4)or(Value shl 4);\r
53759     Mem^:=(Mem^ and $F0)or(Value and $0F);\r
53760     Inc(Mem);\r
53761     if Size>1 then FillChar(Mem^,Size,Value);\r
53762     Mem^:=(Mem^ and $0F)or(Value and $F0);\r
53763   end;\r
53764 var\r
53765   pb: PByte;\r
53766   x,y,z,i: Integer;\r
53767 begin\r
53768   pb:=Data; x:=0; y:=0;\r
53769   if Bmp.fScanLineSize = 0 then\r
53770      Bmp.ScanLineSize;\r
53771   while y<Bmp.Height do\r
53772   begin\r
53773     if pb^=0 then\r
53774     begin\r
53775       Inc(pb);\r
53776       z:=pb^;\r
53777       case pb^ of\r
53778         0: begin\r
53779              Inc(y);\r
53780              x:=0;\r
53781            end;\r
53782         1: Break;\r
53783         2: begin\r
53784              Inc(pb); Inc(x,pb^);\r
53785              Inc(pb); Inc(y,pb^);\r
53786            end;\r
53787         else\r
53788         begin\r
53789           Inc(pb);\r
53790           i:=(z+1)shr 1;\r
53791           if(z and 2)=2 then Inc(i);\r
53792           if((x and 1)=1)and(x+i<Bmp.Width)then\r
53793             OddMove(pb,@PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],i)\r
53794           else\r
53795             Move(pb^,PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],i);\r
53796           Inc(pb,i-1);\r
53797           Inc(x,z);\r
53798         end;\r
53799       end;\r
53800     end else\r
53801     begin\r
53802       z:=pb^;\r
53803       Inc(pb);\r
53804       if((x and 1)=1)and(x+z<Bmp.Width)then\r
53805         OddFill(@PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],z shr 1,pb^)\r
53806       else\r
53807         FillChar(PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],z shr 1,pb^);\r
53808       Inc(x,z);\r
53809     end;\r
53810     Inc(pb);\r
53811   end;\r
53812 end;\r
53814 //[procedure DecodeRLE8]\r
53815 procedure DecodeRLE8(Bmp:PBitmap;Data:Pointer); // by Vyacheslav A. Gavrik\r
53816 var\r
53817   pb: PByte;\r
53818   x,y,z,i: Integer;\r
53819 begin\r
53820   pb:=Data; y:=0; x:=0;\r
53821   if Bmp.fScanLineSize = 0 then\r
53822      Bmp.ScanLineSize;\r
53824   while y<Bmp.Height do\r
53825   begin\r
53826     if pb^=0 then\r
53827     begin\r
53828       Inc(pb);\r
53829       case pb^ of\r
53830         0: begin\r
53831              Inc(y);\r
53832              x:=0;\r
53833            end;\r
53834         1: Break;\r
53835         2: begin\r
53836              Inc(pb); Inc(x,pb^);\r
53837              Inc(pb); Inc(y,pb^);\r
53838            end;\r
53839         else\r
53840         begin\r
53841           i:=pb^;\r
53842           z:=(i+1)and(not 1);\r
53843           Inc(pb);\r
53844           Move(pb^,PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x],z);\r
53845           Inc(pb,z-1);\r
53846           Inc(x,i);\r
53847         end;\r
53848       end;\r
53849     end else\r
53850     begin\r
53851       i:=pb^; Inc(pb);\r
53852       FillChar(PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x],i,pb^);\r
53853       Inc(x,i);\r
53854     end;\r
53855     Inc(pb);\r
53856   end;\r
53857 end;\r
53859 //[function TBitmap.LoadFromFileEx]\r
53860 function TBitmap.LoadFromFileEx(const Filename: String): Boolean; // by Vyacheslav A. Gavrik\r
53861 var Strm: PStream;\r
53862 begin\r
53863   Strm := NewReadFileStream( Filename );\r
53864   Result := LoadFromStreamEx(Strm);\r
53865   Strm.Free;\r
53866 end;\r
53868 //[function TBitmap.LoadFromStreamEx]\r
53869 function TBitmap.LoadFromStreamEx(Strm: PStream): Boolean; // by Vyacheslav A. Gavrik\r
53870 var Pos : Integer;\r
53872     function ReadBitmap : Boolean;\r
53873     var Off, Size, ColorCount: Integer;\r
53874         BFH : TBitmapFileHeader;\r
53875         BFHValid: Boolean;\r
53876         Buffer: Pointer;\r
53877     begin\r
53878       fHandleType := bmDIB;\r
53879       Result := False;\r
53880       BFHValid := FALSE;\r
53881       if Strm.Read( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;\r
53882       Off := 0; Size := 0;\r
53883       if BFH.bfType <> $4D42 then\r
53884          Strm.Seek( Pos, spBegin )\r
53885       else\r
53886       begin\r
53887          BFHValid := TRUE;\r
53888          Off := BFH.bfOffBits;\r
53889          Size := Strm.GetSize;\r
53890       end;\r
53891       GetMem( fDIBHeader, 256*sizeof(TRGBQuad) + sizeof(TBitmapInfoHeader) );\r
53892       if Strm.Read( fDIBHeader^, Sizeof(TBitmapInfoHeader) ) <> Sizeof(TBitmapInfoHeader) then\r
53893          Exit;\r
53894       //if fDIBHeader.bmiHeader.biCompression = BI_RGB then\r
53895       {if fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS then\r
53896                                             //BI_RGB here????\r
53897         Strm.Read( fDIBHeader.bmiColors[ 0 ], 3 * Sizeof( DWORD ) );}\r
53899       fNewPixelFormat := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount\r
53900                          * fDIBHeader.bmiHeader.biPlanes );\r
53902       fWidth := fDIBHeader.bmiHeader.biWidth;\r
53903       ASSERT( fWidth > 0, 'Bitmap width must be > 0' );\r
53904       fHeight := Abs(fDIBHeader.bmiHeader.biHeight);\r
53905       ASSERT( fHeight > 0, 'Bitmap height must be > 0' );\r
53907       fDIBSize := ScanLineSize * fHeight;\r
53908       GetMem( fDIBBits, fDIBSize );\r
53909       ASSERT( fDIBBits <> nil, 'No memory' );\r
53910       ASSERT( (fDIBHeader.bmiHeader.biCompression and\r
53911               (BI_RLE8 or BI_RLE4 or BI_RLE8 or BI_BITFIELDS) <> 0) or\r
53912               (fDIBHeader.bmiHeader.biCompression = BI_RGB),\r
53913               'Unknown compression algorithm');\r
53915       ColorCount := 0;\r
53916       if fDIBHeader.bmiHeader.biBitCount <= 8 then\r
53917         ColorCount := (1 shl fDIBHeader.bmiHeader.biBitCount) * Sizeof( TRGBQuad )\r
53918       else if fNewPixelFormat in [ pf16bit ] then\r
53919         ColorCount := 12;\r
53921       if Off > 0 then\r
53922       begin\r
53923          Off := Off - SizeOf( TBitmapFileHeader ) - Sizeof( TBitmapInfoHeader );\r
53924          if Off <> ColorCount then\r
53925             ColorCount := Off;\r
53926       end;\r
53927       if fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS then\r
53928       begin\r
53929         PDWORD( DWORD( @ fDIBHeader.bmiColors[ 0 ] ) + 8 )^ := ( $00001F );\r
53930         PDWORD( DWORD( @ fDIBHeader.bmiColors[ 0 ] ) + 4 )^ := ( $0007E0 );\r
53931         TColor( fDIBHeader.bmiColors[ 0 ] ) := ( $00F800 );\r
53932       end;\r
53934       if ColorCount <> 0 then\r
53935          if Strm.Read( fDIBheader.bmiColors[ 0 ], ColorCount )\r
53936             <> DWORD( ColorCount ) then Exit;\r
53938       if not BFHValid then\r
53939         Size := fDIBSize\r
53940       else\r
53941       if(fDIBHeader.bmiHeader.biCompression = BI_RLE8)\r
53942          or (fDIBHeader.bmiHeader.biCompression=BI_RLE4) then\r
53943             Size := BFH.bfSize - BFH.bfOffBits\r
53944          else\r
53945          begin\r
53946            if Integer( Strm.Size - BFH.bfOffBits) - Pos > Integer(Size) then\r
53947              Size := fDIBSize\r
53948            else\r
53949              Size := Strm.Size - BFH.bfOffBits - DWORD( Pos );\r
53950          end;\r
53952       if (fDIBHeader.bmiHeader.biCompression = BI_RGB) or\r
53953          (fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS) then\r
53954       begin\r
53955         if Strm.Read( fDIBBits^, Size ) <> DWORD( Size ) then\r
53956           //Exit;\r
53957       end\r
53958         else\r
53959       begin\r
53960         GetMem(Buffer,Size);\r
53961         if Strm.Read(Buffer^,Size) <> DWORD( Size ) then Exit;\r
53963         if fDIBHeader.bmiHeader.biCompression=BI_RLE8 then\r
53964            DecodeRLE8(@Self,Buffer)\r
53965         else\r
53966            DecodeRLE4(@Self,Buffer);\r
53968         fDIBHeader.bmiHeader.biCompression := BI_RGB;\r
53969         FreeMem(Buffer);\r
53970       end;\r
53972       Result := True;\r
53973     end;\r
53974 begin\r
53975   Clear;\r
53976   Pos := Strm.Position;\r
53977   result := ReadBitmap;\r
53978   if not result then\r
53979   begin\r
53980      Strm.Seek( Pos, spBegin );\r
53981      Clear;\r
53982   end;\r
53983 end;\r
53985 ///////////////////////////\r
53987 {$IFDEF ASM_VERSION}\r
53988 //[function TBitmap.ReleaseHandle]\r
53989 function TBitmap.ReleaseHandle: HBitmap;\r
53990 asm\r
53991         PUSH     EBX\r
53992         MOV      EBX, EAX\r
53993         XOR      EDX, EDX\r
53994         CALL     SetHandleType\r
53995         MOV      EAX, EBX\r
53996         CALL     GetHandle\r
53997         TEST     EAX, EAX\r
53998         JZ       @@exit\r
54000         CMP      [EBX].fDIBAutoFree, 0\r
54001         JZ       @@1\r
54002         MOV      EAX, [EBX].fDIBSize\r
54003         PUSH     EAX\r
54004         CALL     System.@GetMem\r
54005         MOV      EDX, EAX\r
54006         XCHG     EAX, [EBX].fDIBBits\r
54007         POP      ECX\r
54008         CALL     System.Move\r
54009 @@1:\r
54010         XOR      EAX, EAX\r
54011         MOV      [EBX].fDIBAutoFree, AL\r
54012         XCHG     EAX, [EBX].fHandle\r
54014 @@exit: POP      EBX\r
54015 end;\r
54016 {$ELSE ASM_VERSION} //Pascal\r
54017 function TBitmap.ReleaseHandle: HBitmap;\r
54018 var OldBits: Pointer;\r
54019 begin\r
54020   HandleType := bmDIB;\r
54021   Result := GetHandle;\r
54022   if Result = 0 then Exit; // only when bitmap is empty\r
54023   if fDIBAutoFree then\r
54024   begin\r
54025     OldBits := fDIBBits;\r
54026     GetMem( fDIBBits, fDIBSize );\r
54027     Move( OldBits^, fDIBBits^, fDIBSize );\r
54028     fDIBAutoFree := FALSE;\r
54029   end;\r
54030   fHandle := 0;\r
54031 end;\r
54032 {$ENDIF ASM_VERSION}\r
54034 {$IFDEF ASM_VERSION}\r
54035 //[procedure TBitmap.SaveToFile]\r
54036 procedure TBitmap.SaveToFile(const Filename: String);\r
54037 asm\r
54038         PUSH     EAX\r
54039         PUSH     EDX\r
54040         CALL     GetEmpty\r
54041         POP      EAX\r
54042         JZ       @@exit\r
54043         CALL     NewWriteFileStream\r
54044         XCHG     EDX, EAX\r
54045         POP      EAX\r
54046         PUSH     EDX\r
54047         CALL     SaveToStream\r
54048         POP      EAX\r
54049         CALL     TObj.Free\r
54050         PUSH     EAX\r
54051 @@exit: POP      EAX\r
54052 end;\r
54053 {$ELSE ASM_VERSION} //Pascal\r
54054 procedure TBitmap.SaveToFile(const Filename: String);\r
54055 var Strm: PStream;\r
54056 begin\r
54057   if Empty then Exit;\r
54058   Strm := NewWritefileStream( Filename );\r
54059   SaveToStream( Strm );\r
54060   Strm.Free;\r
54061 end;\r
54062 {$ENDIF ASM_VERSION}\r
54064 {$IFDEF ASM_VERSION}\r
54065 //[procedure TBitmap.SaveToStream]\r
54066 procedure TBitmap.SaveToStream(Strm: PStream);\r
54067 type  tBFH = TBitmapFileHeader;\r
54068       tBIH = TBitmapInfoHeader;\r
54069 const szBIH = Sizeof( tBIH );\r
54070       szBFH = Sizeof( tBFH );\r
54071 asm\r
54072         PUSH     EBX\r
54073         PUSH     ESI\r
54074         MOV      EBX, EAX\r
54075         MOV      ESI, EDX\r
54076         CALL     GetEmpty\r
54077         JZ       @@exit\r
54078         MOV      EAX, ESI\r
54079         CALL     TStream.GetPosition\r
54080         PUSH     EAX\r
54082         MOV      EAX, EBX\r
54083         XOR      EDX, EDX // EDX = bmDIB\r
54084         CALL     SetHandleType\r
54085         XOR      EAX, EAX\r
54086         MOV      EDX, [EBX].fDIBHeader\r
54087         MOVZX    ECX, [EDX].TBitmapInfoHeader.biBitCount\r
54088         CMP      CL, 8\r
54089         JG       @@1\r
54090         MOV      AL, 4\r
54091         SHL      EAX, CL\r
54092 @@1:\r
54093           PUSH     EAX                        // ColorsSize\r
54094         LEA      ECX, [EAX + szBFH + szBIH]\r
54095         CMP      [EDX].TBitmapInfoHeader.biCompression, 0\r
54096         JZ       @@10\r
54097         ADD      ECX, 74\r
54098 @@10:\r
54099         PUSH     ECX                        // BFH.bfOffBits\r
54100         PUSH     0\r
54101         ADD      ECX, [EBX].fDIBSize\r
54102         PUSH     ECX\r
54103         MOV      CX, $4D42\r
54104         PUSH     CX\r
54105         XOR      ECX, ECX\r
54106         MOV      EDX, ESP\r
54107         MOV      CL, szBFH\r
54108           PUSH     ECX\r
54109         MOV      EAX, ESI\r
54110         CALL     TStream.Write\r
54111           POP      ECX\r
54112         ADD      ESP, szBFH\r
54113         XOR      EAX, ECX\r
54114           POP      ECX  // ColorsSize\r
54115         JNZ      @@ewrite\r
54117         MOV      EDX, [EBX].fDIBHeader\r
54118         CMP      [EDX].TBitmapInfoHeader.biCompression, 0\r
54119         JZ       @@11\r
54120         ADD      ECX, 74\r
54121 @@11:\r
54123         ADD      ECX, szBIH\r
54124         PUSH     ECX\r
54125         MOV      EAX, ESI\r
54126         CALL     TStream.Write\r
54127         POP      ECX\r
54128         XOR      EAX, ECX\r
54129         JNZ      @@ewrite\r
54131         MOV      ECX, [EBX].fDIBSize\r
54132         MOV      EDX, [EBX].fDIBBits\r
54133         MOV      EAX, ESI\r
54134         PUSH     ECX\r
54135         CALL     TStream.Write\r
54136         POP      ECX\r
54137         XOR      EAX, ECX\r
54139 @@ewrite:\r
54140         POP      EDX\r
54141         JZ       @@exit\r
54142         XCHG     EAX, ESI\r
54143         XOR      ECX, ECX\r
54144         CALL     TStream.Seek\r
54145 @@exit:\r
54146         POP      ESI\r
54147         POP      EBX\r
54148 end;\r
54149 {$ELSE ASM_VERSION} //Pascal\r
54150 procedure TBitmap.SaveToStream(Strm: PStream);\r
54151 var BFH : TBitmapFileHeader;\r
54152     Pos : Integer;\r
54153    function WriteBitmap : Boolean;\r
54154    var ColorsSize, BitsSize, Size : Integer;\r
54155    begin\r
54156       Result := False;\r
54157       if Empty then Exit;\r
54158       HandleType := bmDIB; // convert to DIB if DDB\r
54159       FillChar( BFH, Sizeof( BFH ), 0 );\r
54160       ColorsSize := 0;\r
54161       with fDIBHeader.bmiHeader do\r
54162            if biBitCount <= 8 then\r
54163               ColorsSize := (1 shl biBitCount) * Sizeof( TRGBQuad )\r
54164            {else\r
54165            if biCompression <> 0 then\r
54166               ColorsSize := 12};\r
54167       BFH.bfOffBits := Sizeof( BFH ) + Sizeof( TBitmapInfoHeader ) + ColorsSize;\r
54168       BitsSize := fDIBSize; //ScanLineSize * fHeight;\r
54169       BFH.bfSize := BFH.bfOffBits + DWord( BitsSize );\r
54170       BFH.bfType := $4D42; // 'BM';\r
54171       if fDIBHeader.bmiHeader.biCompression <> 0 then\r
54172       begin\r
54173          ColorsSize := 12 + 16*sizeof(TRGBQuad);\r
54174          Inc( BFH.bfOffBits, ColorsSize );\r
54175       end;\r
54176       if Strm.Write( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;\r
54177       Size := Sizeof( TBitmapInfoHeader ) + ColorsSize;\r
54178       if Strm.Write( fDIBHeader^, Size ) <> DWORD(Size) then Exit;\r
54179       if Strm.Write( fDIBBits^, BitsSize ) <> DWord( BitsSize ) then Exit;\r
54180       Result := True;\r
54181    end;\r
54182 begin\r
54183   Pos := Strm.Position;\r
54184   if not WriteBitmap then\r
54185      Strm.Seek( Pos, spBegin );\r
54186 end;\r
54187 {$ENDIF ASM_VERSION}\r
54189 {$IFDEF ASM_VERSION}\r
54190 //[procedure TBitmap.SetHandle]\r
54191 procedure TBitmap.SetHandle(const Value: HBitmap);\r
54192 const szB = sizeof( tagBitmap );\r
54193 asm\r
54194         PUSH     EAX\r
54195         PUSH     EDX\r
54196         CALL     Clear\r
54197         POP      ECX\r
54198         JECXZ    @@exit\r
54199         PUSH     ECX\r
54200         ADD      ESP, -szB\r
54201         PUSH     ESP\r
54202         PUSH     szB\r
54203         PUSH     ECX\r
54204         CALL     GetObject\r
54205         POP      EDX\r
54206         POP      EDX\r
54207         POP      ECX\r
54208         ADD      ESP, 12\r
54209         TEST     EAX, EAX\r
54210         POP      EAX\r
54211         JZ       @@exit\r
54212         XCHG     EAX, [ESP]\r
54213         MOV      [EAX].fWidth, EDX\r
54214         MOV      [EAX].fHeight, ECX\r
54215         POP      EDX\r
54216         MOV      [EAX].fHandle, EDX\r
54217         MOV      [EAX].fHandleType, 1\r
54218         PUSH     EAX\r
54219 @@exit: POP      EAX\r
54220 end;\r
54221 {$ELSE ASM_VERSION} //Pascal\r
54222 procedure TBitmap.SetHandle(const Value: HBitmap);\r
54223 var B: tagBitmap;\r
54224 begin\r
54225   Clear;\r
54226   if Value = 0 then Exit;\r
54227   if GetObject( Value, Sizeof( B ), @B ) = 0 then Exit;\r
54228   fHandle := Value;\r
54229   fWidth := B.bmWidth;\r
54230   fHeight := B.bmHeight;\r
54231   fHandleType := bmDDB;\r
54232 end;\r
54233 {$ENDIF ASM_VERSION}\r
54235 //[procedure TBitmap.SetWidth]\r
54236 procedure TBitmap.SetWidth(const Value: Integer);\r
54237 begin\r
54238   if fWidth = Value then Exit;\r
54239   fWidth := Value;\r
54240   FormatChanged;\r
54241 end;\r
54243 {$IFDEF ASM_VERSION}\r
54244 //[procedure TBitmap.SetHeight]\r
54245 procedure TBitmap.SetHeight(const Value: Integer);\r
54246 asm\r
54247         CMP      EDX, [EAX].fHeight\r
54248         JE       @@exit\r
54249         PUSHAD\r
54250         XOR      EDX, EDX\r
54251         INC      EDX\r
54252         CALL     SetHandleType\r
54253         POPAD\r
54254         MOV      [EAX].fHeight, EDX\r
54255         CALL     FormatChanged\r
54256 @@exit:\r
54257 end;\r
54258 {$ELSE ASM_VERSION} //Pascal\r
54259 procedure TBitmap.SetHeight(const Value: Integer);\r
54260 begin\r
54261   if fHeight = Value then Exit;\r
54263     HandleType := bmDDB;\r
54264     // Not too good, but provides correct changing of height\r
54265     // preserving previous image\r
54267   fHeight := Value;\r
54268   FormatChanged;\r
54269 end;\r
54270 {$ENDIF ASM_VERSION}\r
54272 {$IFDEF ASM_VERSION}\r
54273 //[procedure TBitmap.SetPixelFormat]\r
54274 procedure TBitmap.SetPixelFormat(Value: TPixelFormat);\r
54275 asm\r
54276         PUSH     EBX\r
54277         MOV      EBX, EAX\r
54278         //////////////////////\r
54279         CALL     GetEmpty   //   if Empty then Exit;\r
54280         JZ       @@exit     //\r
54281         MOV      EAX, EBX   //\r
54282         //////////////////////\r
54283         PUSH     EDX\r
54284         CALL     GetPixelFormat\r
54285         POP      EDX\r
54286         CMP      EAX, EDX\r
54287         JE       @@exit\r
54288         TEST     EDX, EDX\r
54289         MOV      EAX, EBX\r
54290         JNE      @@2\r
54291         // Value = pfDevice (=0)\r
54292         POP      EBX\r
54293         INC      EDX // EDX = bmDDB\r
54294         JMP      SetHandleType\r
54295 @@2:\r
54296         MOV      [EBX].fNewPixelFormat, DL\r
54297         CMP      DL, pf16bit\r
54298         JNZ      @@3\r
54299         DEC      EDX\r
54300 @@3:    PUSH     EDX\r
54301         XOR      EDX, EDX\r
54302         CALL     SetHandleType\r
54303         MOV      EAX, [EBX].fDIBHeader\r
54304         MOVZX    EAX, [EAX].TBitmapInfoHeader.biBitCount\r
54305         CALL     Bits2PixelFormat\r
54306         POP      EDX\r
54307         CMP      AL, DL\r
54308         XCHG     EAX, EBX\r
54309 @@exit:\r
54310         POP      EBX\r
54311         JNE      FormatChanged\r
54312 end;\r
54313 {$ELSE ASM_VERSION} //Pascal\r
54314 procedure TBitmap.SetPixelFormat(Value: TPixelFormat);\r
54315 begin\r
54316   if PixelFormat = Value then Exit;\r
54317   if Empty then Exit;\r
54318   if Value = pfDevice then\r
54319     HandleType := bmDDB\r
54320   else\r
54321   begin\r
54322     fNewPixelFormat := Value;\r
54323     //if Value = pf16bit then Value := pf15bit;\r
54324     HandleType := bmDIB;\r
54325     if Value <> Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount ) then\r
54326       FormatChanged;\r
54327   end;\r
54328 end;\r
54329 {$ENDIF ASM_VERSION}\r
54331 //[FUNCTION CalcScanLineSize]\r
54332 {$IFDEF ASM_VERSION}\r
54333 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;\r
54334 asm\r
54335         MOVZX    EDX, [EAX].TBitmapInfoHeader.biBitCount\r
54336         MOV      EAX, [EAX].TBitmapInfoHeader.biWidth\r
54337         MUL      EDX\r
54338         ADD      EAX, 31\r
54339         SHR      EAX, 3\r
54340         AND      EAX, -4\r
54341 end;\r
54342 {$ELSE ASM_VERSION} //Pascal\r
54343 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;\r
54344 begin\r
54345   //Result := ((Header.biBitCount * Header.biWidth + 31)\r
54346   //          shr 5) * 4;\r
54347   Result := ((Header.biBitCount * Header.biWidth + 31) shr 3) and $FFFFFFFC;\r
54348 end;\r
54349 {$ENDIF ASM_VERSION}\r
54350 //[END CalcScanLineSize]\r
54352 //[PROCEDURE FillBmpWithBkColor]\r
54353 {$IFDEF ASM_VERSION}\r
54354 procedure FillBmpWithBkColor( Bmp: PBitmap; DC2: HDC; oldWidth, oldHeight: Integer );\r
54355 asm\r
54356         PUSH     EBX\r
54357         PUSH     ESI\r
54358         XCHG     EAX, EBX\r
54359         PUSH     EDX // [EBP-12] = DC2\r
54360         PUSH     ECX // [EBP-16] = oldWidth\r
54361         MOV      EAX, [EBX].TBitmap.fBkColor\r
54362         CALL     Color2RGB\r
54363         TEST     EAX, EAX\r
54364         JZ       @@exit\r
54365         XCHG     ESI, EAX // ESI = Color2RGB( Bmp.fBkColor )\r
54366         MOV      EAX, EBX\r
54367         CALL     TBitmap.GetHandle\r
54368         TEST     EAX, EAX\r
54369         JZ       @@exit\r
54370         PUSH     EAX //fHandle\r
54371         PUSH     dword ptr [EBP-12] //DC2\r
54372         CALL     SelectObject\r
54373         PUSH     EAX // [EBP-20] = oldBmp\r
54374         PUSH     ESI\r
54375         CALL     CreateSolidBrush\r
54376         XCHG     ESI, EAX // ESI = Br\r
54377         PUSH     [EBX].TBitmap.fHeight\r
54378         PUSH     [EBX].TBitmap.fWidth\r
54379         MOV      EAX, [oldHeight]\r
54380         MOV      EDX, [EBP-16] //oldWidth\r
54381         CMP      EAX, [EBX].TBitmap.fHeight\r
54382         JL       @@fill\r
54383         CMP      EDX, [EBX].TBitmap.fWidth\r
54384         JGE      @@nofill\r
54385 @@fill: CMP      EAX, [EBX].TBitmap.fHeight\r
54386         JNE      @@1\r
54387         XOR      EAX, EAX\r
54388 @@1:\r
54389         CMP      EDX, [EBX].TBitmap.fWidth\r
54390         JNZ      @@2\r
54391         CDQ\r
54392 @@2:    PUSH     EAX\r
54393         PUSH     EDX\r
54395         MOV      EDX, ESP\r
54396         PUSH     ESI\r
54397         PUSH     EDX\r
54398         PUSH     dword ptr [EBP-12] //DC2\r
54399         CALL     Windows.FillRect\r
54400         POP      ECX\r
54401         POP      ECX\r
54402 @@nofill:\r
54403         POP      ECX\r
54404         POP      ECX\r
54405         PUSH     ESI //Br\r
54406         CALL     DeleteObject\r
54407         PUSH     dword ptr [EBP-12] //DC2\r
54408         CALL     SelectObject\r
54409 @@exit:\r
54410         POP      ECX\r
54411         POP      EDX\r
54412         POP      ESI\r
54413         POP      EBX\r
54414 end;\r
54415 {$ELSE ASM_VERSION} //Pascal\r
54416 procedure FillBmpWithBkColor( Bmp: PBitmap; DC2: HDC; oldWidth, oldHeight: Integer );\r
54417 var oldBmp: HBitmap;\r
54418     R: TRect;\r
54419     Br: HBrush;\r
54420 begin\r
54421   with Bmp{-}^{+} do\r
54422   if Color2RGB( fBkColor ) <> 0 then\r
54423   if (oldWidth < fWidth) or (oldHeight < fHeight) then\r
54424     if GetHandle <> 0 then\r
54425     begin\r
54426       oldBmp := SelectObject( DC2, fHandle );\r
54427       ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );\r
54428       Br := CreateSolidBrush( Color2RGB( fBkColor ) );\r
54429       R := MakeRect( oldWidth, oldHeight, fWidth, fHeight );\r
54430       if oldWidth = fWidth then\r
54431          R.Left := 0;\r
54432       if oldHeight = fHeight then\r
54433          R.Top := 0;\r
54434       Windows.FillRect( DC2, R, Br );\r
54435       DeleteObject( Br );\r
54436       SelectObject( DC2, oldBmp );\r
54437     end;\r
54438 end;\r
54439 {$ENDIF ASM_VERSION}\r
54440 //[END FillBmpWithBkColor]\r
54442 const BitCounts: array[ TPixelFormat ] of Byte = ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );\r
54443 {$IFDEF ASM_VERSION}\r
54444 //[procedure TBitmap.FormatChanged]\r
54445 procedure TBitmap.FormatChanged;\r
54446 type  tBIH = TBitmapInfoHeader;\r
54447       tBmp = tagBitmap;\r
54448 const szBIH = Sizeof( tBIH );\r
54449       szBmp = Sizeof( tBmp );\r
54450 asm\r
54451         PUSH     EAX\r
54452         CALL     GetEmpty\r
54453         POP      EAX\r
54454         JZ       @@exit\r
54455         PUSHAD\r
54456         MOV      EBX, EAX\r
54457         CALL     [EBX].fDetachCanvas\r
54458         XOR      EAX, EAX\r
54459         MOV      [EBX].fScanLineSize, EAX\r
54460         MOV      [EBX].fGetDIBPixels, EAX\r
54461         MOV      [EBX].fSetDIBPixels, EAX\r
54462         MOV      ESI, [EBX].fWidth    // ESI := oldWidth\r
54463         MOV      EDI, [EBX].fHeight   // EDI := oldHeight\r
54464         MOV      ECX, [EBX].fDIBBits\r
54465         JECXZ    @@noDIBBits\r
54466         MOV      EAX, [EBX].fDIBHeader\r
54467         MOV      ESI, [EAX].TBitmapInfo.bmiHeader.biWidth\r
54468         MOV      EDI, [EAX].TBitmapInfo.bmiHeader.biHeight\r
54469         TEST     EDI, EDI\r
54470         JGE      @@1\r
54471         NEG      EDI\r
54472 @@1:    JMP      @@createDC2\r
54473 @@noDIBBits:\r
54474         MOV      ECX, [EBX].fHandle\r
54475         JECXZ    @@createDC2\r
54476         ADD      ESP, -24 // -szBmp\r
54477         PUSH     ESP\r
54478         PUSH     24 //szBmp\r
54479         PUSH     ECX\r
54480         CALL     GetObject\r
54481         XCHG     ECX, EAX\r
54482         JECXZ    @@2\r
54483         MOV      ESI, [ESP].tBmp.bmWidth\r
54484         MOV      EDI, [ESP].tBmp.bmHeight\r
54485 @@2:    ADD      ESP, 24 //szBmp\r
54486 @@createDC2:\r
54487         PUSH     0\r
54488         CALL     CreateCompatibleDC\r
54489         PUSH     EAX                         // > DC2\r
54490         CMP      [EBX].fHandleType, bmDDB\r
54491         JNE      @@DIB_handle_type\r
54492         PUSH     0\r
54493         CALL     GetDC\r
54494         PUSH     EAX                         // > DC0\r
54495         PUSH     [EBX].fHeight\r
54496         PUSH     [EBX].fWidth\r
54497         PUSH     EAX\r
54498         CALL     CreateCompatibleBitmap\r
54499         XCHG     EBP, EAX        // EBP := NewHandle\r
54500         PUSH     0\r
54501         CALL     ReleaseDC                   // <\r
54502         POP      EDX\r
54503         PUSH     EDX             // EDX := DC2\r
54504         PUSH     EBP\r
54505         PUSH     EDX\r
54506         CALL     SelectObject\r
54507         PUSH     EAX                         // > OldBmp\r
54508         PUSH     [EBX].fHeight   // prepare Rect(0,0,fWidth,fHeight)\r
54509         PUSH     [EBX].fWidth\r
54510         PUSH     0\r
54511         PUSH     0\r
54512         MOV      EAX, [EBX].fBkColor\r
54513         CALL     Color2RGB\r
54514         PUSH     EAX\r
54515         CALL     CreateSolidBrush\r
54516         MOV      EDX, ESP\r
54517         PUSH     EAX                         // > Br\r
54518         PUSH     EAX\r
54519         PUSH     EDX\r
54520         PUSH     dword ptr [ESP+32] // (DC2)\r
54521         CALL     Windows.FillRect\r
54522         CALL     DeleteObject                // <\r
54523         ADD      ESP, 16            // remove Rect\r
54524         MOV      ECX, [EBX].fDIBBits\r
54525         JECXZ    @@draw\r
54526         PUSH     dword ptr [ESP+4] // (DC2)\r
54527         CALL     SelectObject                // < (OldBmp)\r
54528         PUSH     DIB_RGB_COLORS    // : DIB_RGB_COLORS\r
54529         PUSH     [EBX].fDIBHeader  // : fDIBHeader\r
54530         PUSH     [EBX].fDIBBits    // : fDIBBits\r
54531         PUSH     [EBX].fHeight     // : fHeight\r
54532         PUSH     0                 // : 0\r
54533         PUSH     EBP               // : NewHandle\r
54534         PUSH     dword ptr [ESP+24] // (DC2)\r
54535         CALL     SetDIBits\r
54536         JMP      @@clearData\r
54537 @@draw:\r
54538         MOV      EDX, [ESP+4]\r
54539         PUSH     EDX           // prepare DC2 for SelectObject\r
54540         MOV      EAX, EBX\r
54541         XOR      ECX, ECX\r
54542         PUSH     ECX\r
54543         CALL     Draw\r
54544         CALL     SelectObject\r
54545 @@clearData:\r
54546         MOV      EAX, EBX\r
54547         CALL     ClearData\r
54548         MOV      [EBX].fHandle, EBP\r
54550         JMP      @@fillBkColor\r
54552 @@DIB_handle_type:    // [ESP] = DC2\r
54553         MOVZX    EAX, [EBX].fNewPixelFormat\r
54554 @@getBitsPixel:\r
54555         XCHG     ECX, EAX\r
54556         MOV      CL, [ECX] + offset BitCounts\r
54557         MOVZX    EAX, [DefaultPixelFormat]\r
54558         JECXZ    @@getBitsPixel\r
54559         XOR      EBP, EBP            // NewHandle := 0\r
54560         MOV      EAX, [EBX].fWidth   // EAX := fWidth\r
54561         MOV      EDX, [EBX].fHeight  // EDX := fHeight\r
54562         CALL     PrepareBitmapHeader\r
54563         PUSH     EAX                            // > NewHeader\r
54564         CMP      [EBX].fNewPixelFormat, pf16bit\r
54565         JNE      @@newHeaderReady\r
54566         CALL     PreparePF16bit\r
54567 @@newHeaderReady:\r
54568         POP      EAX\r
54569         PUSH     EAX\r
54570         CALL     CalcScanLineSize\r
54571         MOV      EDX, [EBX].fHeight\r
54572         MUL      EDX\r
54573         PUSH     EAX                           // > sizeBits\r
54575         {$IFDEF _FP}\r
54576         CALL     GetMem\r
54577         {$ELSE}\r
54578         CALL     System.@GetMem\r
54579         {$ENDIF}\r
54580         PUSH     EAX                           // > NewBits\r
54581         PUSH     DIB_RGB_COLORS\r
54582         PUSH     dword ptr [ESP+12] // (NewHeader)\r
54583         PUSH     EAX\r
54584         MOV      EAX, [EBX].fHeight\r
54585         CMP      EAX, EDI\r
54586         {$IFDEF USE_CMOV}\r
54587         CMOVG    EAX, EDI\r
54588         {$ELSE}\r
54589         JLE      @@3\r
54590         MOV      EAX, EDI\r
54591 @@3:    {$ENDIF}\r
54593         PUSH     EAX\r
54594         PUSH     0\r
54595         MOV      EAX, EBX\r
54596         CALL     GetHandle\r
54597         PUSH     EAX\r
54598         PUSH     dword ptr [ESP+36] // (DC2)\r
54599         CALL     GetDIBits\r
54601         MOV      EDX, [EBX].fHeight\r
54602         CMP      EDX, EDI\r
54603         {$IFDEF USE_CMOV}\r
54604         CMOVG    EDX, EDI\r
54605         {$ELSE}\r
54606         JLE      @@30\r
54607         MOV      EDX, EDI\r
54608 @@30:   {$ENDIF}\r
54610         CMP      EAX, EDX\r
54611         JE       @@2clearData\r
54613         POP      EAX\r
54614         {$IFDEF _FP}\r
54615         CALL     FreeMem\r
54616         {$ELSE}\r
54617         CALL     System.@FreeMem\r
54618         {$ENDIF}\r
54620         XOR      EAX, EAX\r
54621         PUSH     EAX\r
54623         MOV      EDX, ESP        // EDX = @NewBits\r
54624         MOV      ECX, [ESP+8]    // ECX = @NewHeader\r
54625         PUSH     EAX             // -> 0\r
54626         PUSH     EAX             // -> 0\r
54627         PUSH     EDX             // -> @NewBits\r
54628         PUSH     DIB_RGB_COLORS  // -> DIB_RGB_COLORS\r
54629         PUSH     ECX             // -> @NewHeader\r
54630         PUSH     dword ptr [ESP+32] // -> DC2\r
54631         CALL     CreateDIBSection\r
54633         XOR      ESI, -1 // use OldWidth to store NewDIBAutoFree flag\r
54635         XCHG     EBP, EAX        // EBP := NewHandle\r
54636         PUSH     EBP\r
54637         PUSH     dword ptr [ESP+16] // -> DC2\r
54638         CALL     SelectObject\r
54639         PUSH     EAX           // save oldBmp\r
54640         MOV      EDX, [ESP+16] // DC2 -> EDX (DC)\r
54641         XOR      ECX, ECX      // 0   -> ECX (X)\r
54642         PUSH     ECX           // 0   -> stack (Y)\r
54643         MOV      EAX, EBX\r
54644         CALL     TBitmap.Draw\r
54645         PUSH     dword ptr [ESP+16] // -> DC2\r
54646         CALL     SelectObject\r
54648 @@2clearData:\r
54649         MOV      EAX, EBX\r
54650         CALL     ClearData\r
54652         POP      [EBX].fDIBBits\r
54653         POP      [EBX].fDIBSize\r
54654         POP      [EBX].fDIBHeader\r
54655         MOV      [EBX].fHandle, EBP\r
54657         TEST     ESI, ESI\r
54658         MOV      [EBX].fDIBAutoFree, 0\r
54659         JGE      @@noDIBautoFree\r
54660         INC      [EBX].fDIBAutoFree\r
54661 @@noDIBautoFree:\r
54663 @@fillBkColor:\r
54664         MOV      ECX, [EBX].fFillWithBkColor\r
54665         JECXZ    @@deleteDC2\r
54666         POP      EDX // (DC2)\r
54667         PUSH     EDX\r
54668         PUSH     EDI\r
54669         XCHG     ECX, ESI\r
54670         XCHG     EAX, EBX\r
54671         CALL     ESI\r
54672 @@deleteDC2:\r
54673         CALL     DeleteDC\r
54674         POPAD\r
54675 @@exit:\r
54676 end;\r
54677 {$ELSE ASM_VERSION} //Pascal\r
54678 procedure TBitmap.FormatChanged;\r
54679 // This method is used whenever Width, Height, PixelFormat or HandleType\r
54680 // properties are changed.\r
54681 // Old image will be drawn here to a new one (excluding cases when\r
54682 // old width or height was 0, and / or new width or height is 0).\r
54683 // To avoid inserting this code into executable, try not to change\r
54684 // properties Width / Height of bitmat after it is created using\r
54685 // NewBitmap( W, H ) function or after it is loaded from file, stream\r
54686 // or resource.\r
54688 var B: tagBitmap;\r
54689     oldBmp, NewHandle: HBitmap;\r
54690     DC0, DC2: HDC;\r
54691     NewHeader: PBitmapInfo;\r
54692     NewBits: Pointer;\r
54693     oldHeight, oldWidth, sizeBits, bitsPixel: Integer;\r
54694     Br: HBrush;\r
54695     N: Integer;\r
54696     NewDIBAutoFree: Boolean;\r
54697     Hndl: THandle;\r
54698 begin\r
54699   if Empty then Exit;\r
54700   NewDIBAutoFree := FALSE;\r
54701   fDetachCanvas( @Self );\r
54702   fScanLineSize := 0;\r
54703   fGetDIBPixels := nil;\r
54704   fSetDIBPixels := nil;\r
54706     oldWidth := fWidth;\r
54707     oldHeight := fHeight;\r
54708     if fDIBBits <> nil then\r
54709     begin\r
54710       oldWidth := fDIBHeader.bmiHeader.biWidth;\r
54711       oldHeight := Abs(fDIBHeader.bmiHeader.biHeight);\r
54712     end\r
54713       else\r
54714     if fHandle <> 0 then\r
54715     begin\r
54716       if GetObject( fHandle, Sizeof( B ), @ B ) <> 0 then\r
54717       begin\r
54718         oldWidth := B.bmWidth;\r
54719         oldHeight := B.bmHeight;\r
54720       end;\r
54721     end;\r
54723   DC2 := CreateCompatibleDC( 0 );\r
54725   if fHandleType = bmDDB then\r
54726   begin\r
54727     // New HandleType is bmDDB: old bitmap can be copied using Draw method\r
54728     DC0 := GetDC( 0 );\r
54729     NewHandle := CreateCompatibleBitmap( DC0, fWidth, fHeight );\r
54730     ASSERT( NewHandle <> 0, 'Can not create DDB' );\r
54731     ReleaseDC( 0, DC0 );\r
54733     oldBmp := SelectObject( DC2, NewHandle );\r
54734     ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );\r
54736     Br := CreateSolidBrush( Color2RGB( fBkColor ) );\r
54737     FillRect( DC2, MakeRect( 0, 0, fWidth, fHeight ), Br );\r
54738     DeleteObject( Br );\r
54740     if fDIBBits <> nil then\r
54741     begin\r
54742       SelectObject( DC2, oldBmp );\r
54743       SetDIBits( DC2, NewHandle, 0, fHeight, fDIBBits, fDIBHeader^, DIB_RGB_COLORS );\r
54744     end\r
54745        else\r
54746     begin\r
54747       Draw( DC2, 0, 0 );\r
54748       SelectObject( DC2, oldBmp );\r
54749     end;\r
54751     ClearData; // Image is cleared but fWidth and fHeight are preserved\r
54752     fHandle := NewHandle;\r
54753   end\r
54754      else\r
54755   begin\r
54756     // New format is DIB. GetDIBits applied to transform old data to new one.\r
54757     bitsPixel := BitCounts[ fNewPixelFormat ];\r
54758     if bitsPixel = 0 then\r
54759     begin\r
54760       bitsPixel := BitCounts[DefaultPixelFormat];\r
54761     end;\r
54763     NewHandle := 0;\r
54764     NewHeader := PrepareBitmapHeader( fWidth, fHeight, bitsPixel );\r
54765     if fNewPixelFormat = pf16bit then\r
54766       PreparePF16bit( NewHeader );\r
54768     sizeBits := CalcScanLineSize( @NewHeader.bmiHeader ) * fHeight;\r
54770       GetMem( NewBits, sizeBits );\r
54771       ASSERT( NewBits <> nil, 'No memory' );\r
54773       Hndl := GetHandle;\r
54774       if Hndl = 0 then Exit;\r
54775       N :=\r
54776       GetDIBits( DC2, Hndl, 0, Min( fHeight, oldHeight ),\r
54777                  NewBits, NewHeader^, DIB_RGB_COLORS );\r
54778       //Assert( N = Min( fHeight, oldHeight ), 'Can not get all DIB bits' );\r
54779       if N <> Min( fHeight, oldHeight ) then\r
54780       begin\r
54781         FreeMem( NewBits );\r
54782         NewBits := nil;\r
54783         NewHandle := CreateDIBSection( DC2, NewHeader^, DIB_RGB_COLORS, NewBits, 0, 0 );\r
54784         NewDIBAutoFree := TRUE;\r
54785         ASSERT( NewHandle <> 0, 'Can not create DIB secion for pf16bit bitmap' );\r
54786         oldBmp := SelectObject( DC2, NewHandle );\r
54787         ASSERT( oldBmp <> 0, 'Can not select pf16bit to DC' );\r
54788         Draw( DC2, 0, 0 );\r
54789         SelectObject( DC2, oldBmp );\r
54790       end;\r
54792     ClearData;\r
54793     fDIBSize := sizeBits;\r
54794     fDIBBits := NewBits;\r
54795     fDIBHeader := NewHeader;\r
54796     fHandle := NewHandle;\r
54797     fDIBAutoFree := NewDIBAutoFree;\r
54799   end;\r
54801   if Assigned( fFillWithBkColor ) then\r
54802      fFillWithBkColor( @Self, DC2, oldWidth, oldHeight );\r
54804   DeleteDC( DC2 );\r
54806 end;\r
54807 {$ENDIF ASM_VERSION}\r
54809 {$IFDEF ASM_VERSION}\r
54810 //[function TBitmap.GetScanLine]\r
54811 function TBitmap.GetScanLine(Y: Integer): Pointer;\r
54812 asm\r
54813         MOV      ECX, [EAX].fDIBHeader\r
54814         JECXZ    @@exit\r
54815         MOV      ECX, [ECX].TBitmapInfoHeader.biHeight\r
54816         TEST     ECX, ECX\r
54817         JL       @@1\r
54819         SUB      ECX, EDX\r
54820         DEC      ECX\r
54821         MOV      EDX, ECX\r
54823 @@1:    MOV      ECX, [EAX].fScanLineSize\r
54824         INC      ECX\r
54825         PUSH     [EAX].fDIBBits\r
54826         LOOP     @@2\r
54828         PUSH     EDX\r
54829         CALL     GetScanLineSize\r
54830         POP      EDX\r
54831         XCHG     ECX, EAX\r
54833 @@2:    XCHG     EAX, ECX\r
54834         MUL      EDX\r
54835         POP      ECX\r
54836         ADD      ECX, EAX\r
54838 @@exit: XCHG     EAX, ECX\r
54839 end;\r
54840 {$ELSE ASM_VERSION} //Pascal\r
54841 function TBitmap.GetScanLine(Y: Integer): Pointer;\r
54842 begin\r
54843   ASSERT( (Y >= 0) {and (Y < fHeight)}, 'ScanLine index out of bounds' );\r
54844   ASSERT( fDIBBits <> nil, 'No bits available' );\r
54845   Result := nil;\r
54846   if fDIBHeader = nil then Exit;\r
54848   if fDIBHeader.bmiHeader.biHeight > 0 then\r
54849      Y := fHeight - 1 - Y;\r
54850   if fScanLineSize = 0 then\r
54851      ScanLineSize;\r
54853   Result := Pointer( Integer( fDIBBits ) + fScanLineSize * Y );\r
54854 end;\r
54855 {$ENDIF ASM_VERSION}\r
54857 {$IFDEF ASM_VERSION}\r
54858 //[function TBitmap.GetScanLineSize]\r
54859 function TBitmap.GetScanLineSize: Integer;\r
54860 asm\r
54861         MOV      ECX, [EAX].fDIBHeader\r
54862         JECXZ    @@exit\r
54864         PUSH     EAX\r
54865         XCHG     EAX, ECX\r
54866         CALL     CalcScanLineSize\r
54867         XCHG     ECX, EAX\r
54868         POP      EAX\r
54869         MOV      [EAX].fScanLineSize, ECX\r
54871 @@exit: XCHG     EAX, ECX\r
54872 end;\r
54873 {$ELSE ASM_VERSION} //Pascal\r
54874 function TBitmap.GetScanLineSize: Integer;\r
54875 begin\r
54876   Result := 0;\r
54877   if fDIBHeader = nil then Exit;\r
54878   FScanLineSize := CalcScanLineSize( @fDIBHeader.bmiHeader );\r
54879   Result := FScanLineSize;\r
54880 end;\r
54881 {$ENDIF ASM_VERSION}\r
54883 {$IFDEF ASM_VERSION}\r
54884 //[procedure TBitmap.CanvasChanged]\r
54885 procedure TBitmap.CanvasChanged( Sender : PObj );\r
54886 asm\r
54887         PUSH     EAX\r
54889           XCHG     EAX, EDX\r
54890           CALL     TCanvas.GetBrush\r
54891           MOV      EDX, [EAX].TGraphicTool.fData.Color\r
54893         POP      EAX\r
54894         MOV      [EAX].fBkColor, EAX\r
54895         CALL     ClearTransImage\r
54896 end;\r
54897 {$ELSE ASM_VERSION} //Pascal\r
54898 procedure TBitmap.CanvasChanged( Sender : PObj );\r
54899 begin\r
54900   fBkColor := PCanvas( Sender ).Brush.Color;\r
54901   ClearTransImage;\r
54902 end;\r
54903 {$ENDIF ASM_VERSION}\r
54905 {$IFDEF ASM_VERSION}\r
54906 //[procedure TBitmap.Dormant]\r
54907 procedure TBitmap.Dormant;\r
54908 asm\r
54909         PUSH     EAX\r
54910         CALL     RemoveCanvas\r
54911         POP      EAX\r
54912         MOV      ECX, [EAX].fHandle\r
54913         JECXZ    @@exit\r
54914         CALL     ReleaseHandle\r
54915         PUSH     EAX\r
54916         CALL     DeleteObject\r
54917 @@exit:\r
54918 end;\r
54919 {$ELSE ASM_VERSION} //Pascal\r
54920 procedure TBitmap.Dormant;\r
54921 begin\r
54922   RemoveCanvas;\r
54923   if fHandle <> 0 then\r
54924     DeleteObject( ReleaseHandle );\r
54925 end;\r
54926 {$ENDIF ASM_VERSION}\r
54928 {$IFDEF ASM_VERSION}\r
54929 //[procedure TBitmap.SetBkColor]\r
54930 procedure TBitmap.SetBkColor(const Value: TColor);\r
54931 asm\r
54932         CMP      [EAX].fBkColor, EDX\r
54933         JE       @@exit\r
54934         MOV      [EAX].fBkColor, EDX\r
54935         MOV      [EAX].fFillWithBkColor, offset[FillBmpWithBkColor]\r
54936         MOV      ECX, [EAX].fApplyBkColor2Canvas\r
54937         JECXZ    @@exit\r
54938         CALL     ECX\r
54939 @@exit:\r
54940 end;\r
54941 {$ELSE ASM_VERSION} //Pascal\r
54942 procedure TBitmap.SetBkColor(const Value: TColor);\r
54943 begin\r
54944   if fBkColor = Value then Exit;\r
54945   fBkColor := Value;\r
54946   fFillWithBkColor := FillBmpWithBkColor;\r
54947   if Assigned( fApplyBkColor2Canvas ) then\r
54948     fApplyBkColor2Canvas( @Self );\r
54949 end;\r
54950 {$ENDIF ASM_VERSION}\r
54952 {$IFDEF ASM_VERSION} \r
54953 //[function TBitmap.Assign]\r
54954 function TBitmap.Assign(SrcBmp: PBitmap): Boolean;\r
54955 const szBIH = sizeof(TBitmapInfoHeader);\r
54956 asm\r
54957         PUSHAD\r
54958         XCHG     EBX, EAX\r
54959 @@clear:\r
54960         MOV      ESI, EDX\r
54961         MOV      EAX, EBX\r
54962         CALL     Clear\r
54963         MOV      EAX, ESI\r
54964         OR       EAX, EAX\r
54965         JZ       @@exit\r
54966         CALL     GetEmpty\r
54967         JZ       @@exit\r
54968         MOV      EAX, [ESI].fWidth\r
54969         MOV      [EBX].fWidth, EAX\r
54970         MOV      EAX, [ESI].fHeight\r
54971         MOV      [EBX].fHeight, EAX\r
54972         MOVZX    ECX, [ESI].fHandleType\r
54973         MOV      [EBX].fHandleType, CL\r
54974           JECXZ    @@fmtDIB\r
54976         DEC      ECX  // ECX = 0\r
54977         PUSH     ECX\r
54978         PUSH     ECX\r
54979         PUSH     ECX\r
54980         PUSH     ECX //IMAGE_BITMAP=0\r
54981         PUSH     [ESI].fHandle\r
54982         CALL     CopyImage\r
54983         MOV      [EBX].fHandle, EAX\r
54984         TEST     EAX, EAX\r
54985         XCHG     EDX, EAX\r
54986         JZ       @@clear\r
54987         JMP      @@exit\r
54989 @@fmtDIB:\r
54990         XCHG     EAX, ECX\r
54991         MOV      AX, szBIH+1024\r
54992         PUSH     EAX\r
54993         CALL     System.@GetMem\r
54994         MOV      [EBX].fDIBHeader, EAX\r
54995         XCHG     EDX, EAX\r
54996         POP      ECX\r
54997         MOV      EAX, [ESI].fDIBHeader\r
54998         CALL     System.Move\r
54999         MOV      EAX, [ESI].fDIBSize\r
55000         MOV      [EBX].fDIBSize, EAX\r
55001         PUSH     EAX\r
55002         CALL     System.@GetMem\r
55003         MOV      [EBX].fDIBBits, EAX\r
55004         XCHG     EDX, EAX\r
55005         POP      ECX\r
55006         MOV      EAX, [ESI].fDIBBits\r
55007         CALL     System.Move\r
55009         INC      EBX // reset "ZF"\r
55011 @@exit:\r
55012         POPAD\r
55013         SETNZ    AL\r
55014 end;\r
55015 {$ELSE ASM_VERSION} //Pascal\r
55016 function TBitmap.Assign(SrcBmp: PBitmap): Boolean;\r
55017 begin\r
55018   Clear;\r
55019   Result := False;\r
55020   if SrcBmp = nil then Exit;\r
55021   if SrcBmp.Empty then Exit;\r
55022   fWidth := SrcBmp.fWidth;\r
55023   fHeight := SrcBmp.fHeight;\r
55024   fHandleType := SrcBmp.fHandleType;\r
55025   if SrcBmp.fHandleType = bmDDB then\r
55026   begin\r
55027     fHandle := CopyImage( SrcBmp.fHandle, IMAGE_BITMAP, 0, 0, 0 {LR_COPYRETURNORG} );\r
55028     ASSERT( fHandle <> 0, 'Can not copy bitmap image' );\r
55029     Result := fHandle <> 0;\r
55030     if not Result then Clear;\r
55031   end\r
55032      else\r
55033   begin\r
55034     GetMem( fDIBHeader, Sizeof(TBitmapInfoHeader) + 256*sizeof(TRGBQuad) );\r
55035     ASSERT( fDIBHeader <> nil, 'No memory' );\r
55036     Move( SrcBmp.fDIBHeader^, fDIBHeader^, Sizeof(TBitmapInfoHeader) + 256*sizeof(TRGBQuad) );\r
55037     fDIBSize := SrcBmp.fDIBSize;\r
55038     GetMem( fDIBBits, fDIBSize );\r
55039     ASSERT( fDIBBits <> nil, 'No memory' );\r
55040     Move( SrcBmp.fDIBBits^, fDIBBits^, fDIBSize );\r
55041     //fDIBAutoFree := TRUE;\r
55042     Result := True;\r
55043   end;\r
55044 end;\r
55045 {$ENDIF ASM_VERSION}\r
55047 {$IFDEF ASM_VERSION}\r
55048 //[procedure TBitmap.RemoveCanvas]\r
55049 procedure TBitmap.RemoveCanvas;\r
55050 asm\r
55051         PUSH     EAX\r
55052         CALL     [EAX].fDetachCanvas\r
55053         POP      EDX\r
55054         XOR      EAX, EAX\r
55055         XCHG     EAX, [EDX].fCanvas\r
55056         CALL     TObj.Free\r
55057 end;\r
55058 {$ELSE ASM_VERSION} //Pascal\r
55059 procedure TBitmap.RemoveCanvas;\r
55060 begin\r
55061   fDetachCanvas( @Self );\r
55062   fCanvas.Free;\r
55063   fCanvas := nil;\r
55064 end;\r
55065 {$ENDIF ASM_VERSION}\r
55067 {$IFDEF ASM_VERSION}\r
55068 //[function TBitmap.DIBPalNearestEntry]\r
55069 function TBitmap.DIBPalNearestEntry(Color: TColor): Integer;\r
55070 const szBIH = sizeof(TBitmapInfoHeader);\r
55071 asm\r
55072         PUSH     EBX\r
55073         PUSH     ESI\r
55074         PUSH     EDI\r
55075         XCHG     ESI, EAX\r
55076         XCHG     EAX, EDX\r
55077         CALL     Color2RGBQuad\r
55078         XCHG     EDI, EAX\r
55079         MOV      EAX, ESI\r
55080         CALL     GetDIBPalEntryCount\r
55081         XCHG     ECX, EAX\r
55082         XOR      EAX, EAX\r
55083         JECXZ    @@exit\r
55085         MOV      ESI, [ESI].fDIBHeader\r
55086         ADD      ESI, szBIH\r
55087         XOR      EDX, EDX\r
55088         PUSH     EDX\r
55089         DEC      DX\r
55091 @@loo:  LODSD\r
55092         XOR      EAX, EDI\r
55093         MOV      EBX, EAX\r
55094         SHR      EBX, 16\r
55095         MOV      BH, 0\r
55096         ADD      AL, AH\r
55097         MOV      AH, 0\r
55098         ADC      AX, BX\r
55099         CMP      AX, DX\r
55100         JAE      @@1\r
55101         MOV      DX, AX\r
55102         POP      EBX\r
55103         PUSH     EDX // save better index (in high order word)\r
55104 @@1:    ADD      EDX, $10000 // increment index\r
55105         LOOP     @@loo\r
55107         XCHG     EAX, ECX\r
55108         POP      AX\r
55109         POP      AX\r
55110 @@exit:\r
55111         POP      EDI\r
55112         POP      ESI\r
55113         POP      EBX\r
55114 end;\r
55115 {$ELSE ASM_VERSION} //Pascal\r
55116 function TBitmap.DIBPalNearestEntry(Color: TColor): Integer;\r
55117 var I, Diff, D: Integer;\r
55118     C : Integer;\r
55119 begin\r
55120   Color := TColor( Color2RGBQuad( Color ) );\r
55121   Result := 0;\r
55122   Diff := MaxInt;\r
55123   for I := 0 to DIBPalEntryCount - 1 do\r
55124   begin\r
55125     C := Color xor PInteger( Integer( @fDIBHeader.bmiColors[ 0 ] )\r
55126                     + I * Sizeof( TRGBQuad ) )^;\r
55127     D := TRGBQuad( C ).rgbBlue + TRGBQuad( C ).rgbGreen + TRGBQuad( C ).rgbRed;\r
55128     if D < Diff then\r
55129     begin\r
55130       Diff := D;\r
55131       Result := I;\r
55132     end;\r
55133   end;\r
55134 end;\r
55135 {$ENDIF ASM_VERSION}\r
55137 {$IFDEF ASM_VERSION}\r
55138 //[function TBitmap.GetDIBPalEntries]\r
55139 function TBitmap.GetDIBPalEntries(Idx: Integer): TColor;\r
55140 const szBIH = sizeof(TBitmapInfoHeader);\r
55141 asm\r
55142         MOV      ECX, [EAX].fDIBHeader\r
55143         JECXZ    @@exit\r
55145         MOV      ECX, [EAX+szBIH+EDX*4]\r
55146         INC      ECX\r
55148 @@exit: DEC      ECX\r
55149         XCHG     EAX, ECX\r
55150 end;\r
55151 {$ELSE ASM_VERSION} //Pascal\r
55152 function TBitmap.GetDIBPalEntries(Idx: Integer): TColor;\r
55153 begin\r
55154   Result := TColor(-1);\r
55155   if fDIBBits = nil then Exit;\r
55156   ASSERT( PixelFormat in [pf1bit..pf8bit], 'Format has no DIB palette entries available' );\r
55157   ASSERT( (Idx >= 0) and (Idx < (1 shl fDIBHeader.bmiHeader.biBitCount)),\r
55158           'DIB palette index out of bounds' );\r
55159   Result := PDWORD( Integer( @fDIBHeader.bmiColors[ 0 ] )\r
55160           + Idx * Sizeof( TRGBQuad ) )^;\r
55161 end;\r
55162 {$ENDIF ASM_VERSION}\r
55164 {$IFDEF ASM_VERSION}\r
55165 //[function TBitmap.GetDIBPalEntryCount]\r
55166 function TBitmap.GetDIBPalEntryCount: Integer;\r
55167 asm\r
55168         PUSH     EAX\r
55169         CALL     GetEmpty\r
55170         POP      EAX\r
55171         JZ       @@ret0\r
55172         CALL     GetPixelFormat\r
55173         MOVZX    ECX, AL\r
55174         MOV      EAX, ECX\r
55175         LOOP     @@1\r
55176         // pf1bit:\r
55177         INC      EAX\r
55178         RET\r
55179 @@1:\r
55180         LOOP     @@2\r
55181         // pf4bit:\r
55182         MOV      AL, 16\r
55183         RET\r
55184 @@2:\r
55185         LOOP     @@ret0\r
55186         // pf8bit:\r
55187         XOR      EAX, EAX\r
55188         INC      AH\r
55189         RET\r
55190 @@ret0:\r
55191         XOR      EAX, EAX\r
55192 end;\r
55193 {$ELSE ASM_VERSION} //Pascal\r
55194 function TBitmap.GetDIBPalEntryCount: Integer;\r
55195 begin\r
55196   Result := 0;\r
55197   if Empty then Exit;\r
55198   case PixelFormat of\r
55199   pf1bit: Result := 2;\r
55200   pf4bit: Result := 16;\r
55201   pf8bit: Result := 256;\r
55202   else;\r
55203   end;\r
55204 end;\r
55205 {$ENDIF ASM_VERSION}\r
55207 //[procedure TBitmap.SetDIBPalEntries]\r
55208 procedure TBitmap.SetDIBPalEntries(Idx: Integer; const Value: TColor);\r
55209 begin\r
55210   if fDIBBits = nil then Exit;\r
55211   Dormant;\r
55212   PDWORD( Integer( @fDIBHeader.bmiColors[ 0 ] )\r
55213                     + Idx * Sizeof( TRGBQuad ) )^ := Color2RGB( Value );\r
55214 end;\r
55216 //[procedure TBitmap.SetHandleType]\r
55217 procedure TBitmap.SetHandleType(const Value: TBitmapHandleType);\r
55218 {var B: tagBitmap;\r
55219     DC0: HDC;}\r
55220 begin\r
55221   if fHandleType = Value then Exit;\r
55222   //++++++++++++++++ ?????????\r
55223   {if fHandleType = bmDDB then\r
55224     if PixelFormat = pfDevice then\r
55225     begin\r
55226       DC0 := GetDC( 0 );\r
55227       fNewPixelFormat := Bits2PixelFormat( GetDeviceCaps( DC0, BITSPIXEL ) );\r
55228       ReleaseDC( 0, DC0 );\r
55229     end\r
55230       else\r
55231     if FHandle <> 0 then\r
55232     begin\r
55233       if GetObject( FHandle, Sizeof( B ), @ B ) > 0 then\r
55234         fNewPixelFormat := Bits2PixelFormat( B.bmPlanes * B.bmBitsPixel );\r
55235     end;}\r
55236   //----------------\r
55237   fHandleType := Value;\r
55238   FormatChanged;\r
55239 end;\r
55241 //[function TBitmap.GetPixelFormat]\r
55242 function TBitmap.GetPixelFormat: TPixelFormat;\r
55243 begin\r
55244   if (HandleType = bmDDB) or (fDIBBits = nil) then\r
55245     Result := pfDevice\r
55246   else\r
55247   begin\r
55248     Result := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount );\r
55249     if (Result = pf15bit) and (fDIBHeader.bmiHeader.biCompression <> 0) then\r
55250     begin\r
55251       Assert( fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS, 'Unsupported bitmap format' );\r
55252       Result := pf16bit;\r
55253     end;\r
55254   end;\r
55255 end;\r
55257 {$IFDEF ASM_VERSION}\r
55258 //[procedure TBitmap.ClearTransImage]\r
55259 procedure TBitmap.ClearTransImage;\r
55260 asm\r
55261         OR       [EAX].fTransColor, -1\r
55262         XOR      EDX, EDX\r
55263         XCHG     [EAX].fTransMaskBmp, EDX\r
55264         XCHG     EAX, EDX\r
55265         CALL     TObj.Free\r
55266 end;\r
55267 {$ELSE ASM_VERSION} //Pascal\r
55268 procedure TBitmap.ClearTransImage;\r
55269 begin\r
55270   fTransColor := clNone;\r
55271   fTransMaskBmp.Free;\r
55272   fTransMaskBmp := nil;\r
55273 end;\r
55274 {$ENDIF ASM_VERSION}\r
55276 {$IFDEF ASM_VERSION}\r
55277 //[procedure TBitmap.Convert2Mask]\r
55278 procedure TBitmap.Convert2Mask(TranspColor: TColor);\r
55279 asm\r
55280         PUSH     EBX\r
55281         PUSH     ESI\r
55282         MOV      EBX, EAX\r
55283         MOV      ESI, EDX\r
55284         CALL     GetHandle\r
55285         TEST     EAX, EAX\r
55286         JZ       @@exit\r
55288         PUSH     0\r
55289         PUSH     1\r
55290         PUSH     1\r
55291         PUSH     [EBX].fHeight\r
55292         PUSH     [EBX].fWidth\r
55293         CALL     CreateBitmap\r
55294         PUSH     EAX                // MonoHandle\r
55295         PUSH     0\r
55296         CALL     CreateCompatibleDC\r
55297         POP      EDX\r
55298         PUSH     EDX\r
55299         PUSH     EAX                // MonoDC\r
55301         PUSH     EDX\r
55302         PUSH     EAX\r
55303         CALL     SelectObject\r
55304         PUSH     EAX                // SaveMono\r
55306         CALL     StartDC            // DCfrom, SaveFrom\r
55307         XCHG     EAX, ESI\r
55308         CALL     Color2RGB\r
55309         PUSH     EAX // Color2RGB(TranspColor)\r
55310         PUSH     dword ptr [ESP+8] //DCfrom\r
55311         CALL     Windows.SetBkColor\r
55312         PUSH     EAX                // SaveBkColor\r
55314         PUSH     SRCCOPY\r
55315         PUSH     0\r
55316         PUSH     0\r
55317         PUSH     dword ptr [ESP+12+4+4] //DCfrom\r
55318         PUSH     [EBX].fHeight\r
55319         PUSH     [EBX].fWidth\r
55320         PUSH     0\r
55321         PUSH     0\r
55322         PUSH     dword ptr [ESP+32+16] //MonoDC\r
55323         CALL     BitBlt\r
55325         PUSH     dword ptr [ESP+8] //DCfrom\r
55326         CALL     Windows.SetBkColor // ESP-> SaveFrom\r
55327         CALL     FinishDC           // ESP-> SaveMono\r
55328         CALL     FinishDC           // ESP-> MonoHandle\r
55330         MOV      EAX, EBX\r
55331         CALL     ClearData\r
55332         POP      [EBX].fHandle\r
55333         MOV      [EBX].fHandleType, bmDDB\r
55334 @@exit:\r
55335         POP      ESI\r
55336         POP      EBX\r
55337 end;\r
55338 {$ELSE ASM_VERSION} //Pascal\r
55339 procedure TBitmap.Convert2Mask(TranspColor: TColor);\r
55340 var MonoHandle: HBitmap;\r
55341     SaveMono, SaveFrom: THandle;\r
55342     MonoDC, {DC0,} DCfrom: HDC;\r
55343     SaveBkColor: TColorRef;\r
55344 begin\r
55345   if GetHandle = 0 then Exit;\r
55346   fDetachCanvas( @Self );\r
55347   ///DC0 := GetDC( 0 );\r
55348   MonoHandle := CreateBitmap( fWidth, fHeight, 1, 1, nil );\r
55349   ASSERT( MonoHandle <> 0, 'Can not create monochrome bitmap' );\r
55350   MonoDC := CreateCompatibleDC( 0 );\r
55351   SaveMono := SelectObject( MonoDC, MonoHandle );\r
55352   ASSERT( SaveMono <> 0, 'Can not select bitmap to DC' );\r
55353   DCfrom := CreateCompatibleDC( 0 );\r
55354   SaveFrom := SelectObject( DCfrom, fHandle );\r
55355   ASSERT( SaveFrom <> 0, 'Can not select source bitmap to DC' );\r
55356   TranspColor := Color2RGB( TranspColor );\r
55357   SaveBkColor := Windows.SetBkColor( DCfrom, TranspColor );\r
55358   BitBlt( MonoDC, 0, 0, fWidth, fHeight, DCfrom, 0, 0, SRCCOPY );\r
55359   {$IFDEF CHK_BITBLT} Chk_BitBlt; {$ENDIF}\r
55360   Windows.SetBkColor( DCfrom, SaveBkColor );\r
55361   SelectObject( DCfrom, SaveFrom );\r
55362   DeleteDC( DCfrom );\r
55363   SelectObject( MonoDC, SaveMono );\r
55364   DeleteDC( MonoDC );\r
55365   ///ReleaseDC( 0, DC0 );\r
55366   ClearData;\r
55367   fHandle := MonoHandle;\r
55368   fHandleType := bmDDB;\r
55369 end;\r
55370 {$ENDIF ASM_VERSION}\r
55372 //[procedure TBitmap.Invert]\r
55373 procedure TBitmap.Invert;\r
55374 begin\r
55375   //BitBlt( Canvas.Handle, 0, 0, Width, Height, Canvas.Handle, 0, 0, DSTINVERT  )\r
55376   InvertRect(Canvas.Handle, BoundsRect);\r
55377 end;\r
55379 //[procedure TBitmap.DIBDrawRect]\r
55380 procedure TBitmap.DIBDrawRect( DC: HDC; X, Y: Integer; const R: TRect );\r
55381 begin\r
55382   if fDIBBits = nil then Exit;\r
55383   StretchDIBits( DC, X, Y, R.Right - R.Left, R.Bottom - R.Top,\r
55384                  R.Left, fHeight - R.Bottom, R.Right - R.Left, R.Bottom - R.Top,\r
55385                  fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY );\r
55386 end;\r
55388 //[PROCEDURE _PrepareBmp2Rotate]\r
55389 {$IFDEF ASM_VERSION}\r
55390 procedure _PrepareBmp2Rotate;\r
55391 const szBIH = sizeof(TBitmapInfoHeader);\r
55392 asm\r
55393         { <- BL = increment to height }\r
55394         XCHG     EDI, EAX\r
55395         MOV      ESI, EDX // ESI = SrcBmp\r
55397         XCHG     EAX, EDX\r
55398         CALL     TBitmap.GetPixelFormat\r
55399         MOVZX    ECX, AL\r
55400         PUSH     ECX\r
55402         MOV      EDX, [ESI].TBitmap.fWidth\r
55403         MOVZX    EBX, BL\r
55404         ADD      EDX, EBX\r
55406         MOV      EAX, [ESI].TBitmap.fHeight\r
55407         CALL     NewDIBBitmap\r
55408         STOSD\r
55409         XCHG     EDI, EAX\r
55411         MOV      EAX, [ESI].TBitmap.fDIBHeader\r
55412         ADD      EAX, szBIH\r
55413         MOV      EDX, [EDI].TBitmap.fDIBHeader\r
55414         ADD      EDX, szBIH\r
55415         XOR      ECX, ECX\r
55416         MOV      CH, 4\r
55417         CALL     System.Move\r
55419         MOV      EAX, EDI\r
55420         XOR      EDX, EDX\r
55421         CALL     TBitmap.GetScanLine\r
55422         MOV      EBX, [EDI].TBitmap.fWidth\r
55423         DEC      EBX // EBX = DstBmp.fWidth - 1\r
55424         XCHG     EDI, EAX // EDI = DstBmp.ScanLine[ 0 ]\r
55426         XOR      EDX, EDX\r
55427         INC      EDX\r
55428         CALL     TBitmap.GetScanLine\r
55429         XCHG     EDX, EAX\r
55430         SUB      EDX, EDI // EDX = BytesPerDstLine\r
55432         MOV      EBP, [ESI].TBitmap.fWidth\r
55433         DEC      EBP // EBP = SrcBmp.fWidth - 1\r
55435         POP      ECX // ECX = PixelFormat\r
55436 end;\r
55437 {$ENDIF ASM_VERSION}\r
55438 //[END _PrepareBmp2Rotate]\r
55440 //[PROCEDURE _RotateBitmapMono]\r
55441 {$IFDEF ASM_VERSION}\r
55442 procedure _RotateBitmapMono( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55443 const szBIH = sizeof(TBitmapInfoHeader);\r
55444 asm\r
55445         PUSHAD\r
55446         MOV      BL, 7\r
55447         CALL     _PrepareBmp2Rotate\r
55449         SHR      EBP, 3\r
55450         SHL      EBP, 8 // EBP = (WBytes-1) * 256\r
55452         MOV      ECX, EBX // ECX and 7 = Shf\r
55453         SHR      EBX, 3\r
55454         ADD      EDI, EBX // EDI = Dst\r
55456         XOR      EBX, EBX // EBX = temp mask\r
55457         XOR      EAX, EAX // Y = 0\r
55458 @@looY:\r
55459         PUSH     EAX\r
55460         PUSH     EDI // Dst1 = Dst (Dst1 in EDI, Dst saved)\r
55461         PUSH     ESI // SrcBmp\r
55463         PUSH     EDX //BytesPerDstLine\r
55464         PUSH     ECX //Shf\r
55466         XCHG     EDX, EAX\r
55467         XCHG     EAX, ESI\r
55468         CALL     TBitmap.GetScanLine\r
55469         XCHG     ESI, EAX // ESI = Src\r
55471         POP      ECX // CL = Shf\r
55472         AND      ECX, 7 // ECX = Shf\r
55473         OR       ECX, EBP // ECX = (Wbytes-1)*8 + Shf\r
55474         POP      EDX // EDX = BytesPerDstLine\r
55476         MOV      BH, $80\r
55477         SHR      EBX, CL // BH = mask, BL = mask & Tmp\r
55478 @@looX:\r
55479         XOR      EAX, EAX\r
55481         LODSB\r
55483         MOV      AH, AL\r
55484         SHR      EAX, CL\r
55485         OR       EAX,$01000000\r
55487 @@looBits:\r
55488         MOV      BL, AH\r
55489         AND      BL, BH\r
55490         OR       [EDI], BL\r
55491         ADD      EDI, EDX\r
55492         ADD      EAX, EAX\r
55493         JNC      @@looBits\r
55495         SUB      ECX, 256\r
55496         JGE      @@looX\r
55498         POP      ESI // ESI = SrcBmp\r
55499         POP      EDI // EDI = Dst\r
55500         POP      EAX // EAX = Y\r
55502         ADD      ECX, 256-1\r
55503         JGE      @@1\r
55504         DEC      EDI\r
55505 @@1:\r
55506         INC      EAX\r
55507         CMP      EAX, [ESI].TBitmap.fHeight\r
55508         JL       @@looY\r
55510         POPAD\r
55511 end;\r
55512 {$ELSE ASM_VERSION} //Pascal\r
55513 procedure _RotateBitmapMono( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55514 var X, Y, Z, Shf, Wbytes, BytesPerDstLine: Integer;\r
55515     Src, Dst, Dst1: PByte;\r
55516     Tmp: Byte;\r
55517 begin\r
55519   DstBmp := NewDIBBitmap( SrcBmp.fHeight, (SrcBmp.fWidth + 7) and not 7, pf1bit );\r
55520   Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 2 * Sizeof( TRGBQuad ) );\r
55522   // Calculate ones:\r
55523   Dst := DstBmp.ScanLine[ 0 ];\r
55524   BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );\r
55525   Wbytes := (SrcBmp.fWidth + 7) shr 3;\r
55527   Inc( Dst, (DstBmp.fWidth - 1) shr 3 );\r
55528   Shf := (DstBmp.fWidth - 1) and 7;\r
55530   // Rotating bits:\r
55531   for Y := 0 to SrcBmp.fHeight - 1 do\r
55532   begin\r
55533     Src := SrcBmp.ScanLine[ Y ];\r
55534     Dst1 := Dst;\r
55535     for X := Wbytes downto 1 do\r
55536     begin\r
55537       Tmp := Src^;\r
55538       Inc( Src );\r
55539       for Z := 8 downto 1 do\r
55540       begin\r
55541         Dst1^ := Dst1^ or ( (Tmp and $80) shr Shf );\r
55542         Tmp := Tmp shl 1;\r
55543         Inc( Dst1, BytesPerDstLine );\r
55544       end;\r
55545     end;\r
55546     Dec( Shf );\r
55547     if Shf < 0 then\r
55548     begin\r
55549       Shf := 7;\r
55550       Dec( Dst );\r
55551     end;\r
55552   end;\r
55553 end;\r
55554 {$ENDIF ASM_VERSION}\r
55555 //[END _RotateBitmapMono]\r
55557 //[PROCEDURE _RotateBitmap4bit]\r
55558 {$IFDEF ASM_VERSION}\r
55559 procedure _RotateBitmap4bit( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55560 const szBIH = sizeof(TBitmapInfoHeader);\r
55561 asm\r
55562         PUSHAD\r
55563         MOV      BL, 1\r
55564         CALL     _PrepareBmp2Rotate\r
55566         SHR      EBP, 1 // EBP = WBytes - 1\r
55567         SHL      EBP, 8 // EBP = (WBytes - 1) * 256\r
55569         // EBX = DstBmp.fWidth - 1\r
55570         MOV      ECX, EBX\r
55571         SHL      ECX, 2 // ECX and 7 = Shf (0 or 4)\r
55572         SHR      EBX, 1\r
55573         ADD      EDI, EBX // EDI = Dst\r
55575         XOR      EAX, EAX // Y = 0\r
55576         XOR      EBX, EBX\r
55578 @@looY:\r
55579         PUSH     EAX // save Y\r
55580         PUSH     EDI // Dst1 = Dst (Dst1 in EDI, Dst saved)\r
55581         PUSH     ESI // SrcBmp\r
55583         PUSH     EDX // BytesPerDstLine\r
55584         PUSH     ECX // Shf\r
55586         XCHG     EDX, EAX\r
55587         XCHG     EAX, ESI\r
55588         CALL     TBitmap.GetScanLine\r
55589         XCHG     ESI, EAX // ESI = Src\r
55591         POP      ECX\r
55592         AND      ECX, 7 // CL = Shf\r
55593         OR       ECX, EBP // ECX = (WBytes-1)*256 + Shf\r
55594         POP      EDX // EDX = BytesPerDstLine\r
55596         MOV      BH, $F0\r
55597         SHR      EBX, CL // shift mask right 4 or 0\r
55599 @@looX:\r
55600         XOR      EAX, EAX\r
55601         LODSB\r
55602         MOV      AH, AL\r
55603         SHR      EAX, CL\r
55605         MOV      BL, AH\r
55606         AND      BL, BH\r
55607         OR       [EDI], BL\r
55608         ADD      EDI, EDX\r
55610         SHL      EAX, 4\r
55611         AND      AH, BH\r
55612         OR       [EDI], AH\r
55613         ADD      EDI, EDX\r
55615         SUB      ECX, 256\r
55616         JGE      @@looX\r
55618         POP      ESI // ESI = SrcBmp\r
55619         POP      EDI // EDI = Dst\r
55620         POP      EAX // EAX = Y\r
55622         ADD      ECX, 256 - 4\r
55623         JGE      @@1\r
55625         DEC      EDI\r
55626 @@1:\r
55627         INC      EAX\r
55628         CMP      EAX, [ESI].TBitmap.fHeight\r
55629         JL       @@looY\r
55631         POPAD\r
55632 end;\r
55633 {$ELSE ASM_VERSION} //Pascal\r
55634 procedure _RotateBitmap4bit( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55635 var X, Y, Shf, Wbytes, BytesPerDstLine: Integer;\r
55636     Src, Dst, Dst1: PByte;\r
55637     Tmp: Byte;\r
55638 begin\r
55640   DstBmp := NewDIBBitmap( SrcBmp.fHeight, (SrcBmp.fWidth + 1) and not 1, pf4bit );\r
55641   Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 16 * Sizeof( TRGBQuad ) );\r
55643   // Calculate ones:\r
55644   Dst := DstBmp.ScanLine[ 0 ];\r
55645   BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );\r
55646   Wbytes := (SrcBmp.fWidth + 1) shr 1;\r
55648   Inc( Dst, (DstBmp.fWidth - 1) shr 1 );\r
55649   Shf := ((DstBmp.fWidth - 1) and 1) shl 2;\r
55651   // Rotating bits:\r
55652   for Y := 0 to SrcBmp.fHeight - 1 do\r
55653   begin\r
55654     Src := SrcBmp.ScanLine[ Y ];\r
55655     Dst1 := Dst;\r
55656     for X := Wbytes downto 1 do\r
55657     begin\r
55658       Tmp := Src^;\r
55659       Inc( Src );\r
55660       Dst1^ := Dst1^ or ( (Tmp and $F0) shr Shf );\r
55661       Inc( Dst1, BytesPerDstLine );\r
55662       Dst1^ := Dst1^ or ( ((Tmp shl 4) and $F0) shr Shf );\r
55663       Inc( Dst1, BytesPerDstLine );\r
55664     end;\r
55665     Dec( Shf, 4 );\r
55666     if Shf < 0 then\r
55667     begin\r
55668       Shf := 4;\r
55669       Dec( Dst );\r
55670     end;\r
55671   end;\r
55672 end;\r
55673 {$ENDIF ASM_VERSION}\r
55674 //[END _RotateBitmap4bit]\r
55676 //[PROCEDURE _RotateBitmap8bit]\r
55677 {$IFDEF ASM_VERSION}\r
55678 procedure _RotateBitmap8bit( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55679 const szBIH = sizeof(TBitmapInfoHeader);\r
55680 asm\r
55681         PUSHAD\r
55682         XOR      EBX, EBX\r
55683         CALL     _PrepareBmp2Rotate\r
55685         ADD      EDI, EBX // EDI = Dst\r
55687         MOV      EBX, EDX // EBX = BytesPerDstLine\r
55688         DEC      EBX\r
55689         MOV      EBP, ESI // EBP = SrcBmp\r
55691         XOR      EDX, EDX // Y = 0\r
55693 @@looY:\r
55694         PUSH     EDX\r
55695         PUSH     EDI\r
55697         MOV      EAX, EBP\r
55698         CALL     TBitmap.GetScanLine\r
55699         XCHG     ESI, EAX\r
55700         MOV      ECX, [EBP].TBitmap.fWidth\r
55702 @@looX:\r
55703         MOVSB\r
55704         ADD      EDI, EBX\r
55705         LOOP     @@looX\r
55707         POP      EDI\r
55708         POP      EDX\r
55710         DEC      EDI\r
55711         INC      EDX\r
55712         CMP      EDX, [EBP].TBitmap.fHeight\r
55713         JL       @@looY\r
55715         POPAD\r
55716 end;\r
55717 {$ELSE ASM_VERSION} //Pascal\r
55718 procedure _RotateBitmap8bit( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55719 var X, Y, Wbytes, BytesPerDstLine: Integer;\r
55720     Src, Dst, Dst1: PByte;\r
55721     Tmp: Byte;\r
55722 begin\r
55724   DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );\r
55725   Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 256 * Sizeof( TRGBQuad ) );\r
55727   // Calculate ones:\r
55728   Wbytes := SrcBmp.fWidth;\r
55729   Dst := DstBmp.ScanLine[ 0 ];\r
55730   BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );\r
55732   Inc( Dst, DstBmp.fWidth - 1 );\r
55734   // Rotating bits:\r
55735   for Y := 0 to SrcBmp.fHeight - 1 do\r
55736   begin\r
55737     Src := SrcBmp.ScanLine[ Y ];\r
55738     Dst1 := Dst;\r
55739     for X := Wbytes downto 1 do\r
55740     begin\r
55741       Tmp := Src^;\r
55742       Inc( Src );\r
55743       Dst1^ := Tmp;\r
55744       Inc( Dst1, BytesPerDstLine );\r
55745     end;\r
55746     Dec( Dst );\r
55747   end;\r
55749 end;\r
55750 {$ENDIF ASM_VERSION}\r
55751 //[END _RotateBitmap8bit]\r
55753 //[PROCEDURE _RotateBitmap16bit]\r
55754 {$IFDEF ASM_VERSION}\r
55755 procedure _RotateBitmap16bit( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55756 asm\r
55757         PUSHAD\r
55758         XOR      EBX, EBX\r
55759         CALL     _PrepareBmp2Rotate\r
55761         ADD      EBX, EBX\r
55762         ADD      EDI, EBX // EDI = Dst\r
55763         MOV      EBX, EDX // EBX = BytesPerDstLine\r
55764         DEC      EBX\r
55765         DEC      EBX\r
55766         MOV      EBP, ESI // EBP = SrcBmp\r
55768         XOR      EDX, EDX // Y = 0\r
55770 @@looY:\r
55771         PUSH     EDX\r
55772         PUSH     EDI\r
55774         MOV      EAX, EBP\r
55775         CALL     TBitmap.GetScanLine\r
55776         XCHG     ESI, EAX\r
55777         MOV      ECX, [EBP].TBitmap.fWidth\r
55779 @@looX:\r
55780         MOVSW\r
55781         ADD      EDI, EBX\r
55782         LOOP     @@looX\r
55784         POP      EDI\r
55785         POP      EDX\r
55787         DEC      EDI\r
55788         DEC      EDI\r
55789         INC      EDX\r
55790         CMP      EDX, [EBP].TBitmap.fHeight\r
55791         JL       @@looY\r
55793         POPAD\r
55794 end;\r
55795 {$ELSE ASM_VERSION} //Pascal\r
55796 procedure _RotateBitmap16bit( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55797 var X, Y, Wwords, BytesPerDstLine: Integer;\r
55798     Src, Dst, Dst1: PWord;\r
55799     Tmp: Word;\r
55800 begin\r
55802   DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );\r
55804   // Calculate ones:\r
55805   Wwords := SrcBmp.fWidth;\r
55806   Dst := DstBmp.ScanLine[ 0 ];\r
55807   BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );\r
55809   Inc( Dst, DstBmp.fWidth - 1 );\r
55811   // Rotating bits:\r
55812   for Y := 0 to SrcBmp.fHeight - 1 do\r
55813   begin\r
55814     Src := SrcBmp.ScanLine[ Y ];\r
55815     Dst1 := Dst;\r
55816     for X := Wwords downto 1 do\r
55817     begin\r
55818       Tmp := Src^;\r
55819       Inc( Src );\r
55820       Dst1^ := Tmp;\r
55821       Inc( PByte(Dst1), BytesPerDstLine );\r
55822     end;\r
55823     Dec( Dst );\r
55824   end;\r
55826 end;\r
55827 {$ENDIF ASM_VERSION}\r
55828 //[END _RotateBitmap16bit]\r
55830 //[PROCEDURE _RotateBitmap2432bit]\r
55831 {$IFDEF ASM_VERSION}\r
55832 procedure _RotateBitmap2432bit( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55833 asm\r
55834         PUSHAD\r
55835         XOR      EBX, EBX\r
55836         CALL     _PrepareBmp2Rotate\r
55838         SUB      ECX, pf24bit\r
55839         JNZ      @@10\r
55840         LEA      EBX, [EBX+EBX*2]\r
55841         JMP      @@11\r
55842 @@10:\r
55843         LEA      EBX, [EBX*4]\r
55844 @@11:   ADD      EDI, EBX // EDI = Dst\r
55846         MOV      EBX, EDX // EBX = BytesPerDstLine\r
55847         DEC      EBX\r
55848         DEC      EBX\r
55849         DEC      EBX\r
55851         MOV      EBP, ESI // EBP = SrcBmp\r
55853         XOR      EDX, EDX // Y = 0\r
55855 @@looY:\r
55856         PUSH     EDX\r
55857         PUSH     EDI\r
55858         PUSH     ECX // ECX = 0 if pf24bit (1 if pf32bit)\r
55860         MOV      EAX, EBP\r
55861         CALL     TBitmap.GetScanLine\r
55862         XCHG     ESI, EAX\r
55863         MOV      ECX, [EBP].TBitmap.fWidth\r
55864         POP      EAX\r
55865         PUSH     EAX\r
55867 @@looX:\r
55868         MOVSW\r
55869         MOVSB\r
55870         ADD      ESI, EAX\r
55871         ADD      EDI, EBX\r
55872         LOOP     @@looX\r
55874         POP      ECX\r
55875         POP      EDI\r
55876         POP      EDX\r
55878         DEC      EDI\r
55879         DEC      EDI\r
55880         DEC      EDI\r
55881         SUB      EDI, ECX\r
55882         INC      EDX\r
55883         CMP      EDX, [EBP].TBitmap.fHeight\r
55884         JL       @@looY\r
55886         POPAD\r
55887 end;\r
55888 {$ELSE ASM_VERSION} //Pascal\r
55889 procedure _RotateBitmap2432bit( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
55890 var X, Y, Wwords, BytesPerDstLine, IncW: Integer;\r
55891     Src, Dst, Dst1: PDWord;\r
55892     Tmp: DWord;\r
55893 begin\r
55895   DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );\r
55897   // Calculate ones:\r
55898   IncW := 4;\r
55899   if DstBmp.PixelFormat = pf24bit then\r
55900      IncW := 3;\r
55901   Wwords := SrcBmp.fWidth;\r
55902   Dst := DstBmp.ScanLine[ 0 ];\r
55903   BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );\r
55905   Inc( PByte(Dst), (DstBmp.fWidth - 1) * IncW );\r
55907   // Rotating bits:\r
55908   for Y := 0 to SrcBmp.fHeight - 1 do\r
55909   begin\r
55910     Src := SrcBmp.ScanLine[ Y ];\r
55911     Dst1 := Dst;\r
55912     for X := Wwords downto 1 do\r
55913     begin\r
55914       Tmp := Src^ and $FFFFFF;\r
55915       Inc( PByte(Src), IncW );\r
55916       Dst1^ := Dst1^ or Tmp;\r
55917       Inc( PByte(Dst1), BytesPerDstLine );\r
55918     end;\r
55919     Dec( PByte(Dst), IncW );\r
55920   end;\r
55922 end;\r
55923 {$ENDIF ASM_VERSION}\r
55924 //[END _RotateBitmap2432bit]\r
55926 type\r
55927   TRotateBmpRefs = packed record\r
55928     proc_RotateBitmapMono: procedure( var Dst: PBitmap; Src: PBitmap );\r
55929     proc_RotateBitmap4bit: procedure( var Dst: PBitmap; Src: PBitmap );\r
55930     proc_RotateBitmap8bit: procedure( var Dst: PBitmap; Src: PBitmap );\r
55931     proc_RotateBitmap16bit: procedure( var Dst: PBitmap; Src: PBitmap );\r
55932     proc_RotateBitmap2432bit: procedure( var Dst: PBitmap; Src: PBitmap );\r
55933   end;\r
55935 var\r
55936   RotateProcs: TRotateBmpRefs;\r
55938 //[PROCEDURE _RotateBitmapRight]\r
55939 {$IFDEF ASM_VERSION}\r
55940 procedure _RotateBitmapRight( SrcBmp: PBitmap );\r
55941 asm\r
55942         PUSH     EBX\r
55943         PUSH     EDI\r
55944         MOV      EBX, EAX\r
55945         CMP      [EBX].TBitmap.fHandleType, bmDIB\r
55946         JNZ      @@exit\r
55948         CALL     TBitmap.GetPixelFormat\r
55949         MOVZX    ECX, AL\r
55950         LOOP     @@not1bit\r
55951         MOV      EAX, [RotateProcs.proc_RotateBitmapMono]\r
55952 @@not1bit:\r
55953         LOOP     @@not4bit\r
55954         MOV      EAX, [RotateProcs.proc_RotateBitmap4bit]\r
55955 @@not4bit:\r
55956         LOOP     @@not8bit\r
55957         MOV      EAX, [RotateProcs.proc_RotateBitmap8bit]\r
55958 @@not8bit:\r
55959         LOOP     @@not15bit\r
55960         INC      ECX\r
55961 @@not15bit:\r
55962         LOOP     @@not16bit\r
55963         MOV      EAX, [RotateProcs.proc_RotateBitmap16bit]\r
55964 @@not16bit:\r
55965         LOOP     @@not24bit\r
55966         INC      ECX\r
55967 @@not24bit:\r
55968         LOOP     @@not32bit\r
55969         MOV      EAX, [RotateProcs.proc_RotateBitmap2432bit]\r
55970 @@not32bit:\r
55971         TEST     EAX, EAX\r
55972         JZ       @@exit\r
55974         PUSH     ECX\r
55975         XCHG     ECX, EAX\r
55976         MOV      EAX, ESP\r
55977         MOV      EDX, EBX\r
55978         CALL     ECX\r
55980         POP      EDI\r
55981         MOV      EAX, [EBX].TBitmap.fWidth\r
55982         CMP      EAX, [EDI].TBitmap.fHeight\r
55983         JGE      @@noCutHeight\r
55985         MOV      EDX, [EDI].TBitmap.fScanLineSize\r
55986         MUL      EDX\r
55987         MOV      [EDI].TBitmap.fDIBSize, EAX\r
55989         MOV      EDX, [EDI].TBitmap.fDIBHeader\r
55990         MOV      EDX, [EDX].TBitmapInfoHeader.biHeight\r
55991         TEST     EDX, EDX\r
55992         JL       @@noCorrectImg\r
55994         PUSH     EAX\r
55996         MOV      EDX, [EDI].TBitmap.fHeight\r
55997         DEC      EDX\r
55998         MOV      EAX, EDI\r
55999         CALL     TBitmap.GetScanLine\r
56000         PUSH     EAX\r
56002         MOV      EDX, [EBX].TBitmap.fWidth\r
56003         DEC      EDX\r
56004         MOV      EAX, EDI\r
56005         CALL     TBitmap.GetScanLine\r
56006         POP      EDX\r
56008         POP      ECX\r
56009         CALL     System.Move\r
56011 @@noCorrectImg:\r
56012         MOV      EAX, [EBX].TBitmap.fWidth\r
56013         MOV      [EDI].TBitmap.fHeight, EAX\r
56014         MOV      EDX, [EDI].TBitmap.fDIBHeader\r
56015         MOV      [EDX].TBitmapInfoHeader.biHeight, EAX\r
56017 @@noCutHeight:\r
56018         MOV      EAX, EBX\r
56019         CALL     TBitmap.ClearData\r
56021         XOR      EAX, EAX\r
56022         XCHG     EAX, [EDI].TBitmap.fDIBHeader\r
56023         XCHG     [EBX].TBitmap.fDIBHeader, EAX\r
56025         XCHG     EAX, [EDI].TBitmap.fDIBBits\r
56026         XCHG     [EBX].TBitmap.fDIBBits, EAX\r
56028         MOV      AL, [EDI].TBitmap.fDIBAutoFree\r
56029         MOV      [EBX].TBitmap.fDIBAutoFree, AL\r
56031         MOV      EAX, [EDI].TBitmap.fDIBSize\r
56032         MOV      [EBX].TBitmap.fDIBSize, EAX\r
56034         MOV      EAX, [EDI].TBitmap.fWidth\r
56035         MOV      [EBX].TBitmap.fWidth, EAX\r
56037         MOV      EAX, [EDI].TBitmap.fHeight\r
56038         MOV      [EBX].TBitmap.fHeight, EAX\r
56040         XCHG     EAX, EDI\r
56041         CALL     TObj.Free\r
56042 @@exit:\r
56043         POP      EDI\r
56044         POP      EBX\r
56045 end;\r
56046 {$ELSE ASM_VERSION} //Pascal\r
56047 procedure _RotateBitmapRight( SrcBmp: PBitmap );\r
56048 var DstBmp: PBitmap;\r
56049     RotateProc: procedure( var DstBmp: PBitmap; SrcBmp: PBitmap );\r
56050 begin\r
56051   if SrcBmp.fHandleType <> bmDIB then Exit;\r
56053   case SrcBmp.PixelFormat of\r
56054   pf1bit: RotateProc := RotateProcs.proc_RotateBitmapMono;\r
56055   pf4bit: RotateProc := RotateProcs.proc_RotateBitmap4bit;\r
56056   pf8bit: RotateProc := RotateProcs.proc_RotateBitmap8bit;\r
56057   pf15bit, pf16bit: RotateProc := RotateProcs.proc_RotateBitmap16bit;\r
56058   else RotateProc := RotateProcs.proc_RotateBitmap2432bit;\r
56059   end;\r
56061   if not Assigned( RotateProc ) then Exit;\r
56062   RotateProc( DstBmp, SrcBmp );\r
56064   if DstBmp.fHeight > SrcBmp.fWidth then\r
56065   begin\r
56066     DstBmp.fDIBSize := DstBmp.fScanLineSize * SrcBmp.fWidth;\r
56067     //if DWORD( DstBmp.ScanLine[ 0 ] ) > DWORD( DstBmp.ScanLine[ 1 ] ) then\r
56068     if DstBmp.fDIBHeader.bmiHeader.biHeight > 0 then\r
56069       Move( DstBmp.ScanLine[ SrcBmp.fWidth - 1 ]^, DstBmp.ScanLine[ DstBmp.fHeight - 1 ]^,\r
56070             DstBmp.fDIBSize );\r
56071     DstBmp.fHeight := SrcBmp.fWidth;\r
56072     DstBmp.fDIBHeader.bmiHeader.biHeight := DstBmp.fHeight;\r
56073   end;\r
56075   SrcBmp.ClearData;\r
56077   //SrcBmp.fNewPixelFormat := DstBmp.PixelFormat;\r
56078   SrcBmp.fDIBHeader := DstBmp.fDIBHeader;\r
56079   DstBmp.fDIBHeader := nil;\r
56081   SrcBmp.fDIBBits := DstBmp.fDIBBits;\r
56082   DstBmp.fDIBBits := nil;\r
56083   SrcBmp.fDIBAutoFree := DstBmp.fDIBAutoFree;\r
56085   SrcBmp.fDIBSize := DstBmp.fDIBSize;\r
56087   SrcBmp.fWidth := DstBmp.fWidth;\r
56088   SrcBmp.fHeight := DstBmp.fHeight;\r
56089   DstBmp.Free;\r
56090 end;\r
56091 {$ENDIF ASM_VERSION}\r
56092 //[END _RotateBitmapRight]\r
56094 //[procedure TBitmap.RotateRight]\r
56095 procedure TBitmap.RotateRight;\r
56096 const AllRotators: TRotateBmpRefs = (\r
56097         proc_RotateBitmapMono: _RotateBitmapMono;\r
56098         proc_RotateBitmap4bit: _RotateBitmap4bit;\r
56099         proc_RotateBitmap8bit: _RotateBitmap8bit;\r
56100         proc_RotateBitmap16bit: _RotateBitmap16bit;\r
56101         proc_RotateBitmap2432bit: _RotateBitmap2432bit );\r
56102 begin\r
56103   RotateProcs := AllRotators;\r
56104   _RotateBitmapRight( @Self );\r
56105 end;\r
56107 //[procedure _RotateBitmapLeft]\r
56108 procedure _RotateBitmapLeft( Src: PBitmap );\r
56109 begin\r
56110   _RotateBitmapRight( Src );\r
56111   _RotateBitmapRight( Src );\r
56112   _RotateBitmapRight( Src );\r
56113 end;\r
56115 //[procedure TBitmap.RotateLeft]\r
56116 procedure TBitmap.RotateLeft;\r
56117 begin\r
56118   RotateRight;\r
56119   _RotateBitmapRight( @Self );\r
56120   _RotateBitmapRight( @Self );\r
56121 end;\r
56123 //[procedure TBitmap.RotateLeftMono]\r
56124 procedure TBitmap.RotateLeftMono;\r
56125 begin\r
56126   if PixelFormat <> pf1bit then Exit;\r
56127   RotateProcs.proc_RotateBitmapMono := _RotateBitmapMono;\r
56128   _RotateBitmapRight( @Self );\r
56129 end;\r
56131 //[procedure TBitmap.RotateRightMono]\r
56132 procedure TBitmap.RotateRightMono;\r
56133 begin\r
56134   if PixelFormat <> pf1bit then Exit;\r
56135   RotateProcs.proc_RotateBitmapMono := _RotateBitmapMono;\r
56136   _RotateBitmapLeft( @Self );\r
56137 end;\r
56139 //[procedure TBitmap.RotateLeft16bit]\r
56140 procedure TBitmap.RotateLeft16bit;\r
56141 begin\r
56142   if PixelFormat <> pf16bit then Exit;\r
56143   RotateProcs.proc_RotateBitmap16bit := _RotateBitmap16bit;\r
56144   _RotateBitmapLeft( @Self );\r
56145 end;\r
56147 //[procedure TBitmap.RotateLeft4bit]\r
56148 procedure TBitmap.RotateLeft4bit;\r
56149 begin\r
56150   if PixelFormat <> pf4bit then Exit;\r
56151   RotateProcs.proc_RotateBitmap4bit := _RotateBitmap4bit;\r
56152   _RotateBitmapLeft( @Self );\r
56153 end;\r
56155 //[procedure TBitmap.RotateLeft8bit]\r
56156 procedure TBitmap.RotateLeft8bit;\r
56157 begin\r
56158   if PixelFormat <> pf8bit then Exit;\r
56159   RotateProcs.proc_RotateBitmap8bit := _RotateBitmap8bit;\r
56160   _RotateBitmapLeft( @Self );\r
56161 end;\r
56163 //[procedure TBitmap.RotateLeftTrueColor]\r
56164 procedure TBitmap.RotateLeftTrueColor;\r
56165 begin\r
56166   if not (PixelFormat in [ pf24bit, pf32bit ]) then Exit;\r
56167   RotateProcs.proc_RotateBitmap2432bit := _RotateBitmap2432bit;\r
56168   _RotateBitmapLeft( @Self );\r
56169 end;\r
56171 //[procedure TBitmap.RotateRight16bit]\r
56172 procedure TBitmap.RotateRight16bit;\r
56173 begin\r
56174   if PixelFormat <> pf16bit then Exit;\r
56175   RotateProcs.proc_RotateBitmap16bit := _RotateBitmap16bit;\r
56176   _RotateBitmapRight( @Self );\r
56177 end;\r
56179 //[procedure TBitmap.RotateRight4bit]\r
56180 procedure TBitmap.RotateRight4bit;\r
56181 begin\r
56182   if PixelFormat <> pf4bit then Exit;\r
56183   RotateProcs.proc_RotateBitmap4bit := _RotateBitmap4bit;\r
56184   _RotateBitmapRight( @Self );\r
56185 end;\r
56187 //[procedure TBitmap.RotateRight8bit]\r
56188 procedure TBitmap.RotateRight8bit;\r
56189 begin\r
56190   if PixelFormat <> pf8bit then Exit;\r
56191   RotateProcs.proc_RotateBitmap8bit := _RotateBitmap8bit;\r
56192   _RotateBitmapRight( @Self );\r
56193 end;\r
56195 //[procedure TBitmap.RotateRightTrueColor]\r
56196 procedure TBitmap.RotateRightTrueColor;\r
56197 begin\r
56198   if not (PixelFormat in [ pf24bit, pf32bit ]) then Exit;\r
56199   RotateProcs.proc_RotateBitmap2432bit := _RotateBitmap2432bit;\r
56200   _RotateBitmapRight( @Self );\r
56201 end;\r
56203 {$IFDEF ASM_VERSION}\r
56204 //[function TBitmap.GetPixels]\r
56205 function TBitmap.GetPixels(X, Y: Integer): TColor;\r
56206 asm\r
56207         PUSH     EBX\r
56208         MOV      EBX, EAX\r
56209         PUSH     ECX\r
56210         PUSH     EDX\r
56211         CALL     GetEmpty\r
56212         PUSHFD\r
56213         OR       EAX, -1\r
56214         POPFD\r
56215         JZ       @@exit\r
56217         CALL     StartDC\r
56218         PUSH     dword ptr [ESP+12]\r
56219         PUSH     dword ptr [ESP+12]\r
56220         PUSH     EAX\r
56221         CALL     Windows.GetPixel\r
56222         XCHG     EBX, EAX\r
56223         CALL     FinishDC\r
56224         XCHG     EAX, EBX\r
56225 @@exit:\r
56226         POP      EDX\r
56227         POP      EDX\r
56228         POP      EBX\r
56229 end;\r
56230 {$ELSE ASM_VERSION} //Pascal\r
56231 function TBitmap.GetPixels(X, Y: Integer): TColor;\r
56232 var DC: HDC;\r
56233     Save: THandle;\r
56234 begin\r
56235   Result := clNone;\r
56236   //if GetHandle = 0 then Exit;\r
56237   if Empty then Exit;\r
56238   fDetachCanvas( @Self );\r
56239   DC := CreateCompatibleDC( 0 );\r
56240   Save := SelectObject( DC, GetHandle );\r
56241   ASSERT( Save <> 0, 'Can not select bitmap to DC' );\r
56242   Result := Windows.GetPixel( DC, X, Y );\r
56243   SelectObject( DC, Save );\r
56244   DeleteDC( DC );\r
56245 end;\r
56246 {$ENDIF ASM_VERSION}\r
56248 {$IFDEF ASM_VERSION}\r
56249 //[procedure TBitmap.SetPixels]\r
56250 procedure TBitmap.SetPixels(X, Y: Integer; const Value: TColor);\r
56251 asm\r
56252         PUSH     EBX\r
56253         MOV      EBX, EAX\r
56254         PUSH     ECX\r
56255         PUSH     EDX\r
56256         CALL     GetEmpty\r
56257         JZ       @@exit\r
56259         CALL     StartDC\r
56260         MOV      EAX, Value\r
56261         CALL     Color2RGB\r
56262         PUSH     EAX\r
56263         PUSH     dword ptr [ESP+16]\r
56264         PUSH     dword ptr [ESP+16]\r
56265         PUSH     dword ptr [ESP+16]\r
56266         CALL     Windows.SetPixel\r
56267         CALL     FinishDC\r
56268 @@exit:\r
56269         POP      EDX\r
56270         POP      ECX\r
56271         POP      EBX\r
56272 end;\r
56273 {$ELSE ASM_VERSION} //Pascal\r
56274 procedure TBitmap.SetPixels(X, Y: Integer; const Value: TColor);\r
56275 var DC: HDC;\r
56276     Save: THandle;\r
56277 begin\r
56278   //if GetHandle = 0 then Exit;\r
56279   if Empty then Exit;\r
56280   fDetachCanvas( @Self );\r
56281   DC := CreateCompatibleDC( 0 );\r
56282   Save := SelectObject( DC, GetHandle );\r
56283   ASSERT( Save <> 0, 'Can not select bitmap to DC' );\r
56284   Windows.SetPixel( DC, X, Y, Color2RGB( Value ) );\r
56285   SelectObject( DC, Save );\r
56286   DeleteDC( DC );\r
56287 end;\r
56288 {$ENDIF ASM_VERSION}\r
56290 //[FUNCTION _GetDIBPixelsPalIdx]\r
56291 {$IFDEF ASM_VERSION}\r
56292 function _GetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer ): TColor;\r
56293 const szBIH = Sizeof(TBitmapInfoHeader);\r
56294 asm\r
56295         PUSH     EBX\r
56296         PUSH     EDI\r
56297         PUSH     EDX\r
56298         XCHG     EBX, EAX\r
56300         XCHG     EAX, EDX\r
56301         MOV      EDI, [EBX].TBitmap.fPixelsPerByteMask\r
56302         INC      EDI\r
56303         CDQ\r
56304         DIV      EDI\r
56305         DEC      EDI\r
56306         XCHG     ECX, EAX // EAX = Y, ECX = X div (Bmp.fPixeldPerByteMask+1)\r
56308         MOV      EDX, [EBX].TBitmap.fScanLineDelta\r
56309         IMUL     EDX\r
56311         ADD      EAX, [EBX].TBitmap.fScanLine0\r
56312         MOVZX    EAX, byte ptr[EAX+ECX]\r
56314         POP      EDX\r
56315         MOV      ECX, [EBX].TBitmap.fPixelsPerByteMask\r
56316         AND      EDX, ECX\r
56317         SUB      ECX, EDX\r
56319         PUSH     EAX\r
56320         MOV      EDI, [EBX].TBitmap.fDIBHeader\r
56321         MOVZX    EAX, [EDI].TBitmapInfoHeader.biBitCount\r
56322         MUL      ECX\r
56323         XCHG     ECX, EAX\r
56324         POP      EAX\r
56325         SHR      EAX, CL\r
56326         AND      EAX, [EBX].TBitmap.fPixelMask\r
56328         MOV      EAX, [EDI+szBIH+EAX*4]\r
56329         CALL     Color2RGBQuad\r
56331         POP      EDI\r
56332         POP      EBX\r
56333 end;\r
56334 {$ELSE ASM_VERSION} //Pascal\r
56335 function _GetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer ): TColor;\r
56336 var Pixel: Byte;\r
56337 begin\r
56338   Pixel := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta\r
56339              + (X div (Bmp.fPixelsPerByteMask + 1)) )^;\r
56340   Pixel := ( Pixel shr ( (Bmp.fPixelsPerByteMask - (X and Bmp.fPixelsPerByteMask))\r
56341                        * Bmp.fDIBHeader.bmiHeader.biBitCount ) )\r
56342            and Bmp.fPixelMask;\r
56343   Result := TColor( Color2RGBQuad( TColor( PRGBQuad( DWORD(@Bmp.fDIBHeader.bmiColors[ 0 ])\r
56344                            + Pixel * Sizeof( TRGBQuad ) )^ ) ) );\r
56345 end;\r
56346 {$ENDIF ASM_VERSION}\r
56347 //[END _GetDIBPixelsPalIdx]\r
56349 //[FUNCTION _GetDIBPixels16bit]\r
56350 {$IFDEF ASM_VERSION}\r
56351 function _GetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer ): TColor;\r
56352 asm\r
56353         PUSH     [EAX].TBitmap.fPixelMask\r
56354         PUSH     EDX // X\r
56355         PUSH     EAX\r
56356         MOV      EAX, [EAX].TBitmap.fScanLineDelta\r
56357         IMUL     ECX\r
56358         POP      EDX\r
56359         ADD      EAX, [EDX].TBitmap.fScanLine0\r
56360         POP      ECX\r
56361         MOVZX    EAX, word ptr [EAX+ECX*2]\r
56362         POP      EDX\r
56363         CMP      DL, 15\r
56364         JNE      @@16bit\r
56366         MOV      EDX, EAX\r
56367         SHR      EDX, 7\r
56368         SHL      EAX, 6\r
56369         MOV      DH, AH\r
56370         AND      DH, $F8\r
56371         SHL      EAX, 13\r
56372         JMP      @@1516bit\r
56374 @@16bit:\r
56375         MOV      DL, AH\r
56376         SHL      EAX, 5\r
56377         MOV      DH, AH\r
56378         SHL      EAX, 14\r
56379 @@1516bit:\r
56380         AND      EAX, $F80000\r
56381         OR       EAX, EDX\r
56382         AND      AX, $FCF8\r
56383 end;\r
56384 {$ELSE ASM_VERSION} //Pascal\r
56385 function _GetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer ): TColor;\r
56386 var Pixel: Word;\r
56387 begin\r
56388   Pixel := PWord( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X * 2 )^;\r
56389   if Bmp.fPixelMask = 15 then\r
56390     Result := (Pixel shr 7) and $F8 or (Pixel shl 6) and $F800\r
56391            or (Pixel shl 19) and $F80000\r
56392   else\r
56393     Result := (Pixel shr 8) and $F8 or (Pixel shl 5) and $FC00\r
56394            or (Pixel shl 19) and $F80000;\r
56395 end;\r
56396 {$ENDIF ASM_VERSION}\r
56397 //[END _GetDIBPixels16bit]\r
56399 //[FUNCTION _GetDIBPixelsTrueColor]\r
56400 {$IFDEF ASM_VERSION}\r
56401 function _GetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer ): TColor;\r
56402 asm\r
56403         PUSH     EBX\r
56404         XCHG     EBX, EAX\r
56405         PUSH     EDX\r
56406         MOV      EAX, [EBX].TBitmap.fScanLineDelta\r
56407         IMUL     ECX\r
56408         XCHG     ECX, EAX\r
56409         POP      EDX\r
56410         MOV      EAX, [EBX].TBitmap.fBytesPerPixel\r
56411         MUL      EDX\r
56412         ADD      EAX, [EBX].TBitmap.fScanLine0\r
56413         MOV      EAX, [EAX+ECX]\r
56414         AND      EAX, $FFFFFF\r
56415         CALL     Color2RGBQuad\r
56416         POP      EBX\r
56417 end;\r
56418 {$ELSE ASM_VERSION} //Pascal\r
56419 function _GetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer ): TColor;\r
56420 var Pixel: DWORD;\r
56421 begin\r
56422   Pixel := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta +\r
56423                    X * Bmp.fBytesPerPixel )^ and $FFFFFF;\r
56424   Result := TColor( Color2RGBQuad( TColor( Pixel ) ) );\r
56425 end;\r
56426 {$ENDIF ASM_VERSION}\r
56427 //[END _GetDIBPixelsTrueColor]\r
56429 {$IFDEF ASM_VERSION}\r
56430 //[function TBitmap.GetDIBPixels]\r
56431 function TBitmap.GetDIBPixels(X, Y: Integer): TColor;\r
56432 asm\r
56433         CMP      word ptr [EAX].fGetDIBPixels+2, 0\r
56434         JNZ      @@assigned\r
56436         // if not assigned, this preparing will be performed for first call:\r
56437         CMP      [EAX].fHandleType, bmDDB\r
56438         JZ       @@GetPixels\r
56440         PUSHAD\r
56441         MOV      EBX, EAX\r
56442         XOR      EDX, EDX\r
56443         CALL     GetScanLine\r
56444         MOV      [EBX].fScanLine0, EAX\r
56445         XOR      EDX, EDX\r
56446         INC      EDX\r
56447         MOV      EAX, EBX\r
56448         CALL     GetScanLine\r
56449         SUB      EAX, [EBX].fScanLine0\r
56450         MOV      [EBX].fScanLineDelta, EAX\r
56451         MOV      EAX, EBX\r
56452         CALL     GetPixelFormat\r
56453         MOVZX    ECX, AL\r
56454         MOV      DX, $0F00\r
56455         MOV      byte ptr [EBX].fBytesPerPixel, 4\r
56456         XOR      EAX, EAX\r
56457         LOOP     @@if4bit\r
56458         MOV      DX, $0107\r
56459         JMP      @@1bit4bit8bit\r
56460 @@if4bit:\r
56461         LOOP     @@if8bit\r
56462         INC      EDX // MOV      DX, $0F01\r
56463         JMP      @@1bit4bit8bit\r
56464 @@if8bit:\r
56465         LOOP     @@if15bit\r
56466         MOV      DH, $FF //MOV      DX, $FF00\r
56467 @@1bit4bit8bit:\r
56468         MOV      EAX, offset[_GetDIBPixelsPalIdx]\r
56469 @@if15bit:\r
56470         LOOP     @@if16bit\r
56471         //MOV      DH, $0F\r
56472         DEC      DH\r
56473         INC      ECX\r
56474 @@if16bit:\r
56475         LOOP     @@if24bit\r
56476         INC      DH\r
56477         MOV      EAX, offset[_GetDIBPixels16bit]\r
56478 @@if24bit:\r
56479         LOOP     @@if32bit\r
56480         DEC      [EBX].fBytesPerPixel\r
56481         INC      ECX\r
56482         DEC      EDX\r
56483 @@if32bit:\r
56484         LOOP     @@iffin\r
56485         INC      EDX\r
56486         MOV      EAX, offset[_GetDIBPixelsTrueColor]\r
56487 @@iffin:\r
56488         MOV      byte ptr [EBX].fPixelMask, DH\r
56489         MOV      byte ptr [EBX].fPixelsPerByteMask, DL\r
56490         MOV      [EBX].fGetDIBPixels, EAX\r
56491         TEST     EAX, EAX\r
56492         POPAD\r
56493 @@GetPixels:\r
56494         JZ       GetPixels\r
56496 @@assigned:\r
56497         JMP      [EAX].fGetDIBPixels\r
56498 end;\r
56499 {$ELSE ASM_VERSION} //Pascal\r
56500 function TBitmap.GetDIBPixels(X, Y: Integer): TColor;\r
56501 begin\r
56502   if not Assigned( fGetDIBPixels ) then\r
56503   begin\r
56504     if fHandleType = bmDIB then\r
56505     begin\r
56506       fScanLine0 := ScanLine[ 0 ];\r
56507       fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);\r
56508       case PixelFormat of\r
56509       pf1bit:\r
56510         begin\r
56511           fPixelMask := $01;\r
56512           fPixelsPerByteMask := 7;\r
56513           fGetDIBPixels := _GetDIBPixelsPalIdx;\r
56514         end;\r
56515       pf4bit:\r
56516         begin\r
56517           fPixelMask := $0F;\r
56518           fPixelsPerByteMask := 1;\r
56519           fGetDIBPixels := _GetDIBPixelsPalIdx;\r
56520         end;\r
56521       pf8bit:\r
56522         begin\r
56523           fPixelMask := $FF;\r
56524           fPixelsPerByteMask := 0;\r
56525           fGetDIBPixels := _GetDIBPixelsPalIdx;\r
56526         end;\r
56527       pf15bit:\r
56528         begin\r
56529           fPixelMask := 15;\r
56530           fGetDIBPixels := _GetDIBPixels16bit;\r
56531         end;\r
56532       pf16bit:\r
56533         begin\r
56534           fPixelMask := 16;\r
56535           fGetDIBPixels := _GetDIBPixels16bit;\r
56536         end;\r
56537       pf24bit:\r
56538         begin\r
56539           fPixelsPerByteMask := 0;\r
56540           fBytesPerPixel := 3;\r
56541           fGetDIBPixels := _GetDIBPixelsTrueColor;\r
56542         end;\r
56543       pf32bit:\r
56544         begin\r
56545           fPixelsPerByteMask := 1;\r
56546           fBytesPerPixel := 4;\r
56547           fGetDIBPixels := _GetDIBPixelsTrueColor;\r
56548         end;\r
56549       else;\r
56550       end;\r
56551     end;\r
56552     if not Assigned( fGetDIBPixels ) then\r
56553     begin\r
56554       Result := Pixels[ X, Y ];\r
56555       Exit;\r
56556     end;\r
56557   end;\r
56558   Result := fGetDIBPixels( @Self, X, Y );\r
56559 end;\r
56560 {$ENDIF ASM_VERSION}\r
56562 //[PROCEDURE _SetDIBPixels1bit]\r
56563 {$IFDEF ASM_VERSION}\r
56564 procedure _SetDIBPixels1bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );\r
56565 asm\r
56566         PUSH     EDX\r
56567         PUSH     [EAX].TBitmap.fScanLine0\r
56568         PUSH     ECX\r
56569         PUSH     [EAX].TBitmap.fScanLineDelta\r
56570         MOV      EAX, Value\r
56571         CALL     Color2RGB\r
56572         MOV      EDX, EAX\r
56573         SHR      EAX, 16\r
56574         ADD      AL, DL\r
56575         ADC      AL, DH\r
56576         CMP      EAX, 170\r
56577         SETGE    CL\r
56578         AND      ECX, 1\r
56579         SHL      ECX, 7\r
56580         POP      EAX\r
56581         POP      EDX\r
56582         IMUL     EDX\r
56583         POP      EDX\r
56584         ADD      EAX, EDX\r
56585         POP      EDX\r
56586         PUSH     ECX\r
56587         MOV      ECX, EDX\r
56588         SHR      EDX, 3\r
56589         ADD      EAX, EDX\r
56590         AND      ECX, 7\r
56591         MOV      DX, $FF7F\r
56592         SHR      EDX, CL\r
56593         AND      byte ptr [EAX], DL\r
56594         POP      EDX\r
56595         SHR      EDX, CL\r
56596         OR       byte ptr [EAX], DL\r
56597 end;\r
56598 {$ELSE ASM_VERSION} //Pascal\r
56599 procedure _SetDIBPixels1bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );\r
56600 var Pixel: Byte;\r
56601     Pos: PByte;\r
56602     Shf: Integer;\r
56603 begin\r
56604   Value := Color2RGB( Value );\r
56605   if ((Value shr 16) and $FF) + ((Value shr 8) and $FF) + (Value and $FF)\r
56606      < 255 * 3 div 2 then Pixel := 0 else Pixel := $80;\r
56607   Pos := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X div 8 );\r
56608   Shf := X and 7;\r
56609   Pos^ := Pos^ and ($FF7F shr Shf) or (Pixel shr Shf);\r
56610 end;\r
56611 {$ENDIF ASM_VERSION}\r
56612 //[END _SetDIBPixels1bit]\r
56614 //[PROCEDURE _SetDIBPixelsPalIdx]\r
56615 {$IFDEF ASM_VERSION}\r
56616 procedure _SetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer; Value: TColor );\r
56617 asm\r
56618         XCHG     EAX, EBP\r
56619         PUSH     EDX // -> X\r
56620         PUSH     ECX // -> Y\r
56621         MOV      ECX, [EBP].TBitmap.fPixelsPerByteMask\r
56622         INC      ECX\r
56623         XCHG     EAX, EDX\r
56624         CDQ\r
56625         DIV      ECX\r
56626         XCHG     ECX, EAX // ECX = X div (fPixelsPerByteMask+1)\r
56627         POP      EAX // <- Y\r
56628         MOV      EDX, [EBP].TBitmap.fScanLineDelta\r
56629         IMUL     EDX\r
56630         ADD      ECX, EAX\r
56631         ADD      ECX, [EBP].TBitmap.fScanLine0 // ECX = Pos\r
56632         PUSH     ECX // -> Pos\r
56634         MOV      EDX, [ESP+16] // Value\r
56635         MOV      EAX, EBP\r
56636         CALL     TBitmap.DIBPalNearestEntry // EAX = Pixel\r
56638         POP      ECX // <- Pos\r
56639         POP      EDX // <- X\r
56641         PUSH     EAX // -> Pixel\r
56643         MOV      EAX, [EBP].TBitmap.fPixelsPerByteMask\r
56644         AND      EDX, EAX\r
56645         SUB      EAX, EDX\r
56646         MOV      EDX, [EBP].TBitmap.fDIBHeader\r
56647         MOVZX    EDX, [EDX].TBitmapInfoHeader.biBitCount\r
56648         MUL      EDX // EAX = Shf\r
56650         XCHG     ECX, EAX // ECX = Shf, EAX = Pos\r
56651         MOV      EDX, [EBP].TBitmap.fPixelMask\r
56652         SHL      EDX, CL\r
56653         NOT      EDX\r
56654         AND      byte ptr [EAX], DL\r
56656         POP      EDX // <- Pixel\r
56657         SHL      EDX, CL\r
56658         OR       byte ptr [EAX], DL\r
56659 end;\r
56660 {$ELSE ASM_VERSION} //Pascal\r
56661 procedure _SetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer; Value: TColor );\r
56662 var Pixel: Byte;\r
56663     Pos: PByte;\r
56664     Shf: Integer;\r
56665 begin\r
56666   Pixel := Bmp.DIBPalNearestEntry( Value );\r
56667   Pos := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta\r
56668                 + X div (Bmp.fPixelsPerByteMask + 1) );\r
56669   Shf := (Bmp.fPixelsPerByteMask - (X and Bmp.fPixelsPerByteMask))\r
56670          * Bmp.fDIBHeader.bmiHeader.biBitCount;\r
56671   Pos^ := Pos^ and not (Bmp.fPixelMask shl Shf) or (Pixel shl Shf);\r
56672 end;\r
56673 {$ENDIF ASM_VERSION}\r
56674 //[END _SetDIBPixelsPalIdx]\r
56676 //[PROCEDURE _SetDIBPixels16bit]\r
56677 {$IFDEF ASM_VERSION}\r
56678 procedure _SetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );\r
56679 asm\r
56680         ADD      EDX, EDX\r
56681         ADD      EDX, [EAX].TBitmap.fScanLine0\r
56682         PUSH     EDX // -> X*2 + Bmp.fScanLine0\r
56683         PUSH     [EAX].TBitmap.fPixelMask\r
56684         MOV      EAX, [EAX].TBitmap.fScanLineDelta\r
56685         IMUL     ECX\r
56686         PUSH     EAX  // -> Y* Bmp.fScanLineDelta\r
56687         MOV      EAX, Value\r
56688         CALL     Color2RGB\r
56689         POP      EBP  // <- Y* Bmp.fScanLineDelta\r
56690         POP      EDX\r
56691         XOR      ECX, ECX\r
56692         SUB      DL, 16\r
56693         JZ       @@16bit\r
56695         MOV      CH, AL\r
56696         SHR      CH, 1\r
56697         SHR      EAX, 6\r
56698         MOV      EDX, EAX\r
56699         AND      DX, $3E0\r
56700         SHR      EAX, 13\r
56701         JMP      @@1516\r
56703 @@16bit:\r
56704         {$IFDEF PARANOIA}\r
56705         DB $24, $F8\r
56706         {$ELSE}\r
56707         AND      AL, $F8\r
56708         {$ENDIF}\r
56709         MOV      CH, AL\r
56710         SHR      EAX, 5\r
56711         MOV      EDX, EAX\r
56712         AND      DX, $7E0\r
56713         SHR      EAX, 14\r
56715 @@1516:\r
56716         MOV      AH, CH\r
56717         AND      AX, $FC1F\r
56718         OR       AX, DX\r
56720         POP      EDX\r
56721         MOV      [EBP+EDX], AX\r
56722 end;\r
56723 {$ELSE ASM_VERSION} //Pascal\r
56724 procedure _SetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );\r
56725 var RGB16: Word;\r
56726     Pos: PWord;\r
56727 begin\r
56728   Value := Color2RGB( Value );\r
56729   if Bmp.fPixelMask = 15 then\r
56730     RGB16 := (Value shr 19) and $001F or (Value shr 6) and $03E0\r
56731           or (Value shl 7) and $7C00\r
56732   else\r
56733     RGB16 := (Value shr 19) and $001F or (Value shr 5) and $07E0\r
56734           or (Value shl 8) and $F800;\r
56735   Pos := PWord( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X * 2 );\r
56736   Pos^ := RGB16;\r
56737 end;\r
56738 {$ENDIF ASM_VERSION}\r
56739 //[END _SetDIBPixels16bit]\r
56741 //[PROCEDURE _SetDIBPixelsTrueColor]\r
56742 {$IFDEF ASM_VERSION}\r
56743 procedure _SetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer; Value: TColor );\r
56744 asm\r
56745         PUSH     [EAX].TBitmap.fScanLineDelta\r
56746         PUSH     [EAX].TBitmap.fScanLine0\r
56747         MOV      EAX, [EAX].TBitmap.fBytesPerPixel\r
56748         MUL      EDX\r
56749         POP      EDX\r
56750         ADD      EDX, EAX\r
56751         POP      EAX\r
56752         PUSH     EDX\r
56753         IMUL     ECX\r
56754         POP      EDX\r
56755         ADD      EDX, EAX\r
56756         PUSH     EDX\r
56757         MOV      EAX, Value\r
56758         CALL     Color2RGBQuad\r
56759         POP      EDX\r
56760         AND      dword ptr [EDX], $FF000000\r
56761         OR       [EDX], EAX\r
56762 end;\r
56763 {$ELSE ASM_VERSION} //Pascal\r
56764 procedure _SetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer; Value: TColor );\r
56765 var RGB: TRGBQuad;\r
56766     Pos: PDWord;\r
56767 begin\r
56768   //Value := Color2RGB( Value );\r
56769   RGB := Color2RGBQuad( Value );\r
56770   Pos := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta\r
56771                  + X * Bmp.fBytesPerPixel );\r
56772   Pos^ := Pos^ and $FF000000 or DWORD(RGB);\r
56773 end;\r
56774 {$ENDIF ASM_VERSION}\r
56775 //[END _SetDIBPixelsTrueColor]\r
56777 {$IFDEF ASM_VERSION}\r
56778 //[procedure TBitmap.SetDIBPixels]\r
56779 procedure TBitmap.SetDIBPixels(X, Y: Integer; const Value: TColor);\r
56780 asm\r
56781         CMP      word ptr [EAX].fSetDIBPixels+2, 0\r
56782         JNZ      @@assigned\r
56783         PUSHAD\r
56784         MOV      EBX, EAX\r
56785         XOR      EDX, EDX\r
56786         CMP      [EBX].fHandleType, DL // bmDIB = 0\r
56787         JNE      @@ddb\r
56788         CALL     GetScanLine\r
56789         MOV      [EBX].fScanLine0, EAX\r
56790         XOR      EDX, EDX\r
56791         INC      EDX\r
56792         MOV      EAX, EBX\r
56793         CALL     GetScanLine\r
56794         SUB      EAX, [EBX].fScanLine0\r
56795         MOV      [EBX].fScanLineDelta, EAX\r
56796         MOV      EAX, EBX\r
56797         CALL     GetPixelFormat\r
56798         MOVZX    ECX, AL\r
56799         MOV      DX, $0F01\r
56800         MOV      EAX, offset[_SetDIBPixelsPalIdx]\r
56801         MOV      byte ptr [EBX].fBytesPerPixel, 4\r
56802         LOOP     @@if4bit\r
56803         MOV      EAX, offset[_SetDIBPixels1bit]\r
56804 @@if4bit:\r
56805         LOOP     @@if8bit\r
56806 @@if8bit:\r
56807         LOOP     @@if15bit\r
56808         DEC      DL\r
56809         MOV      DH, $FF\r
56810 @@if15bit:\r
56811         LOOP     @@if16bit\r
56812         DEC      DH\r
56813         INC      ECX\r
56814 @@if16bit:\r
56815         LOOP     @@if24bit\r
56816         INC      DH\r
56817         MOV      EAX, offset[_SetDIBPixels16bit]\r
56818 @@if24bit:\r
56819         LOOP     @@if32bit\r
56820         DEC      EDX\r
56821         DEC      [EBX].fBytesPerPixel\r
56822         INC      ECX\r
56823 @@if32bit:\r
56824         LOOP     @@ifend\r
56825         INC      EDX\r
56826         MOV      EAX, offset[_SetDIBPixelsTrueColor]\r
56827 @@ifend:\r
56828         MOV      byte ptr [EBX].fPixelMask, DH\r
56829         MOV      byte ptr [EBX].fPixelsPerByteMask, DL\r
56830         MOV      [EBX].fSetDIBPixels, EAX\r
56831         TEST     EAX, EAX\r
56832 @@ddb:\r
56833         POPAD\r
56834         JNZ      @@assigned\r
56835         PUSH     Value\r
56836         CALL     SetPixels\r
56837         JMP      @@exit\r
56838 @@assigned:\r
56839         PUSH     Value\r
56840         CALL     [EAX].fSetDIBPixels\r
56841 @@exit:\r
56842 end;\r
56843 {$ELSE ASM_VERSION} //Pascal\r
56844 procedure TBitmap.SetDIBPixels(X, Y: Integer; const Value: TColor);\r
56845 begin\r
56846   if not Assigned( fSetDIBPixels ) then\r
56847   begin\r
56848     if fHandleType = bmDIB then\r
56849     begin\r
56850       fScanLine0 := ScanLine[ 0 ];\r
56851       fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);\r
56852       case PixelFormat of\r
56853       pf1bit:\r
56854         begin\r
56855           //fPixelMask := $01;\r
56856           //fPixelsPerByteMask := 7;\r
56857           fSetDIBPixels := _SetDIBPixels1bit;\r
56858         end;\r
56859       pf4bit:\r
56860         begin\r
56861           fPixelMask := $0F;\r
56862           fPixelsPerByteMask := 1;\r
56863           fSetDIBPixels := _SetDIBPixelsPalIdx;\r
56864         end;\r
56865       pf8bit:\r
56866         begin\r
56867           fPixelMask := $FF;\r
56868           fPixelsPerByteMask := 0;\r
56869           fSetDIBPixels := _SetDIBPixelsPalIdx;\r
56870         end;\r
56871       pf15bit:\r
56872         begin\r
56873           fPixelMask := 15;\r
56874           fSetDIBPixels := _SetDIBPixels16bit;\r
56875         end;\r
56876       pf16bit:\r
56877         begin\r
56878           fPixelMask := 16;\r
56879           fSetDIBPixels := _SetDIBPixels16bit;\r
56880         end;\r
56881       pf24bit:\r
56882         begin\r
56883           fPixelsPerByteMask := 0;\r
56884           fBytesPerPixel := 3;\r
56885           fSetDIBPixels := _SetDIBPixelsTrueColor;\r
56886         end;\r
56887       pf32bit:\r
56888         begin\r
56889           fPixelsPerByteMask := 1;\r
56890           fBytesPerPixel := 4;\r
56891           fSetDIBPixels := _SetDIBPixelsTrueColor;\r
56892         end;\r
56893       else;\r
56894       end;\r
56895     end;\r
56896     if not Assigned( fSetDIBPixels ) then\r
56897     begin\r
56898       Pixels[ X, Y ] := Value;\r
56899       Exit;\r
56900     end;\r
56901   end;\r
56902   fSetDIBPixels( @Self, X, Y, Value );\r
56903 end;\r
56904 {$ENDIF ASM_VERSION}\r
56906 {$IFDEF ASM_VERSION}\r
56907 //[procedure TBitmap.FlipVertical]\r
56908 procedure TBitmap.FlipVertical;\r
56909 asm\r
56910         PUSH     EBX\r
56911         MOV      EBX, EAX\r
56912         MOV      ECX, [EBX].fHandle\r
56913         JECXZ    @@noHandle\r
56915         CALL     StartDC\r
56916         PUSH     SrcCopy\r
56917         MOV      EDX, [EBX].fHeight\r
56918         PUSH     EDX\r
56919         MOV      ECX, [EBX].fWidth\r
56920         PUSH     ECX\r
56921         PUSH     0\r
56922         PUSH     0\r
56923         PUSH     EAX\r
56924         NEG      EDX\r
56925         PUSH     EDX\r
56926         PUSH     ECX\r
56927         NEG      EDX\r
56928         DEC      EDX\r
56929         PUSH     EDX\r
56930         PUSH     0\r
56931         PUSH     EAX\r
56932         CALL     StretchBlt\r
56933         CALL     FinishDC\r
56934         POP      EBX\r
56935         RET\r
56937 @@noHandle:\r
56938         MOV      ECX, [EBX].fDIBBits\r
56939         JECXZ    @@exit\r
56941         PUSHAD   //----------------------------------------\\r
56942         XOR      EBP, EBP // Y = 0\r
56943         //+++++++++++++++++++++++++++ provide fScanLineSize\r
56944         MOV      EAX, EBX\r
56945         MOV      EDX, EBP\r
56946         CALL     GetScanLine //\r
56947         SUB      ESP, [EBX].fScanLineSize\r
56949 @@loo:  LEA      EAX, [EBP*2]\r
56950         CMP      EAX, [EBX].fHeight\r
56951         JG       @@finloo\r
56953         MOV      EAX, EBX\r
56954         MOV      EDX, EBP\r
56955         CALL     GetScanLine\r
56956         MOV      ESI, EAX // ESI = ScanLine[ Y ]\r
56957         MOV      EDX, ESP\r
56958         MOV      ECX, [EBX].fScanLineSize\r
56959         PUSH     ECX\r
56960         CALL     System.Move\r
56962         MOV      EAX, EBX\r
56963         MOV      EDX, [EBX].fHeight\r
56964         SUB      EDX, EBP\r
56965         DEC      EDX\r
56966         CALL     GetScanLine\r
56967         MOV      EDI, EAX\r
56968         MOV      EDX, ESI\r
56969         POP      ECX\r
56970         PUSH     ECX\r
56971         CALL     System.Move\r
56973         POP      ECX\r
56974         MOV      EAX, ESP\r
56975         MOV      EDX, EDI\r
56976         CALL     System.Move\r
56978         INC      EBP\r
56979         JMP      @@loo\r
56981 @@finloo:\r
56982         ADD      ESP, [EBX].fScanLineSize\r
56983         POPAD\r
56984 @@exit:\r
56985         POP      EBX\r
56986 end;\r
56987 {$ELSE ASM_VERSION} //Pascal\r
56988 procedure TBitmap.FlipVertical;\r
56989 var DC: HDC;\r
56990     Save: THandle;\r
56991     TmpScan: PByte;\r
56992     Y: Integer;\r
56993 begin\r
56994   if fHandle <> 0 then\r
56995   begin\r
56996     fDetachCanvas( @Self );\r
56997     DC := CreateCompatibleDC( 0 );\r
56998     Save := SelectObject( DC, fHandle );\r
56999     StretchBlt( DC, 0, fHeight - 1, fWidth, -fHeight, DC, 0, 0, fWidth, fHeight, SRCCOPY );\r
57000     SelectObject( DC, Save );\r
57001     DeleteDC( DC );\r
57002   end\r
57003      else\r
57004   if fDIBBits <> nil then\r
57005   begin\r
57006     GetMem( TmpScan, ScanLineSize );\r
57007     for Y := 0 to fHeight div 2 do\r
57008     begin\r
57009       Move( ScanLine[ Y ]^, TmpScan^, fScanLineSize );\r
57010       Move( ScanLine[ fHeight - Y - 1 ]^, ScanLine[ Y ]^, fScanLineSize );\r
57011       Move( TmpScan^, ScanLine[ fHeight - Y - 1 ]^, fScanLineSize );\r
57012     end;\r
57013   end;\r
57014 end;\r
57015 {$ENDIF ASM_VERSION}\r
57017 {$IFDEF ASM_VERSION}\r
57018 //[procedure TBitmap.FlipHorizontal]\r
57019 procedure TBitmap.FlipHorizontal;\r
57020 asm\r
57021         PUSH     EBX\r
57022         MOV      EBX, EAX\r
57023         CALL     GetHandle\r
57024         TEST     EAX, EAX\r
57025         JZ       @@exit\r
57027         CALL     StartDC\r
57028         PUSH     SrcCopy\r
57029         MOV      EDX, [EBX].fHeight\r
57030         PUSH     EDX\r
57031         MOV      ECX, [EBX].fWidth\r
57032         PUSH     ECX\r
57033         PUSH     0\r
57034         PUSH     0\r
57035         PUSH     EAX\r
57036         PUSH     EDX\r
57037         NEG      ECX\r
57038         PUSH     ECX\r
57039         PUSH     0\r
57040         NEG      ECX\r
57041         DEC      ECX\r
57042         PUSH     ECX\r
57043         PUSH     EAX\r
57044         CALL     StretchBlt\r
57045         CALL     FinishDC\r
57046 @@exit:\r
57047         POP      EBX\r
57048 end;\r
57049 {$ELSE ASM_VERSION} //Pascal\r
57050 procedure TBitmap.FlipHorizontal;\r
57051 var DC: HDC;\r
57052     Save: THandle;\r
57053 begin\r
57054   if GetHandle <> 0 then\r
57055   begin\r
57056     fDetachCanvas( @Self );\r
57057     DC := CreateCompatibleDC( 0 );\r
57058     Save := SelectObject( DC, fHandle );\r
57059     StretchBlt( DC, fWidth - 1, 0, -fWidth, fHeight, DC, 0, 0, fWidth, fHeight, SRCCOPY );\r
57060     SelectObject( DC, Save );\r
57061     DeleteDC( DC );\r
57062   end;\r
57063 end;\r
57064 {$ENDIF ASM_VERSION}\r
57066 {$IFDEF ASM_VERSION}\r
57067 //[procedure TBitmap.CopyRect]\r
57068 procedure TBitmap.CopyRect(const DstRect: TRect; SrcBmp: PBitmap;\r
57069   const SrcRect: TRect);\r
57070 asm\r
57071         PUSHAD\r
57072         MOV      EBX, EAX\r
57073         MOV      ESI, ECX\r
57074         MOV      EDI, EDX\r
57075         CALL     GetHandle\r
57076         TEST     EAX, EAX\r
57077         JZ       @@exit\r
57078         MOV      EAX, ESI\r
57079         CALL     GetHandle\r
57080         TEST     EAX, EAX\r
57081         JZ       @@exit\r
57082         CALL     StartDC\r
57083         XCHG     EBX, ESI\r
57084         CMP      EBX, ESI\r
57085         JNZ      @@diff1\r
57086         PUSH     EAX\r
57087         PUSH     0\r
57088         JMP      @@nodiff1\r
57089 @@diff1:\r
57090         CALL     StartDC\r
57091 @@nodiff1:\r
57092         PUSH     SrcCopy                  // ->\r
57093         MOV      EBP, [SrcRect]\r
57094         MOV      EAX, [EBP].TRect.Bottom\r
57095         MOV      EDX, [EBP].TRect.Top\r
57096         SUB      EAX, EDX\r
57097         PUSH     EAX                      // ->\r
57098         MOV      EAX, [EBP].TRect.Right\r
57099         MOV      ECX, [EBP].TRect.Left\r
57100         SUB      EAX, ECX\r
57101         PUSH     EAX                      // ->\r
57102         PUSH     EDX                      // ->\r
57103         PUSH     ECX                      // ->\r
57104         PUSH     dword ptr [ESP+24]       // -> DCsrc\r
57105         MOV      EAX, [EDI].TRect.Bottom\r
57106         MOV      EDX, [EDI].TRect.Top\r
57107         SUB      EAX, EDX\r
57108         PUSH     EAX                      // ->\r
57109         MOV      EAX, [EDI].TRect.Right\r
57110         MOV      ECX, [EDI].TRect.Left\r
57111         SUB      EAX, ECX\r
57112         PUSH     EAX                      // ->\r
57113         PUSH     EDX                      // ->\r
57114         PUSH     ECX                      // ->\r
57115         PUSH     dword ptr [ESP+13*4]     // -> DCdst\r
57116         CALL     StretchBlt\r
57117         CMP      EBX, ESI\r
57118         JNE      @@diff2\r
57119         POP      ECX\r
57120         POP      ECX\r
57121         JMP      @@nodiff2\r
57122 @@diff2:\r
57123         CALL     FinishDC\r
57124 @@nodiff2:\r
57125         CALL     FinishDC\r
57126 @@exit:\r
57127         POPAD\r
57128 end;\r
57129 {$ELSE ASM_VERSION} //Pascal\r
57130 procedure TBitmap.CopyRect(const DstRect: TRect; SrcBmp: PBitmap;\r
57131   const SrcRect: TRect);\r
57132 var DCsrc, DCdst: HDC;\r
57133     SaveSrc, SaveDst: THandle;\r
57134 begin\r
57135   if (GetHandle = 0) or (SrcBmp.GetHandle = 0) then Exit;\r
57136   fDetachCanvas( @Self );\r
57137   fDetachCanvas( SrcBmp );\r
57138   DCsrc := CreateCompatibleDC( 0 );\r
57139   SaveSrc := SelectObject( DCsrc, SrcBmp.fHandle );\r
57140   DCdst := DCsrc;\r
57141   SaveDst := 0;\r
57142   if SrcBmp <> @Self then\r
57143   begin\r
57144     DCdst := CreateCompatibleDC( 0 );\r
57145     SaveDst := SelectObject( DCdst, fHandle );\r
57146   end;\r
57147   StretchBlt( DCdst, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left,\r
57148               DstRect.Bottom - DstRect.Top, DCsrc, SrcRect.Left, SrcRect.Top,\r
57149               SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top,\r
57150               SRCCOPY );\r
57151   if SrcBmp <> @Self then\r
57152   begin\r
57153     SelectObject( DCdst, SaveDst );\r
57154     DeleteDC( DCdst );\r
57155   end;\r
57156   SelectObject( DCsrc, SaveSrc );\r
57157   DeleteDC( DCsrc );\r
57158 end;\r
57159 {$ENDIF ASM_VERSION}\r
57162 //[function TBitmap.CopyToClipboard]\r
57163 function TBitmap.CopyToClipboard: Boolean;\r
57164 var DibMem: PChar;\r
57165     HdrSize: Integer;\r
57166     Gbl: HGlobal;\r
57167 begin\r
57168   Result := FALSE;\r
57169   if Applet = nil then Exit;\r
57170   if not OpenClipboard( Applet.GetWindowHandle ) then\r
57171     Exit;\r
57172   if EmptyClipboard then\r
57173   begin\r
57174     HandleType := bmDIB;\r
57175     HdrSize := sizeof( TBitmapInfoHeader );\r
57176     if fDIBHeader.bmiHeader.biBitCount <= 8 then\r
57177        Inc( HdrSize,\r
57178        (1 shl fDIBHeader.bmiHeader.biBitCount) * Sizeof( TRGBQuad ) );\r
57179     Gbl := GlobalAlloc( GMEM_MOVEABLE, HdrSize + fDIBSize );\r
57180     DibMem := GlobalLock( Gbl );\r
57181     if DibMem <> nil then\r
57182     begin\r
57183       Move( fDIBHeader^, DibMem^, HdrSize );\r
57184       Move( fDIBBits^, Pointer( Integer( DibMem ) + HdrSize )^, fDIBSize );\r
57185       if not GlobalUnlock( Gbl ) and (GetLastError = NO_ERROR) then\r
57186       begin\r
57187         Result := SetClipboardData( CF_DIB, Gbl ) <> 0;\r
57188       end;\r
57189     end;\r
57190   end;\r
57191   CloseClipboard;\r
57192 end;\r
57194 //[function TBitmap.PasteFromClipboard]\r
57195 function TBitmap.PasteFromClipboard: Boolean;\r
57196 var Gbl: HGlobal;\r
57197     //DIBPtr: PChar;\r
57198     Size {, HdrSize}: Integer;\r
57199     Mem: PChar;\r
57200     Strm: PStream;\r
57201 begin\r
57202   Result := FALSE;\r
57203   if Applet = nil then Exit;\r
57204   if not OpenClipboard( Applet.GetWindowHandle ) then Exit;\r
57205   TRY\r
57206   if IsClipboardFormatAvailable( CF_DIB ) then\r
57207   begin\r
57208     Gbl := GetClipboardData( CF_DIB );\r
57209     if Gbl <> 0 then\r
57210     begin\r
57211       Size := GlobalSize( Gbl );\r
57212       Mem := GlobalLock( Gbl );\r
57213       TRY\r
57214       if (Size > 0) and (Mem <> nil) then\r
57215       begin\r
57216         Strm := NewMemoryStream;\r
57217         Strm.Write( Mem^, Size );\r
57218         Strm.Position := 0;\r
57219         LoadFromStreamEx( Strm );\r
57220         Strm.Free;\r
57221         Result := not Empty;\r
57222       end;\r
57223       FINALLY\r
57224       GlobalUnlock( Gbl );\r
57225       END;\r
57226     end;\r
57227   end;\r
57228   FINALLY\r
57229   CloseClipboard;\r
57230   END;\r
57231 end;\r
57241 ///////////////////////////////////////////////////////////////////////\r
57242 //\r
57243 //\r
57244 //                             I  C  O  N\r
57245 //\r
57246 //\r
57247 ///////////////////////////////////////////////////////////////////////\r
57249 { -- icon -- }\r
57251 //[function NewIcon]\r
57252 function NewIcon: PIcon;\r
57253 begin\r
57254   {-}\r
57255   New( Result, Create );\r
57256   {+}{++}(*Result := TIcon.Create;*){--}\r
57257   Result.FSize := 32;\r
57258 end;\r
57260 { TIcon }\r
57262 //[PROCEDURE asmIconEmpty]\r
57263 {$IFDEF ASM_VERSION}\r
57264 procedure asmIconEmpty( Icon: PIcon );\r
57265 asm\r
57266         CMP      [EAX].TIcon.fHandle, 0\r
57267 end;\r
57268 {$ENDIF ASM_VERSION}\r
57269 //[END asmIconEmpty]\r
57271 {$IFDEF ASM_VERSION}\r
57272 //[procedure TIcon.Clear]\r
57273 procedure TIcon.Clear;\r
57274 asm     //cmd    //opd\r
57275         XOR      ECX, ECX\r
57276         XCHG     ECX, [EAX].fHandle\r
57277         JECXZ    @@1\r
57278         CMP      [EAX].fShareIcon, 0\r
57279         JNZ      @@1\r
57280         PUSH     EAX\r
57281         PUSH     ECX\r
57282         CALL     DestroyIcon\r
57283         POP      EAX\r
57284 @@1:    MOV      [EAX].fShareIcon, 0\r
57285 end;\r
57286 {$ELSE ASM_VERSION} //Pascal\r
57287 procedure TIcon.Clear;\r
57288 begin\r
57289   if fHandle <> 0 then\r
57290   begin\r
57291     if not FShareIcon then\r
57292       //DeleteObject( fHandle );\r
57293       DestroyIcon( fHandle );\r
57294     fHandle := 0;\r
57295   end;\r
57296   fShareIcon := False;\r
57297 end;\r
57298 {$ENDIF ASM_VERSION}\r
57300 {$IFDEF ASM_VERSION}\r
57301 //[function TIcon.Convert2Bitmap]\r
57302 function TIcon.Convert2Bitmap(TranColor: TColor): HBitmap;\r
57303 asm     //cmd    //opd\r
57304         PUSH     EBX\r
57305         PUSH     ESI\r
57306         PUSH     EDI\r
57307         PUSH     EBP\r
57308         MOV      EBX, EAX\r
57309         MOV      EBP, EDX\r
57310         XOR      EDX, EDX\r
57311         CALL     asmIconEmpty\r
57312         JZ       @@ret_0\r
57313         PUSH     0\r
57314         CALL     GetDC\r
57315         PUSH     EAX //> DC0\r
57316         PUSH     EAX\r
57317         CALL     CreateCompatibleDC\r
57318         XCHG     EDI, EAX\r
57319         MOV      EDX, [EBX].fSize\r
57321         POP      EAX\r
57322         PUSH     EAX\r
57323         PUSH     EDX //>Bottom\r
57324         PUSH     EDX //>Right\r
57325         PUSH     0   //>Top\r
57326         PUSH     0   //>Left\r
57328         PUSH     EDX\r
57329         PUSH     EDX\r
57330         PUSH     EAX\r
57331         CALL     CreateCompatibleBitmap\r
57332         XCHG     EBP, EAX\r
57334         CALL     Color2RGB\r
57335         PUSH     EAX\r
57337         PUSH     EBP\r
57338         PUSH     EDI\r
57339         CALL     SelectObject\r
57340         XCHG     ESI, EAX\r
57342         CALL     CreateSolidBrush\r
57344         MOV      EDX, ESP\r
57345         PUSH     EAX\r
57346         PUSH     EAX\r
57347         PUSH     EDX\r
57348         PUSH     EDI\r
57349         CALL     Windows.FillRect\r
57350         CALL     DeleteObject\r
57352         XCHG     EAX, EBX\r
57353         MOV      EDX, EDI\r
57354         XOR      ECX, ECX\r
57355         PUSH     ECX\r
57356         CALL     Draw\r
57358         PUSH     EDI\r
57359         PUSH     ESI\r
57360         CALL     FinishDC\r
57362         ADD      ESP, 16\r
57363         PUSH     0\r
57364         CALL     ReleaseDC\r
57365         MOV      EDX, EBP\r
57367 @@ret_0:\r
57368         XCHG     EAX, EDX\r
57369         POP      EBP\r
57370         POP      EDI\r
57371         POP      ESI\r
57372         POP      EBX\r
57373 end;\r
57374 {$ELSE ASM_VERSION} //Pascal\r
57375 function TIcon.Convert2Bitmap(TranColor: TColor): HBitmap;\r
57376 var DC0, DC2: HDC;\r
57377     Save: THandle;\r
57378     Br: HBrush;\r
57379 begin\r
57380   Result := 0;\r
57381   if Empty then Exit;\r
57382   DC0 := GetDC( 0 );\r
57383   DC2 := CreateCompatibleDC( DC0 );\r
57384   Result := CreateCompatibleBitmap( DC0, fSize, fSize );\r
57385   Save := SelectObject( DC2, Result );\r
57386   Br := CreateSolidBrush( Color2RGB( TranColor ) );\r
57387   FillRect( DC2, MakeRect( 0, 0, fSize, fSize ), Br );\r
57388   DeleteObject( Br );\r
57389   Draw( DC2, 0, 0 );\r
57390   SelectObject( DC2, Save );\r
57391   DeleteDC( DC2 );\r
57392   ReleaseDC( 0, DC0 );\r
57393 end;\r
57394 {$ENDIF ASM_VERSION}\r
57396 {$IFDEF ASM_VERSION}\r
57397 //[destructor TIcon.Destroy]\r
57398 destructor TIcon.Destroy;\r
57399 asm     //cmd    //opd\r
57400         PUSH     EAX\r
57401         CALL     Clear\r
57402         POP      EAX\r
57403         CALL     TObj.Destroy\r
57404 end;\r
57405 {$ELSE ASM_VERSION} //Pascal\r
57406 destructor TIcon.Destroy;\r
57407 begin\r
57408   Clear;\r
57409   inherited;\r
57410 end;\r
57411 {$ENDIF ASM_VERSION}\r
57413 {$IFDEF ASM_VERSION}\r
57414 //[procedure TIcon.Draw]\r
57415 procedure TIcon.Draw(DC: HDC; X, Y: Integer);\r
57416 asm     //cmd    //opd\r
57417         CALL     asmIconEmpty\r
57418         JZ       @@exit\r
57419         PUSH     DI_NORMAL\r
57420         PUSH     0\r
57421         PUSH     0\r
57422         PUSH     [EAX].fSize\r
57423         PUSH     [EAX].fSize\r
57424         PUSH     [EAX].fHandle\r
57425         PUSH     Y\r
57426         PUSH     ECX\r
57427         PUSH     EDX\r
57428         CALL     DrawIconEx\r
57429 @@exit:\r
57430 end;\r
57431 {$ELSE ASM_VERSION} //Pascal\r
57432 procedure TIcon.Draw(DC: HDC; X, Y: Integer);\r
57433 begin\r
57434   if Empty then Exit;\r
57435   DrawIconEx( DC, X, Y, fHandle, fSize, fSize, 0, 0, DI_NORMAL );\r
57436 end;\r
57437 {$ENDIF ASM_VERSION}\r
57439 {$IFDEF ASM_VERSION}\r
57440 //[procedure TIcon.StretchDraw]\r
57441 procedure TIcon.StretchDraw(DC: HDC; Dest: TRect);\r
57442 asm     //cmd    //opd\r
57443         CALL     asmIconEmpty\r
57444         JZ       @@exit\r
57445         PUSH     DI_NORMAL\r
57446         PUSH     0\r
57447         PUSH     0\r
57448         PUSH     ECX\r
57449         PUSH     ECX\r
57450         PUSH     [EAX].fHandle\r
57451         PUSH     [ECX].TRect.Top\r
57452         PUSH     [ECX].TRect.Left\r
57453         PUSH     EDX\r
57454         MOV      EAX, [ECX].TRect.Bottom\r
57455         SUB      EAX, [ECX].TRect.Top\r
57456         MOV      [ESP+20], EAX\r
57457         MOV      EAX, [ECX].TRect.Right\r
57458         SUB      EAX, [ECX].TRect.Left\r
57459         MOV      [ESP+16], EAX\r
57460         CALL     DrawIconEx\r
57461 @@exit:\r
57462 end;\r
57463 {$ELSE ASM_VERSION} //Pascal\r
57464 procedure TIcon.StretchDraw(DC: HDC; Dest: TRect);\r
57465 begin\r
57466   if Empty then Exit;\r
57467   DrawIconEx( DC, Dest.Left, Dest.Top, FHandle, Dest.Right - Dest.Left,\r
57468               Dest.Bottom - Dest.Top, 0, 0, DI_NORMAL );\r
57469 end;\r
57470 {$ENDIF ASM_VERSION}\r
57472 //[function TIcon.GetEmpty]\r
57473 function TIcon.GetEmpty: Boolean;\r
57474 begin\r
57475   Result := fHandle = 0;\r
57476 end;\r
57478 //*\r
57479 //[function TIcon.GetHotSpot]\r
57480 function TIcon.GetHotSpot: TPoint;\r
57481 var II : TIconInfo;\r
57482 begin\r
57483   Result := MakePoint( 0, 0 );\r
57484   if FHandle = 0 then Exit;\r
57485   GetIconInfo( FHandle, II );\r
57486   Result.x := II.xHotspot;\r
57487   Result.y := II.yHotspot;\r
57488   if II.hbmMask <> 0 then\r
57489     DeleteObject( II.hbmMask );\r
57490   if II.hbmColor <> 0 then\r
57491     DeleteObject( II.hbmColor );\r
57492 end;\r
57494 //*\r
57495 //[procedure TIcon.LoadFromFile]\r
57496 procedure TIcon.LoadFromFile(const FileName: String);\r
57497 var Strm : PStream;\r
57498 begin\r
57499   Strm := NewReadFileStream( Filename );\r
57500   LoadFromStream( Strm );\r
57501   Strm.Free;\r
57502 end;\r
57504 //*\r
57505 //[procedure TIcon.LoadFromStream]\r
57506 procedure TIcon.LoadFromStream(Strm: PStream);\r
57507 var DesiredSize : Integer;\r
57508     Pos : DWord;\r
57509     Mem : PStream;\r
57510     ImgBmp, MskBmp : PBitmap;\r
57511     TmpBmp: PBitmap;\r
57512   function ReadIcon : Boolean;\r
57513   var IH : TIconHeader;\r
57514       IDI, FoundIDI : TIconDirEntry;\r
57515       I, SumSz, FoundSz, D : Integer;\r
57516       II : TIconInfo;\r
57517       BIH : TBitmapInfoheader;\r
57518   begin\r
57519      Result := False;\r
57520      if Strm.Read( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;\r
57521      if (IH.idReserved <> 0) or ((IH.idType <> 1) and (IH.idType <> 2)) or\r
57522         (IH.idCount < 1) then Exit;\r
57523      SumSz := Sizeof( IH );\r
57524      FoundSz := 1000;\r
57525      for I := 1 to IH.idCount do\r
57526      begin\r
57527         if Strm.Read( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;\r
57528         if (IDI.bWidth <> IDI.bHeight) and\r
57529            (IDI.bWidth * 2 <> IDI.bHeight) or\r
57530            (IDI.bWidth = 0) {or\r
57531            (IDI.bReserved <> 0) or (IDI.wPlanes <> 0) or (IDI.wBitCount <> 0)} then\r
57532            Exit;\r
57533         Inc( SumSz, IDI.dwBytesInRes + Sizeof( IDI ) );\r
57534         D := IDI.bWidth - DesiredSize;\r
57535         if D < 0 then D := -D;\r
57536         if D < FoundSz then\r
57537         begin\r
57538            FoundSz := D;\r
57539            FoundIDI := IDI;\r
57540         end;\r
57541      end;\r
57542      if FoundSz = 1000 then Exit;\r
57543      Strm.Seek( Integer( Pos ) + FoundIDI.dwImageOffset, spBegin );\r
57544      fSize := FoundIDI.bWidth;\r
57546      if Strm.Read( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;\r
57547      if (BIH.biWidth <> fSize) or\r
57548         (BIH.biHeight <> fSize * 2) and\r
57549         (BIH.biHeight <> fSize) then Exit;\r
57550      BIH.biHeight := fSize;\r
57552      Mem := NewMemoryStream;\r
57553      Mem.Write( BIH, Sizeof( BIH ) );\r
57554      if (FoundIDI.bColorCount >= 2) or (FoundIDI.bReserved = 1) or\r
57555         (FoundIDI.bColorCount = 0) then\r
57556      begin\r
57557        I := 0;\r
57558        if BIH.biBitCount <= 8 then\r
57559           I := (1 shl BIH.biBitCount) * Sizeof( TRGBQuad );\r
57560        if I > 0 then\r
57561           if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;\r
57562        I := ((BIH.biBitCount * fSize + 31) div 32) * 4 * fSize;\r
57563        if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;\r
57564        ImgBmp := NewBitmap( fSize, fSize );\r
57565        Mem.Seek( 0, spBegin );\r
57566        ImgBmp.LoadFromStream( Mem );\r
57567        if ImgBmp.Empty then Exit;\r
57568      end;\r
57570      BIH.biBitCount := 1;\r
57571      Mem.Seek( 0, spBegin );\r
57572      Mem.Write( BIH, Sizeof( BIH ) );\r
57573      I := 0;\r
57574      Mem.Write( I, Sizeof( I ) );\r
57575      I := $FFFFFF;\r
57576      Mem.Write( I, Sizeof( I ) );\r
57577      I := ((fSize + 31) div 32) * 4 * fSize;\r
57578      if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;\r
57580      MskBmp := NewBitmap( fSize, fSize );\r
57581      Mem.Seek( 0, spBegin );\r
57582      MskBmp.LoadFromStream( Mem );\r
57583      if MskBmp.Empty then Exit;\r
57585      II.fIcon := True;\r
57586      II.xHotspot := 0;\r
57587      II.yHotspot := 0;\r
57588      II.hbmMask := MskBmp.Handle;\r
57589      II.hbmColor := 0;\r
57590      if ImgBmp <> nil then\r
57591      begin\r
57592         II.hbmColor := ImgBmp.Handle;\r
57593         {TmpBmp := NewBitmap( ImgBmp.Width, ImgBmp.Height );\r
57594         TmpBmp.HandleType := bmDIB;\r
57595         ImgBmp.Draw( TmpBmp.Canvas.Handle, 0, 0 );\r
57596         II.hbmColor := TmpBmp.Handle;}\r
57597      end;\r
57598      fHandle := CreateIconIndirect( II );\r
57599      //fShareIcon := False;\r
57600      Strm.Seek( Integer( Pos ) + SumSz, spBegin );\r
57601      Result := fHandle <> 0;\r
57602   end;\r
57603 begin\r
57604   DesiredSize := fSize;\r
57605   if DesiredSize = 0 then\r
57606      DesiredSize := GetSystemMetrics( SM_CXICON );\r
57607   Clear;\r
57608   Pos := Strm.Position;\r
57610   Mem := nil;\r
57611   ImgBmp := nil;\r
57612   MskBmp := nil;\r
57613   TmpBmp := nil;\r
57615   if not ReadIcon then\r
57616   begin\r
57617      Clear;\r
57618      Strm.Seek( Pos, spBegin );\r
57619   end;\r
57621   Mem.Free;\r
57622   ImgBmp.Free;\r
57623   MskBmp.Free;\r
57624   TmpBmp.Free;\r
57625 end;\r
57627 {$IFDEF ASM_VERSION}\r
57628 //[procedure TIcon.SaveToFile]\r
57629 procedure TIcon.SaveToFile(const FileName: String);\r
57630 asm     //cmd    //opd\r
57631         PUSH     EAX\r
57632         MOV      EAX, ESP\r
57633         MOV      ECX, EDX\r
57634         XOR      EDX, EDX\r
57635         CALL     SaveIcons2File\r
57636         POP      EAX\r
57637 end;\r
57638 {$ELSE ASM_VERSION} //Pascal\r
57639 procedure TIcon.SaveToFile(const FileName: String);\r
57640 begin\r
57641   SaveIcons2File( [ @Self ], FileName );\r
57642 end;\r
57643 {$ENDIF ASM_VERSION}\r
57645 {$IFDEF ASM_VERSION}\r
57646 //[procedure TIcon.SaveToStream]\r
57647 procedure TIcon.SaveToStream(Strm: PStream);\r
57648 asm     //cmd    //opd\r
57649         PUSH     EAX\r
57650         MOV      EAX, ESP\r
57651         MOV      ECX, EDX\r
57652         XOR      EDX, EDX\r
57653         CALL     SaveIcons2Stream\r
57654         POP      EAX\r
57655 end;\r
57656 {$ELSE ASM_VERSION} //Pascal\r
57657 procedure TIcon.SaveToStream(Strm: PStream);\r
57658 begin\r
57659   SaveIcons2Stream( [ @Self ], Strm );\r
57660 end;\r
57661 {$ENDIF ASM_VERSION}\r
57663 {$IFDEF ASM_noVERSION}\r
57664 //[procedure TIcon.SetHandle]\r
57665 procedure TIcon.SetHandle(const Value: HIcon);\r
57666 const szII = sizeof( TIconInfo );\r
57667       szBIH = sizeof(TBitmapInfoHeader);\r
57668 asm     //cmd    //opd\r
57669         CMP      EDX, [EAX].fHandle\r
57670         JE       @@exit\r
57671         PUSHAD\r
57672         PUSH     EDX\r
57673         MOV      EBX, EAX\r
57674         CALL     Clear\r
57675         POP      ECX\r
57676         MOV      [EBX].fHandle, ECX\r
57677         JECXZ    @@fin\r
57678         ADD      ESP, -szBIH\r
57679         PUSH     ESP\r
57680         PUSH     ECX\r
57681         CALL     GetIconInfo\r
57682         MOV      ESI, [ESP].TIconInfo.hbmMask\r
57683         MOV      EDI, [ESP].TIconInfo.hbmColor\r
57684         PUSH     ESP\r
57685         PUSH     szBIH\r
57686         PUSH     ESI\r
57687         CALL     GetObject\r
57688         POP      EAX\r
57689         POP      [EBX].fSize\r
57690         ADD      ESP, szBIH-8\r
57691         TEST     ESI, ESI\r
57692         JZ       @@1\r
57693         PUSH     ESI\r
57694         CALL     DeleteObject\r
57695 @@1:    TEST     EDI, EDI\r
57696         JZ       @@fin\r
57697         PUSH     EDI\r
57698         CALL     DeleteObject\r
57699 @@fin:  POPAD\r
57700 @@exit:\r
57701 end;\r
57702 {$ELSE ASM_VERSION} //Pascal\r
57703 procedure TIcon.SetHandle(const Value: HIcon);\r
57704 var II : TIconInfo;\r
57705     B: TagBitmap;\r
57706 begin\r
57707   if FHandle = Value then Exit;\r
57708   Clear;\r
57709   FHandle := Value;\r
57710   if Value <> 0 then\r
57711   begin\r
57712      GetIconInfo( FHandle, II );\r
57713      GetObject( II.hbmMask, Sizeof( B ), @B );\r
57714      fSize := B.bmWidth;\r
57715      if II.hbmMask <> 0 then\r
57716        DeleteObject( II.hbmMask );\r
57717      if II.hbmColor <> 0 then\r
57718        DeleteObject( II.hbmColor );\r
57719   end;\r
57720 end;\r
57721 {$ENDIF ASM_VERSION}\r
57723 //*\r
57724 //[procedure TIcon.SetSize]\r
57725 procedure TIcon.SetSize(const Value: Integer);\r
57726 begin\r
57727   if FSize = Value then Exit;\r
57728   Clear;\r
57729   FSize := Value;\r
57730 end;\r
57732 const PossibleColorBits : array[1..7] of Byte = ( 1, 4, 8, 16, 24, 32, 0 );\r
57733 //[FUNCTION ColorBits]\r
57734 {$IFDEF ASM_VERSION}\r
57735 function ColorBits( ColorsCount : Integer ) : Integer;\r
57736 asm     //cmd    //opd\r
57737         PUSH     EBX\r
57738         MOV      EDX, offset[PossibleColorBits]\r
57739 @@loop: MOVZX    ECX, byte ptr [EDX]\r
57740         JECXZ    @@e_loop\r
57741         INC      EDX\r
57742         XOR      EBX, EBX\r
57743         INC      EBX\r
57744         SHL      EBX, CL\r
57745         CMP      EBX, EAX\r
57746         JL       @@loop\r
57747 @@e_loop:\r
57748         XCHG     EAX, ECX\r
57749         POP      EBX\r
57750 end;\r
57751 {$ELSE ASM_VERSION} //Pascal\r
57752 function ColorBits( ColorsCount : Integer ) : Integer;\r
57753 var I : Integer;\r
57754 begin\r
57755    for I := 1 to 6 do\r
57756    begin\r
57757       Result := PossibleColorBits[ I ];\r
57758       if (1 shl Result) >= ColorsCount then break;\r
57759    end;\r
57760 end;\r
57761 {$ENDIF ASM_VERSION}\r
57762 //[END ColorBits]\r
57764 //[function SaveIcons2StreamEx]\r
57765 function SaveIcons2StreamEx( const BmpHandles: array of HBitmap; Strm: PStream ): Boolean;\r
57766 var I, Off : Integer;\r
57767    IDI : TIconDirEntry;\r
57768    BIH : TBitmapInfoHeader;\r
57769    B: TagBitmap;\r
57770   function RGBArraySize : Integer;\r
57771   begin\r
57772      Result := 0;\r
57773      if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then\r
57774         Result := (IDI.bColorCount + (IDI.bReserved shl 8)) * Sizeof( TRGBQuad );\r
57775   end;\r
57776   function ColorDataSize( W, H: Integer ) : Integer;\r
57777   var N: Integer;\r
57778   begin\r
57779      if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then\r
57780        N := (ColorBits( IDI.bColorCount + (IDI.bReserved shl 8) ) )\r
57781      else\r
57782      begin\r
57783        N := IDI.wBitCount;\r
57784      end;\r
57785      Result := ((N * W + 31) div 32) * 4\r
57786                    * H;\r
57787   end;\r
57788   function MaskDataSize( W, H: Integer ) : Integer;\r
57789   begin\r
57790      Result := ((W + 31) div 32) * 4 * H;\r
57791   end;\r
57792 var BColor, BMask: HBitmap;\r
57793     W, H: Integer;\r
57794     ImgBmp, MskBmp: PBitmap;\r
57795     IH : TIconHeader;\r
57796     Colors : PList;\r
57797 begin\r
57798   Assert( (High(BmpHandles) >= 0) and (High(BmpHandles) and 1 <> 0),\r
57799           'Incorrect parameters count in call to SaveIcons2StreamEx' );\r
57800   Result := False;\r
57801   IH.idReserved := 0;\r
57802   IH.idType := 1;\r
57803   IH.idCount := (High( BmpHandles )+1) div 2;\r
57804   if Strm.Write( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;\r
57805   Off := Sizeof( IH ) + IH.idCount * Sizeof( IDI );\r
57806   Colors := NewList;\r
57807   ImgBmp := NewBitmap( 0, 0 );\r
57808   MskBmp := NewBitmap( 0, 0 );\r
57809   TRY\r
57811     for I := 0 to High( BmpHandles ) div 2 do\r
57812     begin\r
57813       BColor := BmpHandles[ I * 2 ];\r
57814       BMask  := BmpHandles[ I * 2 + 1 ];\r
57815       if (BColor = 0) and (BMask = 0) then break;\r
57816       Assert( BMask <> 0, 'Mask bitmap not provided for saving icons in SaveIcons2StreamEx' );\r
57817       GetObject( BMask, Sizeof( B ), @ B );\r
57818       W := B.bmWidth;\r
57819       H := B.bmHeight;\r
57820       if BColor <> 0 then\r
57821       begin\r
57822         GetObject( BColor, Sizeof( B ), @B );\r
57823         Assert( (B.bmWidth = W) and (B.bmHeight = H),\r
57824                 'Mask bitmap size must much color bitmap size in SaveIcons2StreamEx' );\r
57825       end;\r
57826       FillChar( IDI, Sizeof( IDI ), 0 );\r
57828       IDI.bWidth := W;\r
57829       IDI.bHeight := H;\r
57830       if BColor = 0 then\r
57831         IDI.bColorCount := 2\r
57832       else\r
57833       begin\r
57834         ImgBmp.Handle := CopyImage( BColor, IMAGE_BITMAP, W, H,\r
57835                          LR_CREATEDIBSECTION );\r
57836         FillChar( BIH, Sizeof( BIH ), 0 );\r
57837         BIH.biSize := Sizeof( BIH );\r
57838         GetObject( ImgBmp.Handle, Sizeof( B ), @B );\r
57839         //if ImgBmp.HandleType = bmDDB then\r
57840         begin\r
57841           if (B.bmPlanes = 1) and (B.bmBitsPixel >= 15) then\r
57842           begin\r
57843             //ImgBmp.PixelFormat := pf24bit;\r
57844             IDI.bColorCount := 0;\r
57845             IDI.bReserved := 0;\r
57846             IDI.wBitCount := B.bmBitsPixel;\r
57847           end\r
57848             else\r
57849           if B.bmPlanes * (1 shl B.bmBitsPixel) < 16 then\r
57850           begin\r
57851              ImgBmp.PixelFormat := pf1bit;\r
57852              IDI.bColorCount := 2;\r
57853           end\r
57854              else\r
57855           if B.bmPlanes * (1 shl B.bmBitsPixel) < 256 then\r
57856           begin\r
57857              ImgBmp.PixelFormat := pf4bit;\r
57858              IDI.bColorCount := 16;\r
57859           end\r
57860              else\r
57861           begin\r
57862              ImgBmp.PixelFormat := pf8bit;\r
57863              IDI.bColorCount := 0;\r
57864              IDI.bReserved := 1;\r
57865           end;\r
57866           //GetObject( ImgBmp.Handle, Sizeof( BIH ), @BIH );\r
57867         end;\r
57868         //IDI.bColorCount := (1 shl BIH.biBitCount) * BIH.biPlanes;\r
57869       end;\r
57870       Colors.Add( Pointer(IDI.bColorCount + (IDI.bReserved shl 8)) );\r
57871       IDI.dwBytesInRes := Sizeof( BIH ) +  RGBArraySize +\r
57872                           ColorDataSize( W, H ) + MaskDataSize( W, H );\r
57873       IDI.dwImageOffset := Off;\r
57874       if Strm.Write( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;\r
57875       Inc( Off, IDI.dwBytesInRes );\r
57876     end;\r
57877     for I := 0 to High( BmpHandles ) div 2 do\r
57878     begin\r
57879       BColor := BmpHandles[ I * 2 ];\r
57880       BMask  := BmpHandles[ I * 2 + 1 ];\r
57881       if (BColor = 0) and (BMask = 0) then break;\r
57882       GetObject( BMask, Sizeof( B ), @ B );\r
57883       W := B.bmWidth;\r
57884       H := B.bmHeight;\r
57886       FillChar( BIH, Sizeof( BIH ), 0 );\r
57887       BIH.biSize := Sizeof( BIH );\r
57888       BIH.biWidth := W;\r
57889       BIH.biHeight := H;\r
57890       if BColor <> 0 then\r
57891         BIH.biHeight := W * 2;\r
57892       BIH.biPlanes := 1;\r
57893       PWord( @ IDI.bColorCount )^ := DWord( Colors.Items[ I ] );\r
57894       if IDI.wBitCount = 0 then\r
57895         IDI.wBitCount := ColorBits( PWord( @ IDI.bColorCount )^ );\r
57896       BIH.biBitCount := IDI.wBitCount;\r
57897       BIH.biSizeImage := Sizeof( BIH ) + ColorDataSize( W, H ) + MaskDataSize( W, H );\r
57898       if Strm.Write( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;\r
57899       if BColor <> 0 then\r
57900       begin\r
57902         ImgBmp.Handle := CopyImage( BColor, IMAGE_BITMAP, W, H, 0 );\r
57903         case BIH.biBitCount of\r
57904         1 : ImgBmp.PixelFormat := pf1bit;\r
57905         4 : ImgBmp.PixelFormat := pf4bit;\r
57906         8 : ImgBmp.PixelFormat := pf8bit;\r
57907         16: ImgBmp.PixelFormat := pf16bit;\r
57908         24: ImgBmp.PixelFormat := pf24bit;\r
57909         32: ImgBmp.PixelFormat := pf32bit;\r
57910         end;\r
57911       end\r
57912         else\r
57913       begin\r
57914         ImgBmp.Handle := CopyImage( BMask, IMAGE_BITMAP, W, H, 0 );\r
57915         ImgBmp.PixelFormat := pf1bit;\r
57916       end;\r
57917       if ImgBmp.FDIBBits <> nil then\r
57918       begin\r
57919         if Strm.Write( Pointer(Integer(ImgBmp.FDIBHeader) + Sizeof(TBitmapInfoHeader))^,\r
57920            PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) ) <>\r
57921            PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) then Exit;\r
57922         if Strm.Write( ImgBmp.FDIBBits^, ColorDataSize( W, H ) ) <>\r
57923            DWord( ColorDataSize( W, H ) ) then Exit;\r
57924       end;\r
57925     MskBmp.Handle := CopyImage( BMask, IMAGE_BITMAP, W, H, 0 );\r
57927     MskBmp.PixelFormat := pf1bit;\r
57928     if Strm.Write( MskBmp.FDIBBits^, MaskDataSize( W, H ) ) <>\r
57929       DWord( MaskDataSize( W, H ) ) then Exit;\r
57930     end;\r
57932   FINALLY\r
57933     Colors.Free;\r
57934     ImgBmp.Free;\r
57935     MskBmp.Free;\r
57936   END;\r
57937   Result := True;\r
57938 end;\r
57940 {$IFDEF FPC}\r
57941   {$DEFINE _D3orFPC}\r
57942 {$ENDIF}\r
57943 {$IFDEF _D2orD3}\r
57944   {$DEFINE _D3orFPC}\r
57945 {$ENDIF}\r
57946 //[procedure SaveIcons2Stream]\r
57947 procedure SaveIcons2Stream( const Icons : array of PIcon; Strm : PStream );\r
57948 var I, J, Pos : Integer;\r
57949     {$IFDEF _D3orFPC}\r
57950     Bitmaps: array[ 0..63 ] of HBitmap;\r
57951     {$ELSE DELPHI}\r
57952     Bitmaps: array of HBitmap;\r
57953     {$ENDIF FPC/DELPHI}\r
57954     II: TIconInfo;\r
57955     Bmp: HBitmap;\r
57956 begin\r
57957   for I := 0 to High( Icons ) do\r
57958   begin\r
57959      if Icons[ I ].Handle = 0 then Exit;\r
57960      for J := I + 1 to High( Icons ) do\r
57961         if Icons[ I ].Size = Icons[ J ].Size then Exit;\r
57962   end;\r
57963   Pos := Strm.Position;\r
57965   {$IFDEF _D3orFPC}\r
57966   for I := 0 to High( Bitmaps ) do\r
57967     Bitmaps[ I ] := 0;\r
57968   {$ELSE DELPHI}\r
57969   SetLength( Bitmaps, Length( Icons ) * 2 );\r
57970   {$ENDIF FPC/DELPHI}\r
57971   for I := 0 to High( Icons ) do\r
57972   begin\r
57973     GetIconInfo( Icons[ I ].Handle, II );\r
57974     Bitmaps[ I * 2 ] := II.hbmColor;\r
57975     Bitmaps[ I * 2 + 1 ] := II.hbmMask;\r
57976   end;\r
57978   if not SaveIcons2StreamEx( Bitmaps, Strm ) then\r
57979      Strm.Seek( Pos, spBegin );\r
57981   for I := 0 to High( Bitmaps ) do\r
57982   begin\r
57983     Bmp := Bitmaps[ I ];\r
57984     if Bmp <> 0 then\r
57985       DeleteObject( Bmp );\r
57986   end;\r
57987 end;\r
57988 (*\r
57989 var I, J, Pos : Integer;\r
57990     IH : TIconHeader;\r
57991     Colors : PList;\r
57992     ImgBmp,\r
57993     MskBmp : PBitmap;\r
57994    function WriteIcons : Boolean;\r
57995    var I, Off : Integer;\r
57996        IDI : TIconDirEntry;\r
57997        BIH : TBitmapInfoHeader;\r
57998        II : TIconInfo;\r
57999        B: TagBitmap;\r
58000       function RGBArraySize : Integer;\r
58001       begin\r
58002          Result := 0;\r
58003          if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then\r
58004             Result := (IDI.bColorCount + (IDI.bReserved shl 8)) * Sizeof( TRGBQuad );\r
58005       end;\r
58006       function ColorDataSize : Integer;\r
58007       var N: Integer;\r
58008       begin\r
58009          //Result := 0;\r
58010          if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then\r
58011            N := (ColorBits( IDI.bColorCount + (IDI.bReserved shl 8) ) )\r
58012          else\r
58013            N := IDI.wBitCount;\r
58014          Result := ((N * Icons[ I ].Size + 31) div 32) * 4\r
58015                        * Icons[ I ].Size;\r
58016       end;\r
58017       function MaskDataSize : Integer;\r
58018       begin\r
58019          Result := ((Icons[ I ].Size + 31) div 32) * 4\r
58020                    * Icons[ I ].Size;\r
58021       end;\r
58022    begin\r
58023      Result := False;\r
58024      if Strm.Write( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;\r
58025      Off := Sizeof( IH ) + IH.idCount * Sizeof( IDI );\r
58026      for I := Low( Icons ) to High( Icons ) do\r
58027      begin\r
58028        FillChar( IDI, Sizeof( IDI ), 0 );\r
58029        IDI.bWidth := Icons[ I ].Size;\r
58030        IDI.bHeight := Icons[ I ].Size;\r
58031        GetIconInfo( Icons[ I ].Handle, II );\r
58032        if II.hbmColor = 0 then\r
58033           IDI.bColorCount := 2\r
58034        else\r
58035        begin\r
58036          {ImgBmp.Handle := CopyImage( II.hbmColor, IMAGE_BITMAP, Icons[ I ].Size,\r
58037                           Icons[ I ].Size, LR_CREATEDIBSECTION );}\r
58038          ImgBmp.Handle := II.hbmColor;\r
58039          II.hbmColor := 0;\r
58040          FillChar( BIH, Sizeof( BIH ), 0 );\r
58041          BIH.biSize := Sizeof( BIH );\r
58042          GetObject( ImgBmp.Handle, Sizeof( B ), @B );\r
58043          //if ImgBmp.HandleType = bmDDB then\r
58044          begin\r
58045             if (B.bmPlanes = 1) and (B.bmBitsPixel >= 15) then\r
58046             begin\r
58047               //ImgBmp.PixelFormat := pf24bit;\r
58048               IDI.bColorCount := 0;\r
58049               IDI.bReserved := 0;\r
58050               IDI.wBitCount := B.bmBitsPixel;\r
58051             end\r
58052               else\r
58053             if B.bmPlanes * (1 shl B.bmBitsPixel) < 16 then\r
58054             begin\r
58055                ImgBmp.PixelFormat := pf1bit;\r
58056                IDI.bColorCount := 2;\r
58057             end\r
58058                else\r
58059             if B.bmPlanes * (1 shl B.bmBitsPixel) < 256 then\r
58060             begin\r
58061                ImgBmp.PixelFormat := pf4bit;\r
58062                IDI.bColorCount := 16;\r
58063             end\r
58064                else\r
58065             begin\r
58066                ImgBmp.PixelFormat := pf8bit;\r
58067                IDI.bColorCount := 0;\r
58068                IDI.bReserved := 1;\r
58069             end;\r
58070             //GetObject( ImgBmp.Handle, Sizeof( BIH ), @BIH );\r
58071          end;\r
58072          //IDI.bColorCount := (1 shl BIH.biBitCount) * BIH.biPlanes;\r
58073          //--//DeleteObject( II.hbmColor );\r
58074        end;\r
58075        if II.hbmMask <> 0 then\r
58076          DeleteObject( II.hbmMask );\r
58077        Colors.Add( Pointer(IDI.bColorCount + (IDI.bReserved shl 8)) );\r
58078        IDI.dwBytesInRes := Sizeof( BIH ) +  RGBArraySize +\r
58079                            ColorDataSize + MaskDataSize;\r
58080        IDI.dwImageOffset := Off;\r
58081        if Strm.Write( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;\r
58082        Inc( Off, IDI.dwBytesInRes );\r
58083      end;\r
58084      for I := Low( Icons ) to High( Icons ) do\r
58085      begin\r
58086        FillChar( BIH, Sizeof( BIH ), 0 );\r
58087        BIH.biSize := Sizeof( BIH );\r
58088        BIH.biWidth := Icons[ I ].Size;\r
58089        BIH.biHeight := Icons[ I ].Size;\r
58090        //GetObject( Icons[ I ].Handle, Sizeof( II ), @II );\r
58091        GetIconInfo( Icons[ I ].Handle, II );\r
58092        if II.hbmColor <> 0 then\r
58093           BIH.biHeight := Icons[ I ].Size * 2;\r
58094        BIH.biPlanes := 1;\r
58095        PWord( @ IDI.bColorCount )^ := DWord( Colors.Items[ I - Low( Icons ) ] );\r
58096        if IDI.wBitCount = 0 then\r
58097          IDI.wBitCount := ColorBits( PWord( @ IDI.bColorCount )^ );\r
58098        BIH.biBitCount := IDI.wBitCount;\r
58099        BIH.biSizeImage := Sizeof( BIH ) + ColorDataSize + MaskDataSize;\r
58100        if Strm.Write( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;\r
58101        if II.hbmColor <> 0 then\r
58102        begin\r
58104           ImgBmp.Handle := {CopyImage( II.hbmColor, IMAGE_BITMAP, Icons[ I ].Size,\r
58105                           Icons[ I ].Size, 0 );}\r
58106                           II.hbmColor;\r
58107                           II.hbmColor := 0;\r
58108           case BIH.biBitCount of\r
58109           1 : ImgBmp.PixelFormat := pf1bit;\r
58110           4 : ImgBmp.PixelFormat := pf4bit;\r
58111           8 : ImgBmp.PixelFormat := pf8bit;\r
58112           16: ImgBmp.PixelFormat := pf16bit;\r
58113           24: ImgBmp.PixelFormat := pf24bit;\r
58114           32: ImgBmp.PixelFormat := pf32bit;\r
58115           end;\r
58116        end\r
58117           else\r
58118        begin\r
58119           ImgBmp.Handle := CopyImage( II.hbmMask, IMAGE_BITMAP, Icons[ I ].Size,\r
58120                           Icons[ I ].Size, 0 );\r
58121           ImgBmp.PixelFormat := pf1bit;\r
58122        end;\r
58123        if ImgBmp.FDIBBits <> nil then\r
58124        begin\r
58125           if Strm.Write( Pointer(Integer(ImgBmp.FDIBHeader) + Sizeof(TBitmapInfoHeader))^,\r
58126              PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) ) <>\r
58127              PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) then Exit;\r
58128           if Strm.Write( ImgBmp.FDIBBits^, ColorDataSize ) <>\r
58129              DWord( ColorDataSize ) then Exit;\r
58130        end;\r
58131        MskBmp.Handle := CopyImage( II.hbmMask, IMAGE_BITMAP, Icons[ I ].Size,\r
58132                           Icons[ I ].Size, 0 {LR_COPYRETURNORG} );\r
58133        //***\r
58134        if II.hbmMask <> 0 then\r
58135          DeleteObject( II.hbmMask );\r
58136        if II.hbmColor <> 0 then\r
58137          DeleteObject( II.hbmColor );\r
58138        //***\r
58140        MskBmp.PixelFormat := pf1bit;\r
58141        if Strm.Write( MskBmp.FDIBBits^, MaskDataSize ) <>\r
58142           DWord( MaskDataSize ) then Exit;\r
58143      end;\r
58144      Result := True;\r
58145    end;\r
58146 begin\r
58147   for I := Low( Icons ) to High( Icons ) do\r
58148   begin\r
58149      if Icons[ I ].Handle = 0 then Exit;\r
58150      for J := I + 1 to High( Icons ) do\r
58151         if Icons[ I ].Size = Icons[ J ].Size then Exit;\r
58152   end;\r
58153   IH.idReserved := 0;\r
58154   IH.idType := 1;\r
58155   IH.idCount := High( Icons ) - Low( Icons ) + 1;\r
58156   Pos := Strm.Position;\r
58157   Colors := NewList;\r
58158   ImgBmp := NewBitmap( 0, 0 );\r
58159   MskBmp := NewBitmap( 0, 0 );\r
58161   if not WriteIcons then\r
58162      Strm.Seek( Pos, spBegin );\r
58164   ImgBmp.Free;\r
58165   MskBmp.Free;\r
58166   Colors.Free;\r
58167 end;\r
58168 *)\r
58170 //[procedure SaveIcons2File]\r
58171 procedure SaveIcons2File( const Icons : array of PIcon; const FileName : String );\r
58172 var Strm: PStream;\r
58173 begin\r
58174   Strm := NewWriteFileStream( FileName );\r
58175   SaveIcons2Stream( Icons, Strm );\r
58176   Strm.Free;\r
58177 end;\r
58179 //[procedure TIcon.LoadFromExecutable]\r
58180 procedure TIcon.LoadFromExecutable(const FileName: String; IconIdx: Integer);\r
58181 var I: Integer;\r
58182 begin\r
58183   Clear;\r
58184   I := ExtractIcon( hInstance, PChar( FileName ), IconIdx );\r
58185   if I > 1 then\r
58186     Handle := I;\r
58187 end;\r
58189 //[function GetFileIconCount]\r
58190 function GetFileIconCount( const FileName: String ): Integer;\r
58191 begin\r
58192   Result := ExtractIcon( hInstance, PChar( FileName ), DWORD(-1) );\r
58193 end;\r
58195 //[procedure TIcon.LoadFromResourceID]\r
58196 procedure TIcon.LoadFromResourceID(Inst, ResID, DesiredSize: Integer);\r
58197 begin\r
58198   LoadFromResourceName( Inst, MAKEINTRESOURCE( ResID ), DesiredSize );\r
58199 end;\r
58201 //[procedure TIcon.LoadFromResourceName]\r
58202 procedure TIcon.LoadFromResourceName(Inst: Integer; ResName: PChar; DesiredSize: Integer);\r
58203 begin\r
58204   Handle := LoadImage( Inst, ResName, IMAGE_ICON, DesiredSize, DesiredSize,\r
58205                        $8000 {LR_SHARED} );\r
58206   {if Handle = 0 then\r
58207     Handle := LoadIcon( Inst, ResName )\r
58208   else}\r
58209   if fHandle <> 0 then FShareIcon := True;\r
58210 end;\r
58212 //[function LoadImgIcon]\r
58213 function LoadImgIcon( RsrcName: PChar; Size: Integer ): HIcon;\r
58214 begin\r
58215   Result := LoadImage( hInstance, RsrcName, IMAGE_ICON, Size, Size, $8000 {LR_SHARED} );\r
58216 end;\r
58219 ////////////////////////////////////////////////////////////////////////\r
58220 //\r
58221 //\r
58222 //                         M  E T A F I L E\r
58223 //\r
58224 //\r
58225 ////////////////////////////////////////////////////////////////////////\r
58227 {++}(*\r
58228 //[API SetEnhMetaFileBits]\r
58229 function SetEnhMetaFileBits; external gdi32 name 'SetEnhMetaFileBits';\r
58230 function PlayEnhMetaFile; external gdi32 name 'PlayEnhMetaFile';\r
58231 *){--}\r
58233 //[function NewMetafile]\r
58234 function NewMetafile: PMetafile;\r
58235 begin\r
58236   {-}\r
58237   new( Result, Create );\r
58238   {+}{++}(*Result := PMetafile.Create;*){--}\r
58239 end;\r
58240 //[END NewMetafile]\r
58242 { TMetafile }\r
58244 //[procedure TMetafile.Clear]\r
58245 procedure TMetafile.Clear;\r
58246 begin\r
58247   if fHandle <> 0 then\r
58248     DeleteEnhMetaFile( fHandle );\r
58249   fHandle := 0;\r
58250 end;\r
58252 //[destructor TMetafile.Destroy]\r
58253 destructor TMetafile.Destroy;\r
58254 begin\r
58255   if fHeader <> nil then\r
58256     FreeMem( fHeader );\r
58257   Clear;\r
58258   inherited;\r
58259 end;\r
58261 //[procedure TMetafile.Draw]\r
58262 procedure TMetafile.Draw(DC: HDC; X, Y: Integer);\r
58263 begin\r
58264   StretchDraw( DC, MakeRect( X, Y, X + Width, Y + Height ) );\r
58265 end;\r
58267 //[function TMetafile.Empty]\r
58268 function TMetafile.Empty: Boolean;\r
58269 begin\r
58270   Result := fHandle = 0;\r
58271 end;\r
58273 //[function TMetafile.GetHeight]\r
58274 function TMetafile.GetHeight: Integer;\r
58275 begin\r
58276   Result := 0;\r
58277   if Empty then Exit;\r
58278   RetrieveHeader;\r
58279   Result := fHeader.rclBounds.Bottom - fHeader.rclBounds.Top;\r
58280 end;\r
58282 //[function TMetafile.GetWidth]\r
58283 function TMetafile.GetWidth: Integer;\r
58284 begin\r
58285   Result := 0;\r
58286   if Empty then Exit;\r
58287   RetrieveHeader;\r
58288   Result := fHeader.rclBounds.Right - fHeader.rclBounds.Left;\r
58289 end;\r
58291 //[function TMetafile.LoadFromFile]\r
58292 function TMetafile.LoadFromFile(const Filename: String): Boolean;\r
58293 var Strm: PStream;\r
58294 begin\r
58295   Strm := NewReadFileStream( FileName );\r
58296   Result := LoadFromStream( Strm );\r
58297   Strm.Free;\r
58298 end;\r
58300 //[function ComputeAldusChecksum]\r
58301 function ComputeAldusChecksum(var WMF: TMetafileHeader): Word;\r
58302 type\r
58303   PWord = ^Word;\r
58304 var\r
58305   pW: PWord;\r
58306   pEnd: PWord;\r
58307 begin\r
58308   Result := 0;\r
58309   pW := @WMF;\r
58310   pEnd := @WMF.CheckSum;\r
58311   while Longint(pW) < Longint(pEnd) do\r
58312   begin\r
58313     Result := Result xor pW^;\r
58314     Inc(Longint(pW), SizeOf(Word));\r
58315   end;\r
58316 end;\r
58318 //[function TMetafile.LoadFromStream]\r
58319 function TMetafile.LoadFromStream(Strm: PStream): Boolean;\r
58320 var WMF: TMetaFileHeader;\r
58321     WmfHdr: TMetaHeader;\r
58322     EnhHdr: TEnhMetaHeader;\r
58323     Pos, Pos1: Integer;\r
58324     Sz: Integer;\r
58325     MemStrm: PStream;\r
58326     MFP: TMetafilePict;\r
58327 begin\r
58328   Result := FALSE;\r
58329   Pos := Strm.Position;\r
58331   if Strm.Read( WMF, Sizeof( WMF ) ) <> Sizeof( WMF ) then\r
58332   begin\r
58333     Strm.Position := Pos;\r
58334     Exit;\r
58335   end;\r
58337   MemStrm := NewMemoryStream;\r
58339   if WMF.Key = WMFKey then\r
58340   begin // Windows metafile\r
58342     if WMF.CheckSum <> ComputeAldusChecksum( WMF ) then\r
58343     begin\r
58344       Strm.Position := Pos;\r
58345       Exit;\r
58346     end;\r
58348     Pos1 := Strm.Position;\r
58349     if Strm.Read( WmfHdr, Sizeof( WmfHdr ) ) <> Sizeof( WmfHdr ) then\r
58350     begin\r
58351       Strm.Position := Pos;\r
58352       Exit;\r
58353     end;\r
58355     Strm.Position := Pos1;\r
58356     Sz := WMFHdr.mtSize * 2;\r
58357     Stream2Stream( MemStrm, Strm, Sz );\r
58358     FillChar( MFP, Sizeof( MFP ), 0 );\r
58359     MFP.mm := MM_ANISOTROPIC;\r
58360     fHandle := SetWinMetafileBits( Sz, MemStrm.Memory, 0, MFP );\r
58362   end\r
58363     else\r
58364   begin // may be enchanced?\r
58366     Strm.Position := Pos;\r
58367     if Strm.Read( EnhHdr, Sizeof( EnhHdr ) ) < 8 then\r
58368     begin\r
58369       Strm.Position := Pos;\r
58370       Exit;\r
58371     end;\r
58372     // yes, enchanced\r
58373     Strm.Position := Pos;\r
58374     Sz := EnhHdr.nBytes;\r
58375     Stream2Stream( MemStrm, Strm, Sz );\r
58376     fHandle := SetEnhMetaFileBits( Sz, MemStrm.Memory );\r
58378   end;\r
58380   MemStrm.Free;\r
58381   Result := fHandle <> 0;\r
58382   if not Result then\r
58383     Strm.Position := Pos;\r
58385 end;\r
58387 //[procedure TMetafile.RetrieveHeader]\r
58388 procedure TMetafile.RetrieveHeader;\r
58389 var SzHdr: Integer;\r
58390 begin\r
58391   if fHeader <> nil then\r
58392     FreeMem( fHeader );\r
58393   SzHdr := GetEnhMetaFileHeader( fHandle, 0, nil );\r
58394   GetMem( fHeader, SzHdr );\r
58395   GetEnhMetaFileHeader( fHandle, SzHdr, fHeader );\r
58396 end;\r
58398 //[procedure TMetafile.SetHandle]\r
58399 procedure TMetafile.SetHandle(const Value: THandle);\r
58400 begin\r
58401   Clear;\r
58402   fHandle := Value;\r
58403 end;\r
58405 //[procedure TMetafile.StretchDraw]\r
58406 procedure TMetafile.StretchDraw(DC: HDC; const R: TRect);\r
58407 begin\r
58408   if Empty then Exit;\r
58409   PlayEnhMetaFile( DC, fHandle, R );\r
58410 end;\r
58423 //*\r
58424 //[procedure AlignChildrenProc]\r
58425 procedure AlignChildrenProc( Sender: PObj );\r
58426 type\r
58427   TAligns = set of TControlAlign;\r
58428 var P: PControl;\r
58429     CR: TRect;\r
58430   procedure DoAlign( Allowed: TAligns );\r
58431   var I: Integer;\r
58432       C: PControl;\r
58433       R, R1: TRect;\r
58434       W, H: Integer;\r
58435       ChgPos, ChgSiz: Boolean;\r
58436   begin\r
58437     for I := 0 to P.fChildren.fCount - 1 do\r
58438     begin\r
58439       C := P.fChildren.fItems[ I ];\r
58440       if not C.ToBeVisible then continue;\r
58441       // important: not fVisible, and even not Visible, but ToBeVisible!\r
58442       if C.fNotUseAlign then continue;\r
58443       if C.FAlign in Allowed then\r
58444       begin\r
58445         R := C.BoundsRect;\r
58446         R1 := R;\r
58447         W := R.Right - R.Left;\r
58448         H := R.Bottom - R.Top;\r
58449         case C.FAlign of\r
58450         caTop:\r
58451           begin\r
58452             OffsetRect( R, 0, -R.Top + CR.Top + P.Margin );\r
58453             Inc( CR.Top, H + P.Margin );\r
58454             R.Left := CR.Left + P.Margin;\r
58455             R.Right := CR.Right - P.Margin;\r
58456           end;\r
58457         caBottom:\r
58458           begin\r
58459             OffsetRect( R, 0, -R.Bottom + CR.Bottom - P.Margin );\r
58460             Dec( CR.Bottom, H + P.Margin );\r
58461             R.Left := CR.Left + P.Margin;\r
58462             R.Right := CR.Right - P.Margin;\r
58463           end;\r
58464         caLeft:\r
58465           begin\r
58466             OffsetRect( R, -R.Left + CR.Left + P.Margin, 0 );\r
58467             Inc( CR.Left, W + P.Margin );\r
58468             R.Top := CR.Top + P.Margin;\r
58469             R.Bottom := CR.Bottom - P.Margin;\r
58470           end;\r
58471         caRight:\r
58472           begin\r
58473             OffsetRect( R, -R.Right + CR.Right - P.Margin, 0 );\r
58474             Dec( CR.Right, W + P.Margin );\r
58475             R.Top := CR.Top + P.Margin;\r
58476             R.Bottom := CR.Bottom - P.Margin;\r
58477           end;\r
58478         caClient:\r
58479           begin\r
58480             R := CR;\r
58481             InflateRect( R, -P.Margin, -P.Margin );\r
58482           end;\r
58483         end;\r
58484         if R.Right < R.Left then R.Right := R.Left;\r
58485         if R.Bottom < R.Top then R.Bottom := R.Top;\r
58486         ChgPos := (R.Left <> R1.Left) or (R.Top <> R1.Top);\r
58487         ChgSiz := (R.Right - R.Left <> W) or (R.Bottom - R.Top <> H);\r
58488         if ChgPos or ChgSiz then\r
58489         begin\r
58490           C.BoundsRect := R;\r
58491           if ChgSiz then\r
58492             AlignChildrenProc( C );\r
58493         end;\r
58494       end;\r
58495     end;\r
58496   end;\r
58497 begin\r
58498   P := Pointer( Sender );\r
58499   if P = nil then Exit; // Called for form - ignore.\r
58500   CR := P.ClientRect;\r
58501   DoAlign( [ caTop, caBottom ] );\r
58502   DoAlign( [ caLeft, caRight ] );\r
58503   DoAlign( [ caClient ] );\r
58504 end;\r
58506 //*\r
58507 //[procedure TControl.Set_Align]\r
58508 procedure TControl.Set_Align(const Value: TControlAlign);\r
58509 begin\r
58510   Global_Align := AlignChildrenProc;\r
58511   if fNotUseAlign then Exit;\r
58512   if FAlign = Value then Exit;\r
58513   FAlign := Value;\r
58514   //Global_Align( Parent );\r
58515   AlignChildrenProc( Parent );\r
58516 end;\r
58518 //*\r
58519 //[function TControl.SetAlign]\r
58520 function TControl.SetAlign(AAlign: TControlAlign): PControl;\r
58521 begin\r
58522   Set_Align( AAlign );\r
58523   Result := @Self;\r
58524 end;\r
58526 //*\r
58527 //[function WndProcPreventResizeFlicks]\r
58528 function WndProcPreventResizeFlicks( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
58529 type TRectsArray = array[0..2] of TRect;\r
58530      PRectsArray = ^TRectsArray;\r
58531      TChange = ( ChgL, ChgT, ChgR, ChgB );\r
58532      TChanges = Set of TChange;\r
58533 var Rects : PRectsArray;\r
58534     Changes : Set of TChange;\r
58535     Resizing : Boolean;\r
58536     X, Y, DX, DY : Integer;\r
58537     EntireRect, Src, Dst : TRect;\r
58539     function GetClientAfter : TRect;\r
58540     var R : TRect;\r
58541     begin\r
58542       R := Rects[ 2 ];\r
58543       OffsetRect( R, Rects[ 0 ].Left - Rects[ 1 ].Left,\r
58544                   Rects[ 0 ].Top - Rects[ 1 ].Top );\r
58545       if Rects[ 0 ].Right - Rects[ 0 ].Left <> Rects[ 1 ].Right - Rects[ 1 ].Left then\r
58546          R.Right := R.Left + (R.Right - R.Left)\r
58547                            + (Rects[ 0 ].Right - Rects[ 0 ].Left)\r
58548                            - (Rects[ 1 ].Right - Rects[ 1 ].Left);\r
58549       if Rects[ 0 ].Bottom - Rects[ 0 ].Top <> Rects[ 1 ].Bottom - Rects[ 1 ].Top then\r
58550          R.Bottom := R.Top + (R.Bottom - R.Top)\r
58551                            + (Rects[ 0 ].Bottom - Rects[ 0 ].Top)\r
58552                            - (Rects[ 1 ].Bottom - Rects[ 1 ].Top);\r
58553       Result := R;\r
58554     end;\r
58556     procedure DoResize( F : PControl; Changes : TChanges );\r
58557     var ClientAfter : TRect;\r
58559         procedure CollectClipRgn( V : PControl; Changes : TChanges );\r
58560         var C : PControl;\r
58561             I : Integer;\r
58562         begin\r
58563            for I := 0 to V.FChildren.FCount - 1 do\r
58564            begin\r
58565                C := V.FChildren.FItems[ I ];\r
58566                if not C.Visible then Continue;\r
58568                if C.fNotUseAlign then\r
58569                begin\r
58570                  C.Update;\r
58571                end;\r
58572            end;\r
58573         end; // of CollectClipRgn\r
58576     begin // DoResize\r
58577          ClientAfter := GetClientAfter;\r
58578          //ClipRgn := CreateRectRgn( ClientAfter.Left, ClientAfter.Top,\r
58579          //           ClientAfter.Right, ClientAfter.Bottom );\r
58580          CollectClipRgn( F, Changes );\r
58581          //ScrollWithoutClipRgn;\r
58582          //DeleteObject( ClipRgn );\r
58583     end; // of DoResize\r
58585 var PR: PRect;\r
58586     R: TRect;\r
58587 begin // Procedure WndProcResizeFlicks\r
58588   Result := False;\r
58589   case Msg.message of\r
58590   WM_NCCALCSIZE:\r
58591     if Msg.wParam <> 0 then\r
58592     begin\r
58593       Rects := Pointer( Msg.lParam );\r
58594       Changes := [];\r
58595       if Rects[ 0 ].Left <> Rects[ 1 ].Left then\r
58596          Changes := Changes + [ ChgL ];\r
58597       if Rects[ 0 ].Top <> Rects[ 1 ].Top then\r
58598          Changes := Changes + [ ChgT ];\r
58599       if Rects[ 0 ].Right <> Rects[ 1 ].Right then\r
58600          Changes := Changes + [ ChgR ];\r
58601       if Rects[ 0 ].Bottom <> Rects[ 1 ].Bottom then\r
58602          Changes := Changes + [ ChgB ];\r
58603       Resizing := Changes * [ ChgL, ChgT ] <> [ ];\r
58604       if Resizing and not Sender.fNotUseAlign then\r
58605       begin\r
58606         EntireRect := GetClientAfter;\r
58607         OffsetRect( EntireRect, -EntireRect.Left, -EntireRect.Top );\r
58608         if EntireRect.Right - EntireRect.Left < Rects[ 2 ].Right - Rects[ 2 ].Left then\r
58609            EntireRect.Right := Rects[ 2 ].Right - Rects[ 2 ].Left;\r
58610         if EntireRect.Bottom - EntireRect.Top < Rects[ 2 ].Bottom - Rects[ 2 ].Top then\r
58611            EntireRect.Bottom := Rects[ 2 ].Bottom - Rects[ 2 ].Top;\r
58612         X := Min( Rects[ 0 ].Left, Rects[ 1 ].Left ) + Rects[ 2 ].Left - Rects[ 1 ].Left;\r
58613         Y := Min( Rects[ 0 ].Top, Rects[ 1 ].Top ) + Rects[ 2 ].Top - Rects[ 2 ].Top;\r
58614         OffsetRect( EntireRect, X, Y );\r
58615         DX := 0; DY := 0;\r
58616         if ChgL in Changes then\r
58617           DX := Rects[ 0 ].Left - Rects[ 1 ].Left;\r
58618         if ChgR in Changes then\r
58619           DX := Rects[ 0 ].Right - Rects[ 1 ].Right;\r
58620         if ChgT in Changes then\r
58621           DY := Rects[ 0 ].Top - Rects[ 1 ].Top;\r
58622         if ChgB in Changes then\r
58623           DY := Rects[ 0 ].Bottom - Rects[ 1 ].Bottom;\r
58624         DoResize( Sender, Changes );\r
58625         if (Changes = [ChgL]) {and (Rects[0].Left <> Rects[1].Left)} then\r
58626         begin\r
58627           Rslt := WVR_VALIDRECTS;\r
58628           Src := Rects[ 2 ];\r
58629           Dst := GetClientAfter;\r
58630           Src.Right := Src.Left - DX;\r
58631           Dst.Right := Dst.Left - DX;\r
58632           Rects[ 1 ] := Src;\r
58633           Rects[ 2 ] := Dst;\r
58634         end\r
58635           else\r
58636         if (Changes = [ChgR]) {and (Rects[0].Right > Rects[1].Right)} then\r
58637         begin\r
58638           Rslt := WVR_VALIDRECTS;\r
58639           Src := Rects[ 2 ];\r
58640           Dst := GetClientAfter;\r
58641           Src.Left := Src.Right - DX;\r
58642           Dst.Left := Dst.Right - DX;\r
58643           Rects[ 1 ] := Src;\r
58644           Rects[ 2 ] := Dst;\r
58645         end\r
58646            else\r
58647         if (Changes = [ChgT]) {and (Rects[0].Top <> Rects[1].Top)} then\r
58648         begin\r
58649           Rslt := WVR_VALIDRECTS;\r
58650           Src := Rects[ 2 ];\r
58651           Dst := GetClientAfter;\r
58652           Src.Bottom := Src.Top - DY;\r
58653           Dst.Bottom := Dst.Top - DY;\r
58654           Rects[ 1 ] := Src;\r
58655           Rects[ 2 ] := Dst;\r
58656         end\r
58657            else\r
58658         if Changes = [ChgL,ChgT] then\r
58659         begin\r
58660           Rslt := WVR_VALIDRECTS;\r
58661           Src := Rects[ 2 ];\r
58662           Dst := GetClientAfter;\r
58663           Src.Left := Src.Right - DX;\r
58664           Dst.Left := Dst.Right - DX;\r
58665           Src.Bottom := Src.Top - DY;\r
58666           Dst.Bottom := Dst.Top - DY;\r
58667           Rects[ 1 ] := Src;\r
58668           Rects[ 2 ] := Dst;\r
58669         end;\r
58670         PostMessage( Sender.fHandle, CM_UPDATE, 0, 0 );\r
58671       end\r
58672          {else\r
58673       if Sender.fNotUseAlign then\r
58674       begin\r
58675       end};\r
58676     end;\r
58677   CM_UPDATE:\r
58678     begin\r
58679       if Sender.fNotUpdate then\r
58680       begin\r
58681         Sender.fNotUpdate := False;\r
58682         Sender.Invalidate;\r
58683       end;\r
58684       Sender.Update;\r
58685     end;\r
58686   WM_SIZING:\r
58687     begin\r
58688       if (Msg.wParam = WMSZ_TOPLEFT) or (Msg.wParam = WMSZ_BOTTOMLEFT) or (Msg.wParam = WMSZ_TOPRIGHT) then\r
58689       begin\r
58690         PR := Pointer( Msg.lParam );\r
58691         GetWindowRect( Sender.fHandle, R );\r
58692         PostMessage( Sender.fHandle, CM_SIZEPOS, LoWord( PR.Left) or (PR.Top shl 16),\r
58693                      LoWord( PR.Right - PR.Left ) or ( (PR.Bottom - PR.Top) shl 16) );\r
58694         if Msg.wParam = WMSZ_TOPLEFT then\r
58695           if Abs( R.Top - PR.Top ) < Abs( R.Left - PR.Left ) then\r
58696             PR.Top := R.Top\r
58697           else\r
58698             PR.Left := R.Left\r
58699         else\r
58700         if Msg.wParam = WMSZ_BOTTOMLEFT then\r
58701           if Abs( R.Bottom - PR.Bottom ) < Abs( R.Left - PR.Left ) then\r
58702             PR.Bottom := R.Bottom\r
58703           else\r
58704             PR.Left := R.Left\r
58705         else // WMSZ_TOPRIGHT\r
58706           if Abs( R.Top - PR.Top ) < Abs( R.Right - PR.Right ) then\r
58707             PR.Top := R.Top\r
58708           else\r
58709             PR.Right := R.Right;\r
58710         Sender.fNotUpdate := True;\r
58711         Rslt := 1;\r
58712         Result := TRUE;\r
58713       end;\r
58714     end;\r
58715   CM_SIZEPOS:\r
58716     begin\r
58717       Sender.fNotUpdate := False;\r
58718       SetWindowPos( Sender.fHandle, 0, SmallInt( LoWord( Msg.wParam ) ),\r
58719                     SmallInt( HiWord( Msg.wParam ) ), SmallInt( LoWord( Msg.lParam ) ),\r
58720                     SmallInt( HiWord( Msg.lParam ) ), SWP_NOZORDER or SWP_NOACTIVATE );\r
58721     end;\r
58722   WM_PAINT:\r
58723     begin\r
58724       if Sender.fNotUpdate then\r
58725       begin\r
58726         Rslt := 0;\r
58727         Result := True;\r
58728       end;\r
58729     end;\r
58730   WM_ERASEBKGND:\r
58731     begin\r
58732       if Sender.fNotUpdate then\r
58733       begin\r
58734         Rslt := 1;\r
58735         Result := True;\r
58736       end;\r
58737     end;\r
58738   end;\r
58739 end;\r
58741 //*\r
58742 //[function TControl.PreventResizeFlicks]\r
58743 function TControl.PreventResizeFlicks: PControl;\r
58744 begin\r
58745   fWndProcResizeFlicks := WndProcPreventResizeFlicks;\r
58746   Result := @Self;\r
58747 end;\r
58749 //*\r
58750 //[procedure TControl.Update]\r
58751 procedure TControl.Update;\r
58752 var I: Integer;\r
58753     C: PControl;\r
58754 begin\r
58755   if fUpdateCount > 0 then\r
58756     Exit;\r
58757   if fNotUpdate then Exit;\r
58758   if fHandle = 0 then Exit;\r
58759   UpdateWindow( fHandle );\r
58760   for I := 0 to fChildren.fCount - 1 do\r
58761   begin\r
58762     C := fChildren.fItems[ I ];\r
58763     C.Update;\r
58764   end;\r
58765 end;\r
58767 //[FUNCTION WndProcUpdate]\r
58768 {$IFDEF ASM_VERSION}\r
58769 function WndProcUpdate( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
58770 asm     //cmd    //opd\r
58771         PUSH     EBX\r
58772         XCHG     EBX, EAX\r
58773         MOV      EAX, [EBX].TControl.fUpdateCount\r
58774         TEST     EAX, EAX\r
58775         JZ       @@exit\r
58777         XOR      EAX, EAX\r
58778         MOV      EDX, [EDX].TMsg.message\r
58779         CMP      DX, WM_PAINT\r
58780         JNE      @@chk_erasebkgnd\r
58782         MOV      [ECX], EAX\r
58783         PUSH     EAX\r
58784         PUSH     [EBX].TControl.fHandle\r
58785         CALL     ValidateRect\r
58786         JMP      @@rslt_1\r
58787 @@chk_erasebkgnd:\r
58788         CMP      DX, WM_ERASEBKGND\r
58789         JNE      @@exit\r
58790         INC      EAX\r
58791         MOV      [ECX], EAX\r
58792 @@rslt_1:\r
58793         MOV      AL, 1\r
58794 @@exit:\r
58795         POP      EBX\r
58796 end;\r
58797 {$ELSE ASM_VERSION} //Pascal\r
58798 function WndProcUpdate( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
58799 begin\r
58800   if Sender.fUpdateCount > 0 then\r
58801   begin\r
58802     case Msg.message of\r
58803     WM_PAINT:\r
58804       begin\r
58805         ValidateRect( Sender.Handle, nil );\r
58806         Rslt := 0;\r
58807       end;\r
58808     WM_ERASEBKGND: Rslt := 1;\r
58809     else begin\r
58810            Result := FALSE;\r
58811            Exit;\r
58812          end;\r
58813     end;\r
58814     Result := TRUE;\r
58815   end\r
58816     else Result := FALSE;\r
58817 end;\r
58818 {$ENDIF ASM_VERSION}\r
58819 //[END WndProcUpdate]\r
58821 //[procedure TControl.BeginUpdate]\r
58822 procedure TControl.BeginUpdate;\r
58823 begin\r
58824   Inc( fUpdateCount );\r
58825   AttachProc( @WndProcUpdate );\r
58826 end;\r
58828 //[procedure TControl.EndUpdate]\r
58829 procedure TControl.EndUpdate;\r
58830 begin\r
58831   Dec( fUpdateCount );\r
58832   if fUpdateCount <= 0 then\r
58833   begin\r
58834     Invalidate;\r
58835     //Update;\r
58836   end;\r
58837 end;\r
58839 //*\r
58840 //[function TControl.GetSelection]\r
58841 function TControl.GetSelection: String;\r
58842 var L: Integer;\r
58843 begin\r
58844   if fCommandActions.aGetSelection <> 0 then\r
58845   begin\r
58846     L := SelLength;\r
58847     SetString( Result, nil, L + 1 );\r
58848     Perform( fCommandActions.aGetSelection, 0, Integer( @Result[ 1 ] ) );\r
58849   end\r
58850      else\r
58851   Result := Copy( Text, SelStart + 1, SelLength );\r
58852 end;\r
58854 //*\r
58855 //[procedure TControl.SetSelection]\r
58856 procedure TControl.SetSelection(const Value: String);\r
58857 begin\r
58858   ReplaceSelection( Value, True );\r
58859 end;\r
58861 //*\r
58862 //[procedure TControl.ReplaceSelection]\r
58863 procedure TControl.ReplaceSelection(const Value: String; aCanUndo: Boolean);\r
58864 begin\r
58865   if fCommandActions.aReplaceSel <> 0 then\r
58866   begin\r
58867     Perform( fCommandActions.aReplaceSel, Integer( aCanUndo ), Integer( Pchar( Value ) ) );\r
58868   end;\r
58869 end;\r
58871 //[procedure TControl.DeleteLines]\r
58872 procedure TControl.DeleteLines(FromLine, ToLine: Integer);\r
58873 var I1, I2: Integer;\r
58874     SStart, SLength: Integer;\r
58875 begin\r
58876   if FromLine > ToLine then Exit;\r
58877   Assert( FromLine >= 0, 'Incorrect line index' );\r
58878   I1 := Item2Pos( FromLine );\r
58879   I2 := Item2Pos( ToLine+1 );\r
58880   SStart := SelStart;\r
58881   SLength := SelLength;\r
58882   SelStart := I1;\r
58883   SelLength := I2 - I1;\r
58884   ReplaceSelection( '', TRUE );\r
58885   if SStart >= I2 then\r
58886   begin\r
58887     SStart := SStart - (I2 - I1);\r
58888   end\r
58889     else\r
58890   if SStart >= I1 then\r
58891   begin\r
58892     SLength := SLength - (I2 - SStart);\r
58893     SStart := I1;\r
58894   end\r
58895     else\r
58896   if SStart + SLength >= I2 then\r
58897   begin\r
58898     SLength := SLength - (I2 - I1);\r
58899   end\r
58900     else\r
58901   if SStart + SLength >= I1 then\r
58902   begin\r
58903     SLength := I1 - SLength;\r
58904   end;\r
58905   SelStart := SStart;\r
58906   SelLength := Max( 0, SLength );\r
58907 end;\r
58909 //*\r
58910 //[procedure TControl.SetTabOrder]\r
58911 procedure TControl.SetTabOrder(const Value: Integer);\r
58912 var CL: PList;\r
58913     I : Integer;\r
58914     C: PControl;\r
58915 begin\r
58916   if Value = fTabOrder then Exit;\r
58917   CL := CollectTabControls( ParentForm );\r
58918   for I := 0 to CL.fCount - 1 do\r
58919   begin\r
58920     C := CL.fItems[ I ];\r
58921     if C.fTabOrder >= Value then\r
58922       Inc( C.fTabOrder );\r
58923   end;\r
58924   fTabOrder := Value;\r
58925   CL.Free;\r
58926 end;\r
58928 //*\r
58929 //[function TControl.GetFocused]\r
58930 function TControl.GetFocused: Boolean;\r
58931 begin\r
58932   if fIsControl then\r
58933     Result := ParentForm.fCurrentControl = @Self\r
58934   else\r
58935     Result := GetForegroundWindow = fHandle;\r
58936 end;\r
58938 //*\r
58939 //[procedure TControl.SetFocused]\r
58940 procedure TControl.SetFocused(const Value: Boolean);\r
58941 begin\r
58942   if not Value then Exit;\r
58943   if fIsControl then\r
58944   begin\r
58945     ParentForm.fCurrentControl := @Self;\r
58946     SetFocus( GetWindowHandle );\r
58947   end\r
58948     else\r
58949   begin\r
58950     SetForegroundWindow( GetWindowHandle );\r
58951   end;\r
58952 end;\r
58954 type\r
58955   PCharFormat = ^TCharFormat;\r
58962 //////////////////////////////////////////////////////////////////////\r
58963 //\r
58964 //\r
58965 //                  R  I  C  H     E  D  I  T\r
58966 //\r
58967 //\r
58968 //////////////////////////////////////////////////////////////////////\r
58970 { -- rich edit -- }\r
58972 //*\r
58973 //[function TControl.REGetFont]\r
58974 function TControl.REGetFont: PGraphicTool;\r
58975 var CF: PCharFormat;\r
58976     FS: TFontStyle;\r
58977 begin\r
58978   CF := @fRECharFormatRec;\r
58979   FillChar( CF^, 82 {sizeof( TCharFormat2 )}, 0 );\r
58980   CF.cbSize := sizeof( RichEdit.TCharFormat ) + fCharFmtDeltaSz;\r
58981   if fTmpFont = nil then\r
58982     fTmpFont := NewFont;\r
58983   Result := fTmpFont;\r
58984   Result.OnChange := nil;\r
58985   Perform( EM_GETCHARFORMAT, 1, Integer( CF ) );\r
58986   Result.FontHeight := CF.yHeight;\r
58987   FS := [ ];\r
58988   if LongBool(CF.dwEffects and CFE_BOLD) then\r
58989     FS := [ fsBold ];\r
58990   if LongBool(CF.dwEffects and CFE_ITALIC) then\r
58991     FS := FS + [ fsItalic ];\r
58992   if LongBool(CF.dwEffects and CFE_STRIKEOUT) then\r
58993     FS := FS + [ fsStrikeOut ];\r
58994   if LongBool(CF.dwEffects and CFE_UNDERLINE) then\r
58995     FS := FS + [ fsUnderline ];\r
58996   Result.FontStyle := FS;\r
58997   if not LongBool(CF.dwEffects and CFE_AUTOCOLOR) then\r
58998     Result.Color := CF.crTextColor;\r
58999   Result.FontPitch := TFontPitch( CF.bPitchAndFamily and 3 );\r
59000   Result.FontCharset := CF.bCharSet;\r
59001   Result.FontName := CF.szFaceName;\r
59002   Result.OnChange := RESetFont;\r
59003 end;\r
59005 const RichAreas: array[ TRichFmtArea ] of Integer = ( SCF_SELECTION,\r
59006       SCF_WORD, 4 {SCF_ALL} );\r
59008 //*\r
59009 //[procedure TControl.RESetFontEx]\r
59010 procedure TControl.RESetFontEx(const Index: Integer);\r
59011 var CF: PCharFormat;\r
59012     FS: TFontStyle;\r
59013 begin\r
59014   CF := @fRECharFormatRec;\r
59015   FillChar( CF^, {82} sizeof( TCharFormat2 ), 0 );\r
59016   CF.cbSize := 60 { sizeof( TCharFormat ) } + fCharFmtDeltaSz;\r
59017   CF.dwMask := CFM_BOLD or CFM_COLOR or CFM_FACE or CFM_ITALIC\r
59018             or CFM_SIZE or CFM_STRIKEOUT or CFM_UNDERLINE;\r
59019   CF.yHeight := fTmpFont.FontHeight;\r
59020   FS := fTmpFont.FontStyle;\r
59021   if fsBold in FS then CF.dwEffects := CFE_BOLD;\r
59022   if fsItalic in FS then CF.dwEffects := CF.dwEffects or CFE_ITALIC;\r
59023   if fsStrikeOut in FS then CF.dwEffects := CF.dwEffects or CFE_STRIKEOUT;\r
59024   if fsUnderline in FS then CF.dwEffects := CF.dwEffects or CFE_UNDERLINE;\r
59025   CF.crTextColor := Color2RGB(fTmpFont.Color);\r
59026   CF.bCharSet := fTmpFont.FontCharset;\r
59027   CF.bPitchAndFamily := Ord( fTmpFont.FontPitch );\r
59028   StrLCopy( CF.szFaceName, PChar( fTmpFont.FontName ), 31 );\r
59029   Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( CF ) );\r
59030 end;\r
59032 //*\r
59033 //[procedure TControl.RESetFont]\r
59034 procedure TControl.RESetFont(Value: PGraphicTool);\r
59035 var H: Integer;\r
59036 begin\r
59037   if Value <> fTmpFont then\r
59038     REGetFont;\r
59039   H := fTmpFont.fData.Font.Height;\r
59040   fTmpFont := fTmpFont.Assign( Value );\r
59041   if fTmpFont.fData.Font.Height = 0 then\r
59042     fTmpFont.fData.Font.Height := H;\r
59043   RESetFontEx( Integer( CFM_BOLD or CFM_COLOR or CFM_FACE or CFM_ITALIC\r
59044             or CFM_SIZE or CFM_STRIKEOUT or CFM_UNDERLINE ) );\r
59045 end;\r
59047 //*\r
59048 //[function TControl.REGetFontMask]\r
59049 function TControl.REGetFontMask( const Index: Integer ): Boolean;\r
59050 begin\r
59051   REGetFont;\r
59052   Result := LongBool( fRECharFormatRec.dwMask and Index );\r
59053 end;\r
59055 //*\r
59056 //[function TControl.REGetFontEffects]\r
59057 function TControl.REGetFontEffects(const Index: Integer): Boolean;\r
59058 begin\r
59059   REGetFont;\r
59060   Result := LongBool( fRECharFormatRec.dwEffects and Index );\r
59061 end;\r
59063 //*\r
59064 //[procedure TControl.RESetFontEffect]\r
59065 procedure TControl.RESetFontEffect(const Index: Integer;\r
59066   const Value: Boolean);\r
59067 var CF: PCharFormat;\r
59068 begin\r
59069   ReGetFont;\r
59070   CF := @fRECharFormatRec;\r
59071   CF.dwEffects := $FFFFFFFF and Index;\r
59072   if not Value then CF.dwEffects := 0;\r
59073   CF.dwMask := Index;\r
59074   Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( CF ) );\r
59075 end;\r
59077 //*\r
59078 //[function TControl.REGetFontAttr]\r
59079 function TControl.REGetFontAttr(const Index: Integer): Integer;\r
59080 var CF: PDWORD;\r
59081     Mask: DWORD;\r
59082 begin\r
59083   REGetFont;\r
59084   CF := Pointer( Integer( @fRECharFormatRec ) + (HiWord(Index) and $7E) );\r
59085   Mask := $FFFFFFFF;\r
59086   if LongBool( HiWord(Index) and $1 ) then\r
59087     Mask := $FF;\r
59088   Result := CF^ and Mask;\r
59089 end;\r
59091 //*\r
59092 //[procedure TControl.RESetFontAttr]\r
59093 procedure TControl.RESetFontAttr(const Index, Value: Integer);\r
59094 {const\r
59095   CFE_MASK = CFE_AUTOCOLOR or CFE_BOLD or CFE_ITALIC or CFE_PROTECTED or CFE_STRIKEOUT or\r
59096              CFE_UNDERLINE or CFE_LINK or CFE_SUBSCRIPT or CFE_SUPERSCRIPT or}\r
59097 var CF: PDWORD;\r
59098     Mask: DWORD;\r
59099 begin\r
59100   REGetFont;\r
59101   CF := Pointer( Integer( @fRECharFormatRec ) + (HiWord(Index) and $7E) );\r
59102   Mask := 0;\r
59103   if LongBool( HiWord(Index) and $1 ) then\r
59104     Mask := $FFFFFF00;\r
59105   CF^ := CF^ and Mask or DWORD(Value);\r
59106   fRECharFormatRec.dwMask := Index and $FF81FFFF;\r
59107   if LongBool( fRECharFormatRec.dwMask and (CFM_COLOR or CFM_BACKCOLOR) ) then\r
59108     fRECharFormatRec.dwEffects := fRECharFormatRec.dwEffects and\r
59109                                not (CFE_AUTOCOLOR or CFE_AUTOBACKCOLOR);\r
59110   {fRECharFormatRec.dwEffects := fRECharFormatRec.dwEffects and CFE_MASK;}\r
59111   Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @fRECharFormatRec ) );\r
59112 end;\r
59114 //[procedure TControl.RESetFontAttr1]\r
59115 procedure TControl.RESetFontAttr1(const Index, Value: Integer);\r
59116 begin\r
59117   RESetFontAttr( Index, Color2RGB( Value ) );\r
59118 end;\r
59120 //*\r
59121 //[function TControl.REGetFontSizeValid]\r
59122 function TControl.REGetFontSizeValid: Boolean;\r
59123 begin\r
59124   Result := REGetFontMask( Integer( CFM_SIZE ) );\r
59125 end;\r
59127 //*\r
59128 //[function TControl.REGetFontName]\r
59129 function TControl.REGetFontName: String;\r
59130 begin\r
59131   ReGetFont;\r
59132   Result := fRECharFormatRec.szFaceName;\r
59133 end;\r
59135 //*\r
59136 //[procedure TControl.RESetFontName]\r
59137 procedure TControl.RESetFontName(const Value: String);\r
59138 begin\r
59139   ReGetFont;\r
59140   StrLCopy( fRECharFormatRec.szFaceName, PChar( Value ), Sizeof( fRECharFormatRec.szFaceName ) - 1 );\r
59141   fRECharFormatRec.dwMask := CFM_FACE;\r
59142   Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @fRECharFormatRec ) );\r
59143 end;\r
59145 //*\r
59146 //[procedure TControl.SelectAll]\r
59147 procedure TControl.SelectAll;\r
59148 begin\r
59149   SelStart := 0;\r
59150   SelLength := -1; // this can be not working for some controls... //*//*\r
59151 end;\r
59153 //*\r
59154 //[function TControl.REGetCharformat]\r
59155 function TControl.REGetCharformat: TCharFormat;\r
59156 begin\r
59157   REGetFont;\r
59158   Result := fRECharFormatRec;\r
59159 end;\r
59161 //*\r
59162 //[procedure TControl.RESetCharFormat]\r
59163 procedure TControl.RESetCharFormat(const Value: TCharFormat);\r
59164 begin\r
59165   Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @Value ) );\r
59166 end;\r
59168 //*\r
59169 //[function REOut2Stream]\r
59170 function REOut2Stream( Sender: PControl; Buf: PByte; Sz: DWORD; pSz: PInteger )\r
59171   :DWORD; stdcall;\r
59172 begin\r
59173   if Sz + Sender.fREStream.Position > Sender.fREStream.Size then\r
59174     Sender.fREStream.Size := Sender.fREStream.Size + DWORD( {Min(} Sz {, 8192 )} );\r
59175   pSz^ := Sender.fREStream.Write( Buf^, Sz );\r
59176   if Assigned( Sender.fOnProgress ) then\r
59177     Sender.fOnProgress( Sender );\r
59178   Result := 0;\r
59179 end;\r
59181 const TextTypes: array[ TRETextFormat ] of WORD = ( SF_RTF, SF_TEXT,\r
59182       SF_RTF or SFF_PLAINRTF, SF_RTFNOOBJS, SF_RTFNOOBJS or SFF_PLAINRTF,\r
59183       SF_TEXTIZED );\r
59185 //*\r
59186 //[function TControl.RE_SaveToStream]\r
59187 function TControl.RE_SaveToStream(Stream: PStream; Format: TRETextFormat;\r
59188   SelectionOnly: Boolean): Boolean;\r
59189 var ES: TEditStream;\r
59190     SelFlag: Integer;\r
59191 begin\r
59192   fREStream := Stream;\r
59193   ES.dwCookie := Integer( @Self );\r
59194   ES.dwError := 0;\r
59195   ES.pfnCallback := @REOut2Stream;\r
59196   SelFlag := 0;\r
59197   if SelectionOnly then\r
59198     SelFlag := SFF_SELECTION;\r
59199   Perform( EM_STREAMOUT, TextTypes[ Format ] or SelFlag, Integer( @ES ) );\r
59200   fREStream := nil;\r
59201   fREError := ES.dwError;\r
59202   Result := fREError = 0;\r
59203 end;\r
59205 //[procedure RE_AddText]\r
59206 procedure RE_AddText( Self_: PControl; const S: String );\r
59207 begin\r
59208   Self_.SelStart := Self_.TextSize;\r
59209   Self_.RE_Text[ reText, True ] := S;\r
59210 end;\r
59212 //*\r
59213 //[function TControl.REReadText]\r
59214 function TControl.REReadText(Format: TRETextFormat;\r
59215   SelectionOnly: Boolean): String;\r
59216 var B0: Integer;\r
59217     MS: PStream;\r
59218 begin\r
59219   fCommandActions.aAddText := RE_AddText;\r
59220   MS := NewMemoryStream;\r
59221   RE_SaveToStream( MS, Format, SelectionOnly );\r
59222   B0 := 0;\r
59223   MS.Write( B0, 1 );\r
59224   Result := PChar( MS.fMemory );\r
59225   MS.Free;\r
59226 end;\r
59228 //*\r
59229 //[function REInFromStream]\r
59230 function REInFromStream( Sender: PControl; Buf: PByte; Sz: DWORD; pSz: PInteger )\r
59231   :DWORD; stdcall;\r
59232 begin\r
59233   {$IFDEF _D3} if Sender.fREStrLoadLen >= 0 then {$ENDIF}\r
59234   if Sz > Sender.fREStrLoadLen then\r
59235     Sz := Sender.fREStrLoadLen;\r
59236   pSz^ := Sender.fREStream.Read( Buf^, Sz );\r
59237   Dec( Sender.fREStrLoadLen, pSz^ );\r
59238   if Assigned( Sender.fOnProgress ) then\r
59239     Sender.fOnProgress( Sender );\r
59240   Result := 0;\r
59241 end;\r
59243 //*\r
59244 //[function TControl.RE_LoadFromStream]\r
59245 function TControl.RE_LoadFromStream(Stream: PStream; Length: Integer;\r
59246   Format: TRETextFormat; SelectionOnly: Boolean): Boolean;\r
59247 var ES: TEditStream;\r
59248     SelFlag: Integer;\r
59249 begin\r
59250   fREStream := Stream;\r
59251   fREStrLoadLen := DWORD( Length );\r
59252   ES.dwCookie := Integer( @Self );\r
59253   ES.dwError := 0;\r
59254   ES.pfnCallback := @REInFromStream;\r
59255   SelFlag := 0;\r
59256   if SelectionOnly then\r
59257     SelFlag := SFF_SELECTION;\r
59258   Perform( EM_STREAMIN, TextTypes[ Format ] or SelFlag, Integer( @ES ) );\r
59259   fREStream := nil;\r
59260   fREError := ES.dwError;\r
59261   Result := fREError = 0;\r
59262 end;\r
59264 //*\r
59265 //[procedure TControl.REWriteText]\r
59266 procedure TControl.REWriteText(Format: TRETextFormat;\r
59267   SelectionOnly: Boolean; const Value: String);\r
59268 var MS: PStream;\r
59269 begin\r
59270   fCommandActions.aAddText := RE_AddText;\r
59271   MS := NewMemoryStream;\r
59272   MS.fMemory := PChar( Value );\r
59273   MS.fData.fSize := Length( Value );\r
59274   MS.fData.fCapacity := MS.fData.fSize;\r
59275   RE_LoadFromStream( MS, MS.fData.fSize, Format, SelectionOnly );\r
59276   MS.fMemory := nil;\r
59277   MS.Free;\r
59278 end;\r
59280 //*\r
59281 //[function TControl.RE_LoadFromFile]\r
59282 function TControl.RE_LoadFromFile(const Filename: String;\r
59283   Format: TRETextFormat; SelectionOnly: Boolean): Boolean;\r
59284 var Strm: PStream;\r
59285 begin\r
59286   Strm := NewReadFileStream( Filename );\r
59287   Result := RE_LoadFromStream( Strm, -1, Format, SelectionOnly );\r
59288   Strm.Free;\r
59289 end;\r
59291 //*\r
59292 //[function TControl.RE_SaveToFile]\r
59293 function TControl.RE_SaveToFile(const Filename: String;\r
59294   Format: TRETextFormat; SelectionOnly: Boolean): Boolean;\r
59295 var Strm: PStream;\r
59296 begin\r
59297   Strm := NewWriteFileStream( Filename );\r
59298   Result := RE_SaveToStream( Strm, Format, SelectionOnly );\r
59299   Strm.Free;\r
59300 end;\r
59302 //*\r
59303 //[function TControl.REGetParaFmt]\r
59304 function TControl.REGetParaFmt: TParaFormat;\r
59305 begin\r
59306   FillChar( Result, sizeof( TParaFormat2 ), 0 );\r
59307   Result.cbSize := sizeof( RichEdit.TParaFormat ) + fParaFmtDeltaSz;\r
59308   Perform( EM_GETPARAFORMAT, 0, Integer( @Result ) );\r
59309 end;\r
59311 //*\r
59312 //[procedure TControl.RESetParaFmt]\r
59313 procedure TControl.RESetParaFmt(const Value: TParaFormat);\r
59314 begin\r
59315   //Value.cbSize := szTParaFmtRec;\r
59316   Perform( EM_SETPARAFORMAT, 0, Integer( @Value ) );\r
59317 end;\r
59319 //*\r
59320 //[function TControl.REGetNumbering]\r
59321 function TControl.REGetNumbering: Boolean;\r
59322 begin\r
59323   Result := LongBool( ReGetParaAttr( 9 shl 16 ) );\r
59324 end;\r
59326 //*\r
59327 //[function TControl.REGetParaAttr]\r
59328 function TControl.REGetParaAttr( const Index: Integer ): Integer;\r
59329 var pDw : PDWORD;\r
59330 begin\r
59331   fREParaFmtRec := REGetParaFmt;\r
59332   pDw := Pointer( Integer( @fREParaFmtRec ) + ( HiWord( Index ) and $7E ) );\r
59333   Result := pDw^;\r
59334   if LongBool( HiWord( Index ) and 1 ) then\r
59335     Result := Result and $FFFF;\r
59336 end;\r
59338 //*\r
59339 //[function TControl.REGetParaAttrValid]\r
59340 function TControl.REGetParaAttrValid( const Index: Integer ): Boolean;\r
59341 begin\r
59342   Result := LongBool( ReGetParaAttr( 4 shl 16 ) and Index );\r
59343 end;\r
59345 //*\r
59346 //[function TControl.REGetTabCount]\r
59347 function TControl.REGetTabCount: Integer;\r
59348 begin\r
59349   Result := ReGetParaAttr( 27 shl 16 );\r
59350 end;\r
59352 //*\r
59353 //[function TControl.REGetTabs]\r
59354 function TControl.REGetTabs(Idx: Integer): Integer;\r
59355 begin\r
59356   Result := ReGetParaAttr( (28 + 4 * Idx) shl 16 );\r
59357 end;\r
59359 //*\r
59360 //[function TControl.REGetTextAlign]\r
59361 function TControl.REGetTextAlign: TRichTextAlign;\r
59362 begin\r
59363   Result := TRichTextAlign( ReGetParaAttr( 25 shl 16 ) - 1 );\r
59364 end;\r
59366 //*\r
59367 //[procedure TControl.RESetNumbering]\r
59368 procedure TControl.RESetNumbering(const Value: Boolean);\r
59369 begin\r
59370   RESetParaAttr( (9 shl 16) or PFM_NUMBERING, Integer( Value ) );\r
59371 end;\r
59373 //*\r
59374 //[procedure TControl.RESetParaAttr]\r
59375 procedure TControl.RESetParaAttr(const Index, Value: Integer);\r
59376 var pDw: PDWORD;\r
59377     Mask: Integer;\r
59378 begin\r
59379   REGetParaAttr( 0 );\r
59380   pDw := Pointer( Integer( @fREParaFmtRec ) + ( HiWord( Index ) and $7E ) );\r
59381   Mask := 0;\r
59382   if LongBool( HiWord( Index ) and 1 ) then\r
59383     Mask := Integer( $FFFF0000 );\r
59384   pDw^ := pDw^ and Mask or DWORD(Value);\r
59385   //////////////////////////////////////////////////////////////////////////////\r
59386     fREParaFmtRec.dwMask := Index and $8000FFFF;\r
59387   //////////////////////////////////////////////////////////////////////////////\r
59388   //fREParaFmtRec.dwMask := DWORD( Index ) or $8000FFFF;                      //\r
59389   //////////////////////////////////////////////////////////////////////////////\r
59390   RESetParaFmt( fREParaFmtRec );\r
59391 end;\r
59393 //*\r
59394 //[procedure TControl.RESetTabCount]\r
59395 procedure TControl.RESetTabCount(const Value: Integer);\r
59396 begin\r
59397   REGetParaAttr( 0 );\r
59398   RESetParaAttr( (27 shl 16) or PFM_TABSTOPS, Value );\r
59399 end;\r
59401 //*\r
59402 //[procedure TControl.RESetTabs]\r
59403 procedure TControl.RESetTabs(Idx: Integer; const Value: Integer);\r
59404 begin\r
59405   REGetParaAttr( 0 );\r
59406   RESetParaAttr( (28 + 4 * Idx) or PFM_TABSTOPS, Value );\r
59407 end;\r
59409 //*\r
59410 //[procedure TControl.RESetTextAlign]\r
59411 procedure TControl.RESetTextAlign(const Value: TRichTextAlign);\r
59412 begin\r
59413   RESetParaAttr( (25 shl 16) or PFM_ALIGNMENT, Ord( Value ) + 1 );\r
59414 end;\r
59416 //*\r
59417 //[function TControl.REGetStartIndentValid]\r
59418 function TControl.REGetStartIndentValid: Boolean;\r
59419 begin\r
59420   Result := REGetParaAttrValid( Integer( PFM_STARTINDENT ) );\r
59421 end;\r
59423 //*\r
59424 //[procedure TControl.RE_HideSelection]\r
59425 procedure TControl.RE_HideSelection(aHide: Boolean);\r
59426 begin\r
59427   Perform( EM_HIDESELECTION, Integer( aHide ), 1 );\r
59428 end;\r
59430 //*\r
59431 //[function TControl.RE_SearchText]\r
59432 function TControl.RE_SearchText(const Value: String; MatchCase,\r
59433   WholeWord, ScanForward: Boolean; SearchFrom, SearchTo: Integer): Integer;\r
59434 var Flags: Integer;\r
59435     FT: TFindText;\r
59436 begin\r
59437   Flags := Integer( ScanForward );\r
59438   if WholeWord then Flags := Flags or FT_WHOLEWORD;\r
59439   if MatchCase then Flags := Flags or FT_MATCHCASE;\r
59440   FT.chrg.cpMin := SearchFrom;\r
59441   FT.chrg.cpMax := SearchTo;\r
59442   FT.lpstrText := PChar( Value );\r
59443   Result := Perform( EM_FINDTEXT, Flags, Integer( @FT ) );\r
59444 end;\r
59446 //*\r
59447 //[function TControl.CanUndo]\r
59448 function TControl.CanUndo: Boolean;\r
59449 begin\r
59450   Result := LongBool( Perform( EM_CANUNDO, 0, 0 ) );\r
59451 end;\r
59453 //*\r
59454 //[procedure TControl.EmptyUndoBuffer]\r
59455 procedure TControl.EmptyUndoBuffer;\r
59456 begin\r
59457   Perform( EM_EMPTYUNDOBUFFER, 0, 0 );\r
59458 end;\r
59460 //*\r
59461 //[function TControl.Undo]\r
59462 function TControl.Undo: Boolean;\r
59463 begin\r
59464   Result := LongBool( Perform( EM_UNDO, 0, 0 ) );\r
59465 end;\r
59467 //*\r
59468 //[function TControl.RE_Redo]\r
59469 function TControl.RE_Redo: Boolean;\r
59470 begin\r
59471   Result := LongBool( Perform( EM_REDO, 0, 0 ) );\r
59472 end;\r
59474 //*\r
59475 //[function TControl.REGetAutoURLDetect]\r
59476 function TControl.REGetAutoURLDetect: Boolean;\r
59477 begin\r
59478   Result := LongBool( Perform( EM_GETAUTOURLDETECT, 0, 0 ) );\r
59479 end;\r
59481 //*\r
59482 //[procedure TControl.RESetAutoURLDetect]\r
59483 procedure TControl.RESetAutoURLDetect(const Value: Boolean);\r
59484 begin\r
59485   AttachProc( WndProc_RE_LinkNotify );\r
59486   Perform( EM_AUTOURLDETECT, Integer( Value ), 0 );\r
59487 end;\r
59489 //*\r
59490 //[function TControl.GetMaxTextSize]\r
59491 function TControl.GetMaxTextSize: DWORD;\r
59492 begin\r
59493   Result := Perform( EM_GETLIMITTEXT, 0, 0 );\r
59494 end;\r
59496 //*\r
59497 //[procedure TControl.SetMaxTextSize]\r
59498 procedure TControl.SetMaxTextSize(const Value: DWORD);\r
59499 var V1, V2: Integer;\r
59500 begin\r
59501   if fCommandActions.aSetLimit <> 0 then\r
59502   begin\r
59503     V1 := 0; V2 := Value;\r
59504     if fCommandActions.aSetLimit = EM_SETLIMITTEXT then\r
59505     begin\r
59506       V1 := Value; V2 := 0;\r
59507     end;\r
59508     Perform( fCommandActions.aSetLimit, V1, V2 );\r
59509   end;\r
59510 end;\r
59512 //*\r
59513 //[function WndProc_REFmt]\r
59514 function WndProc_REFmt( _Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
59515 var Mask: Integer;\r
59516     Shft, Flg: Boolean;\r
59517     Delta: Integer;\r
59518     TA: TRichTextAlign;\r
59519     ChgTA: Boolean;\r
59520     US: TRichUnderline;\r
59521     NS: TRichNumbering;\r
59522     NB: TRichNumBrackets;\r
59523     Side: TBorderEdge;\r
59524     Param: DWORD;\r
59525 begin\r
59526   Result := False;\r
59527   if Msg.message = WM_CHAR then\r
59528   if _Self_.FSupressTab then\r
59529   begin\r
59530     _Self_.FSupressTab := FALSE;\r
59531     if Msg.wParam = 9 then\r
59532     begin\r
59533       Result := TRUE;\r
59534       Exit;\r
59535     end;\r
59536   end;\r
59538   if Msg.message = WM_KEYDOWN then\r
59539   if GetKeyState( VK_CONTROL ) < 0 then\r
59540   begin\r
59541     Shft := GetKeyState( VK_SHIFT ) < 0;\r
59542     Rslt := 0;\r
59543     Result := True;\r
59544     Mask := 0;\r
59545     ChgTA := False; TA := raLeft;\r
59546     Param := Msg.wParam;\r
59547     //Msg.wParam := 0;\r
59548     case Param of\r
59549     Integer('Z'):\r
59550       begin\r
59551         if Shft then\r
59552         begin\r
59553           _Self_.RE_Redo;\r
59554           Exit;\r
59555         end;\r
59556         Result := False;\r
59557       end;\r
59559     Integer('L'): begin ChgTA := True; TA := raLeft; end;\r
59560     Integer('R'): begin ChgTA := True; TA := raRight; end;\r
59561     Integer('E'): begin ChgTA := True; TA := raCenter; end;\r
59562     Integer('J'): begin ChgTA := True; TA := raJustify; end;\r
59563     Integer('N'): begin\r
59564                     if Shft then\r
59565                     begin\r
59566                       NS := _Self_.RE_NumStyle;\r
59567                       NB := _Self_.RE_NumBrackets;\r
59568                       if NS = rnBullets then\r
59569                       begin\r
59570                         _Self_.RE_NumStyle := rnNone;\r
59571                         Exit;\r
59572                       end;\r
59573                       if NS = rnNone then\r
59574                       begin\r
59575                         _Self_.RE_NumStyle := rnBullets;\r
59576                         //NB := rnbPlain;\r
59577                         Exit;\r
59578                       end\r
59579                          else\r
59580                       if Ord( NB ) = 0  then\r
59581                         NB := High(NB)  else\r
59582                         NB := Pred(NB);\r
59583                       _Self_.RE_NumBrackets := NB;\r
59584                     end\r
59585                        else\r
59586                     begin\r
59587                       NS := _Self_.RE_NumStyle;\r
59588                       if Ord( NS ) = 0 then\r
59589                       begin\r
59590                         NS := rnURoman; //rnULetter; //High( NS );\r
59591                         { because rnLRoman, rnURoman, rnNoNumber are not shown\r
59592                           in RichEdit. }\r
59593                         _Self_.RE_NumBrackets := rnbPeriod;\r
59594                       end              else\r
59595                         NS := Pred(NS);\r
59596                       _Self_.RE_NumStyle := NS;\r
59597                       if NS in [ rnLRoman, rnURoman, rnArabic ] then\r
59598                         _Self_.RE_NumStart := 1;\r
59599                     end;\r
59600                     Exit;\r
59601                   end;\r
59602     Integer('W'): begin\r
59603                     Delta := _Self_.RE_BorderWidth[ beLeft ] + 4;\r
59604                     if Shft then Delta := -1;\r
59605                     for Side := Low(Side) to High(Side) do\r
59606                     begin\r
59607                       if Delta < 0 then\r
59608                         _Self_.RE_BorderStyle[ Side ] := _Self_.RE_BorderStyle[ Side ] + 1\r
59609                       else\r
59610                       begin\r
59611                         _Self_.RE_BorderWidth[ Side ] := Delta;\r
59612                         _Self_.RE_BorderSpace[ Side ] := Delta;\r
59613                       end;\r
59614                     end;\r
59615                     Exit;\r
59616                   end;\r
59617     (* TABLES STUFF -- to try, uncomment it and press CTRL+T in RichEdit.\r
59618        (and uncomment declaration for Tmp above).\r
59620        Not finished, and seems no way to figure it out - even RichEdit20.dll\r
59621        (i.e. Rich Edit v3.0) can not display tables properly formatted. :(((\r
59623     Integer('T'): begin\r
59624                     if _Self_.RE_Table then\r
59625                     begin\r
59626                       //MsgOK( 'table' );\r
59627                     end;\r
59628                     Tmp := _Self_.REReadText( reRTF, True );\r
59629                     if StrIsStartingFrom( PChar(Tmp), '{\rtf' )\r
59630                     and (CopyTail( Tmp, 3 ) = '}'#$D#$A) then\r
59631                     begin\r
59632                       //Tmp := Copy( Tmp, 1, Length(Tmp) - 3 );\r
59633                       _Self_.RE_Text[ reRTF, True ] :=  '{\rtf1' + //Copy( Tmp, 1, 6 ) +\r
59634     '\trowd' +\r
59635     //'\lytcalctblwd' +\r
59636     //'\oldlinewrap' +\r
59637     //'\alntblind' +\r
59638     //'\trgaph108' +\r
59639     '\trleft-108' +\r
59640     {'\trbrdrt\brdrs\brdrw10' +\r
59641     '\trbrdrl\brdrs\brdrw10' +\r
59642     '\trbrdrb\brdrs\brdrw10' +\r
59643     '\trbrdrr\brdrs\brdrw10' +\r
59644     '\trbrdrh\brdrs\brdrw10' +\r
59645     '\trbrdrv\brdrs\brdrw10' +}\r
59646     //'\clvertalt' +\r
59647     {'\clbrdrt\brdrs\brdrw10' +\r
59648     '\clbrdrl\brdrs\brdrw10' +\r
59649     '\clbrdrb\brdrs\brdrw10' +\r
59650     '\clbrdrr\brdrs\brdrw10' +}\r
59651     //'\cltxlrtb' +\r
59652     '\cellx1414' +\r
59653     //'\pard' +\r
59654     //'\plain' +\r
59655     //'\widctlpar' +\r
59656     '\trautofit1' +\r
59657     '\intbl' +\r
59658     //'\adjustright' +\r
59659     //'\fs20\lang1049' +\r
59660     //'\cgrid' +\r
59661     '\trrh0' +\r
59662     '{\clFitText{{\box\brdrs\brdrw20\brsp20}'+\r
59663     '\par}\cell\row}' +\r
59664     //'\pard\widctlpar' +\r
59665     //'\intbl'+\r
59666     //'\adjustright'+\r
59667     //'{\row}' +\r
59668     '\pard\widctlpar' +\r
59669                              '}'#$D#$A;\r
59670                       _Self_.Perform( WM_KEYDOWN, VK_UP, 0 );\r
59671                       _Self_.Perform( WM_KEYUP, VK_UP, 0 );\r
59672                     end;\r
59673                     Exit;\r
59674                   end;\r
59675     *)\r
59676     Integer('B'): Mask := CFM_BOLD;\r
59677     Integer('I'):\r
59678       begin\r
59679         Mask := CFM_ITALIC;\r
59680         _Self_.FSupressTab := TRUE;\r
59681       end;\r
59682     Integer('U'):\r
59683       begin\r
59684         if Shft then\r
59685         begin\r
59686           US := _Self_.RE_FmtUnderlineStyle;\r
59687           if Ord(US) = 0 then US := High(TRichUnderLine)\r
59688           else US := Pred( US );\r
59689           _Self_.RE_FmtUnderlineStyle := US;\r
59690           Exit;\r
59691         end;\r
59692         Mask := CFM_UNDERLINE;\r
59693       end;\r
59694     Integer('O'): Mask := CFM_STRIKEOUT;\r
59695     VK_SUBTRACT, VK_ADD: Mask := Integer( CFM_SIZE );\r
59696     else\r
59697       begin\r
59698         Result := False;\r
59699         Msg.wParam := Param;\r
59700       end;\r
59701     end;\r
59702     if not Result then Exit;\r
59704     if ChgTA then\r
59705       begin\r
59706         if Shft then Result := False\r
59707         else _Self_.RE_TextAlign := TA;\r
59708         Exit;\r
59709       end;\r
59711     _Self_.REGetFont;\r
59712     if Mask > 0 then\r
59713     begin\r
59714       if Shft then Result := False\r
59715       else begin\r
59716              Flg := _Self_.REGetFontEffects( Mask );\r
59717              if not Flg then\r
59718                _Self_.fRECharFormatRec.dwEffects := _Self_.fRECharFormatRec.dwEffects and not Mask;\r
59719              _Self_.fRECharFormatRec.dwEffects := _Self_.fRECharFormatRec.dwEffects xor DWORD(Mask);\r
59720            end;\r
59721     end\r
59722        else\r
59723     begin\r
59724       if Msg.wParam = VK_SUBTRACT then\r
59725         Delta := -1\r
59726       else\r
59727         Delta := 1;\r
59728       if Shft then\r
59729         Mask := CFM_OFFSET;\r
59730       if Shft then\r
59731         Inc( _Self_.fRECharFormatRec.yOffset, Delta * _Self_.fRECharFormatRec.yHeight div 3 )\r
59732       else\r
59733         Inc( _Self_.fRECharFormatRec.yHeight, Delta * _Self_.fRECharFormatRec.yHeight div 8 );\r
59734       Flg := LongBool( _Self_.fRECharFormatRec.dwMask and Mask );\r
59735       if not Flg then\r
59736         _Self_.fRECharFormatRec.yOffset := 0;\r
59737     end;\r
59738     _Self_.fRECharFormatRec.dwMask := Mask;\r
59739     _Self_.Perform( EM_SETCHARFORMAT, SCF_SELECTION { RichAreas[ _Self_.fRECharArea ] }, Integer( @_Self_.fRECharFormatRec ) );\r
59740   end;\r
59741 end;\r
59743 //*\r
59744 //[function TControl.RE_FmtStandard]\r
59745 function TControl.RE_FmtStandard: PControl;\r
59746 begin\r
59747   AttachProc( WndProc_REFmt );\r
59748   Result := @Self;\r
59749 end;\r
59751 //[FUNCTION EnumDynHandlers]\r
59752 {$IFDEF ASM_VERSION}\r
59753 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
59754 asm     //cmd    //opd\r
59755         CMP      [EAX].TControl.fRefCount, 0\r
59756         JL       @@fin_false\r
59757         PUSHAD\r
59758         MOV      EBX, EAX\r
59759         MOV      EBP, ECX\r
59760         MOV      ECX, [EBX].TControl.fDynHandlers\r
59761         JECXZ    @@ret_false\r
59762         MOV      ESI, ECX\r
59763         MOV      ECX, [ESI].TList.fCount\r
59764         JECXZ    @@ret_false\r
59765         MOV      EDI, ECX\r
59766         SHR      EDI, 1\r
59767         CALL     TControl.RefInc\r
59768 @@loo:  DEC      EDI\r
59769         JS       @@e_loo\r
59770         PUSH     EDX\r
59771         PUSH     EBX\r
59772 {$IFNDEF ENUM_DYN_HANDLERS_AFTER_RUN}\r
59773         XOR      EAX, EAX\r
59774         CMP      [AppletTerminated], AL\r
59775         JZ       @@do_call\r
59776         MOV      ECX, [ESI].TList.fItems\r
59777         MOV      ECX, [ECX+EDI*8+4]\r
59778         JECXZ    @@skip_call\r
59779 {$ENDIF}\r
59780 @@do_call:\r
59781         MOV      EAX, [ESI].TList.fItems\r
59782         MOV      EAX, [EAX+EDI*8]\r
59783         XCHG     EAX, EBX\r
59784         MOV      ECX, EBP\r
59785         CALL     EBX\r
59786 @@skip_call:\r
59787         POP      EBX\r
59788         POP      EDX\r
59789         TEST     AL, AL\r
59790         JZ       @@loo\r
59791 @@ret_true:\r
59792         MOV      EAX, EBX\r
59793         CALL     TControl.RefDec\r
59794         POPAD\r
59795         MOV      AL, 1\r
59796         RET\r
59797 @@e_loo:\r
59798         XOR      EAX, EAX\r
59799         INC      EAX\r
59800         CMP      [EBX].TControl.fRefCount, EAX\r
59801         JE       @@ret_true\r
59802         MOV      EAX, EBX\r
59803         CALL     TControl.RefDec\r
59804 @@ret_false:\r
59805         POPAD\r
59806 @@fin_false:\r
59807         XOR      EAX, EAX\r
59808 end;\r
59809 {$ELSE ASM_VERSION} //Pascal\r
59810 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
59811 var I: Integer;\r
59812     Proc: TWindowFunc;\r
59813 begin\r
59814   Result := False;\r
59815   if Self_.fRefCount < 0 then Exit;\r
59816   if (Self_.fDynHandlers = nil) or (Self_.fDynHandlers.fCount = 0) then Exit;\r
59817   Self_.RefInc; // Prevent destroying Self_\r
59818   for I := Self_.fDynHandlers.fCount div 2 - 1 downto 0 do\r
59819   begin\r
59820     Proc := Self_.fDynHandlers.fItems[ I * 2 ];\r
59821 {$IFNDEF ENUM_DYN_HANDLERS_AFTER_RUN}\r
59822     if not AppletTerminated or (Self_.fDynHandlers.fItems[ I * 2 + 1 ] <> nil) then\r
59823 {$ENDIF}\r
59824     if Proc( Self_, Msg, Rslt ) then\r
59825     begin\r
59826       Result := True;\r
59827       break;\r
59828     end;\r
59829   end;\r
59830   {$IFDEF DEBUG_ENDSESSION}\r
59831   if EndSession_Initiated then\r
59832   begin\r
59833     LogFileOutput( GetStartDir + 'es_debug.txt',\r
59834                    'ENUM_DYN_HANDLERS: Self_:' + Int2Hex( DWORD( Self_ ), 8 ) );\r
59835     LogFileOutput( GetStartDir + 'es_debug.txt',\r
59836                    'ENUM_DYN_HANDLERS: Self_.fRefCount:' + Int2Str( Self_.fRefCount ) );\r
59837   end;\r
59838   {$ENDIF}\r
59839   if LongBool(Self_.fRefCount and 1) then\r
59840     Result := True; // If Self_ will be destroyed now, stop further processing\r
59841   Self_.RefDec; // Destroy Self_, if Free was called for it while processing attached procedures\r
59842 end;\r
59843 {$ENDIF ASM_VERSION}\r
59844 //[END EnumDynHandlers]\r
59846 {$IFDEF ASM_VERSION}\r
59847 //[procedure TControl.AttachProcEx]\r
59848 procedure TControl.AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );\r
59849 asm     //cmd    //opd\r
59850         PUSH     EBX\r
59851         PUSH     EDI\r
59852         PUSH     ECX\r
59853         XCHG     EBX, EAX\r
59854         MOV      EDI, EDX\r
59855         MOV      [EBX].fOnDynHandlers, offset[EnumDynHandlers]\r
59856         MOV      ECX, [EBX].TControl.fDynHandlers\r
59857         INC      ECX\r
59858         LOOP     @@1\r
59859         CALL     NewList\r
59860         XCHG     ECX, EAX\r
59861         MOV      [EBX].TControl.fDynHandlers, ECX\r
59862 @@1:\r
59863         PUSH     ECX\r
59864         MOV      EAX, EBX\r
59865         MOV      EDX, EDI\r
59866         CALL     TControl.IsProcAttached\r
59867         TEST     AL, AL\r
59868         POP      EBX\r
59869         JNZ      @@exit\r
59870         MOV      EAX, EBX\r
59871         MOV      EDX, EDI\r
59872         CALL     TList.Add\r
59873         XCHG     EAX, EBX\r
59874         POP      EDX\r
59875         PUSH     EDX\r
59876         CALL     TList.Add\r
59877 @@exit:\r
59878         POP      ECX\r
59879         POP      EDI\r
59880         POP      EBX\r
59881 end;\r
59882 {$ELSE ASM_VERSION} //Pascal\r
59883 procedure TControl.AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );\r
59884 begin\r
59885   if fDynHandlers = nil then\r
59886     fDynHandlers := NewList;\r
59887   if not IsProcAttached( Proc ) then\r
59888   begin\r
59889     fDynHandlers.Add( @Proc );\r
59890     fDynHandlers.Add( Pointer( Integer( ExecuteAfterAppletTerminated ) ) );\r
59891   end;\r
59892   fOnDynHandlers := EnumDynHandlers;\r
59893 end;\r
59894 {$ENDIF ASM_VERSION}\r
59896 //[procedure TControl.AttachProc]\r
59897 procedure TControl.AttachProc(Proc: TWindowFunc);\r
59898 begin\r
59899   AttachProcEx( Proc, FALSE );\r
59900 end;\r
59902 //*\r
59903 //[procedure TControl.DetachProc]\r
59904 procedure TControl.DetachProc(Proc: TWindowFunc);\r
59905 var I: Integer;\r
59906 begin\r
59907   if fDynHandlers = nil then Exit;\r
59908   I := fDynHandlers.IndexOf( @Proc );\r
59909   if I >=0 then\r
59910   begin\r
59911     fDynHandlers.Delete( I );\r
59912     fDynHandlers.Delete( I );\r
59913   end;\r
59914 end;\r
59916 {$IFDEF ASM_VERSION}\r
59917 //[function TControl.IsProcAttached]\r
59918 function TControl.IsProcAttached(Proc: TWindowFunc): Boolean;\r
59919 asm     //cmd    //opd\r
59920         MOV      ECX, [EAX].TControl.fDynHandlers\r
59921         JECXZ    @@exit\r
59922         XCHG     EAX, ECX\r
59923         CALL     TList.IndexOf\r
59924         TEST     EAX, EAX\r
59925         SETGE    CL\r
59926 @@exit: XCHG     EAX, ECX\r
59927 end;\r
59928 {$ELSE ASM_VERSION} //Pascal\r
59929 function TControl.IsProcAttached(Proc: TWindowFunc): Boolean;\r
59930 var I: Integer;\r
59931 begin\r
59932   Result := False;\r
59933   if fDynHandlers = nil then Exit;\r
59934   I := fDynHandlers.IndexOf( @Proc );\r
59935   Result := I >=0;\r
59936 end;\r
59937 {$ENDIF ASM_VERSION}\r
59939 //[function WndProcAutoPopupMenu]\r
59940 function WndProcAutoPopupMenu( Control: PControl; var Msg: TMsg; var MsgRslt: Integer ): Boolean;\r
59941 var R: TRect;\r
59942     M: Word;\r
59943     I: Integer;\r
59944     P: TPoint;\r
59945 begin\r
59946   if (Msg.message = WM_CONTEXTMENU) and\r
59947      (Control.fAutoPopupMenu <> nil) then\r
59948   begin\r
59949     {$IFDEF USE_MENU_CURCTL}\r
59950     PMenu( Control.fAutoPopupMenu ).fCurCtl := Control;\r
59951     {$ENDIF USE_MENU_CURCTL}\r
59952     P.X := SmallInt( LoWord( Msg.lParam ) );\r
59953     P.Y := SmallInt( HiWord( Msg.lParam ) );\r
59954     if (Msg.lParam = -1) then\r
59955     begin\r
59956       I := Control.CurIndex;\r
59957       M := Control.fCommandActions.aItem2XY;\r
59958       if (I >= 0) and (M <> 0) then\r
59959       begin\r
59960         CASE M OF\r
59961         EM_POSFROMCHAR:\r
59962           begin\r
59963             I := Control.SelStart + Control.SelLength;\r
59964             // Edit or Rich Edit 2:\r
59965             I := Control.Perform( M, I, 1 );\r
59966             P.X := SmallInt( LoWord( I ) );\r
59967             P.Y := SmallInt( HiWord( I ) );\r
59968           end;\r
59969         LB_GETITEMRECT, LVM_GETITEMRECT, TCM_GETITEMRECT:\r
59970           begin\r
59971             R.Left := LVIR_BOUNDS;\r
59972             Control.Perform( M, I, Integer( @ R ) );\r
59973             P.X := R.Left;\r
59974             P.Y := R.Bottom;\r
59975           end;\r
59976         TVM_GETITEMRECT:\r
59977           begin\r
59978             I := Control.TVSelected;\r
59979             R.Left := I;\r
59980             Control.Perform( M, 1, Integer( @ R ) );\r
59981             P.X := R.Left;\r
59982             P.Y := R.Bottom;\r
59983           end;\r
59984         END;\r
59985         R := Control.ClientRect;\r
59986         if P.X < R.Left then P.X := R.Left;\r
59987         if P.X > R.Right then P.X := R.Right;\r
59988         if P.Y < R.Top then P.Y := R.Top;\r
59989         if P.Y > R.Bottom then P.Y := R.Bottom;\r
59990       end;\r
59991       P := Control.Client2Screen( P );\r
59992     end;\r
59993     PMenu( Control.fAutoPopupMenu ).Popup( P.X, P.Y );\r
59994     Result := TRUE;\r
59995   end\r
59996     else\r
59997   Result := FALSE;\r
59998 end;\r
60000 //[procedure TControl.SetAutoPopupMenu]\r
60001 procedure TControl.SetAutoPopupMenu(PopupMenu: PObj);\r
60002 { new version - by Alexander Pravdin. Allows to attach a submenu (e.g. of the\r
60003   main menu) as a popup menu to a control, to avoid duplicating menu object,\r
60004   if it is the same already as desired. }\r
60005 var pm: PMenu;\r
60006 begin\r
60007   if PopupMenu <> nil then\r
60008   {$IFDEF USE_MENU_CURCTL}\r
60009   begin\r
60010     pm := PMenu( PopupMenu );\r
60011     if ( pm.FParent <> nil ) then\r
60012     begin\r
60013       while pm.FControl = nil do\r
60014         pm := pm.FParent;\r
60015       PMenu( PopupMenu ).FControl := pm.FControl;\r
60016     end\r
60017     else\r
60018     begin\r
60019       PMenu( PopupMenu ).FControl := @Self;\r
60020     end;\r
60021     AttachProc(WndProcAutoPopupMenu);\r
60022     AttachProc(WndProcMenu)\r
60023   end\r
60024   else begin\r
60025     DetachProc(WndProcAutoPopupMenu);\r
60026     DetachProc(WndProcMenu);\r
60027   end;\r
60028   {$ELSE}\r
60029   begin\r
60030     pm := PMenu( PopupMenu );\r
60031     while pm.FControl = nil do pm := pm.Parent;\r
60032     PMenu( PopupMenu ).FControl := pm.FControl;\r
60033   end;\r
60034   {$ENDIF}\r
60035   fAutoPopupMenu := PopupMenu;\r
60036   {$IFNDEF USE_MENU_CURCTL}\r
60037   AttachProc( WndProcAutoPopupMenu );\r
60038   {$ENDIF}\r
60039 end;\r
60041 //[function SearchAnsiMnemonics]\r
60042 function SearchAnsiMnemonics( const S: String ): String;\r
60043 var I: Integer;\r
60044     Sh: ShortInt;\r
60045 begin\r
60046   Result := S;\r
60047   for I := 1 to Length( Result ) do\r
60048   begin\r
60049     Sh := VkKeyScanEx( Result[ I ], MnemonicsLocale );\r
60050     if Sh <> -1 then\r
60051       Result[ I ] := Char( Sh );\r
60052   end;\r
60053 end;\r
60055 //[procedure SupportAnsiMnemonics]\r
60056 procedure SupportAnsiMnemonics( LocaleID: Integer );\r
60057 begin\r
60058   MnemonicsLocale := LocaleID;\r
60059   SearchMnemonics := SearchAnsiMnemonics;\r
60060 end;\r
60062 //[function WndProcMnemonics]\r
60063 function WndProcMnemonics( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60064 var Form: PControl;\r
60066   function HandleMnenonic( Prnt: PControl ): Boolean;\r
60067   var C: PControl;\r
60068       XY: Integer;\r
60069       procedure DoPressMnemonic;\r
60070       begin\r
60071         if Msg.message = WM_SYSKEYDOWN then\r
60072         begin\r
60073           Form.FPressedMnemonic := Msg.wParam;\r
60074           C.Perform( WM_LBUTTONDOWN, MK_LBUTTON, XY );\r
60075         end\r
60076           else\r
60077         begin\r
60078           Form.FPressedMnemonic := 0;\r
60079           C.Perform( WM_LBUTTONUP, MK_LBUTTON, XY );\r
60080         end;\r
60081       end;\r
60082   var I, J: Integer;\r
60083       R: TRect;\r
60084   begin\r
60085     for I := 0 to Prnt.ChildCount-1 do\r
60086     begin\r
60087       C := Prnt.Children[ I ];\r
60088       if C.IsButton then\r
60089       if C.Enabled then\r
60090       begin\r
60091         if C.fCommandActions.aGetCount = TB_BUTTONCOUNT then\r
60092         for J := 0 to C.Count-1 do\r
60093         begin\r
60094           if C.TBButtonEnabled[ J ] then\r
60095           if pos( '&' + Char( Msg.wParam ), SearchMnemonics( C.TBButtonText[ J ] ) ) > 0 then\r
60096           begin\r
60097             C.fCurIndex := J;\r
60098             C.fCurItem := C.TBIndex2Item( J );\r
60099             R := C.TBButtonRect[ J ];\r
60100             XY := R.Left or (R.Top shl 16);\r
60101             DoPressMnemonic;\r
60102             Result := TRUE;\r
60103             Exit;\r
60104           end;\r
60105         end;\r
60106         if pos( '&' + Char( Msg.wParam ), SearchMnemonics( C.Caption ) ) > 0 then\r
60107         begin\r
60108           XY := 0;\r
60109           DoPressMnemonic;\r
60110           Result := TRUE;\r
60111           Exit;\r
60112         end;\r
60113       end;\r
60114       if HandleMnenonic( C ) then\r
60115       begin\r
60116         Result := TRUE;\r
60117         Exit;\r
60118       end;\r
60119     end;\r
60120     Result := FALSE;\r
60121   end;\r
60123 {$IFDEF NEW_MENU_ACCELL}\r
60124   function FindByCtlRef(C: PControl; Accell: TMenuAccelerator): Boolean;\r
60126     function FindInMenu(M: PMenu): PMenu;\r
60127     var\r
60128       I: Integer;\r
60129       SM: PMenu;\r
60130     begin\r
60131       for I := 0 to M.FItems.Count - 1 do begin\r
60132         Result := M.FItems.Items[I];\r
60133         if (Cardinal(Result.Accelerator) = Cardinal(Accell)) and Result.Enabled then\r
60134           Exit;\r
60135       end;\r
60136       Result := nil;\r
60137       for I := 0 to M.FItems.Count - 1 do begin\r
60138         SM := PMenu(M.FItems.Items[I]);\r
60139         if (SM.FItems.Count > 0) then\r
60140           Result := FindInMenu(SM);\r
60141         if (Result <> nil) then\r
60142           Break;\r
60143       end;\r
60144     end;\r
60146     function FindInMenu2(M: PMenu): Boolean;\r
60147     var\r
60148       MI: PMenu;\r
60149     begin\r
60150       if (M <> nil) then begin\r
60151         MI := FindInMenu(M);\r
60152         if (MI <> nil) then begin\r
60153           //M.FControl.Perform(WM_COMMAND, MI.FId, 0);\r
60154           C.Perform(WM_COMMAND, MI.FId, 0); // fixed\r
60155           Result := True;\r
60156           Exit;\r
60157         end;\r
60158       end;\r
60159       Result := False;\r
60160     end;\r
60162   var\r
60163     Parent: PControl;\r
60164   begin\r
60165     Result := False;\r
60166     if not FindInMenu2(PMenu(C.fAutoPopupMenu)) then\r
60167       if not FindInMenu2(PMenu(C.fMenuObj)) then begin\r
60168         Parent := C.Parent;\r
60169         if (Parent <> nil) then\r
60170           Result := FindByCtlRef(Parent, Accell);\r
60171       end;\r
60172   end;\r
60174 var\r
60175   Ac: TMenuAccelerator;\r
60176 {$ENDIF}\r
60177 begin\r
60178   Result := FALSE;\r
60179   if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then\r
60180   begin\r
60181 {$IFDEF NEW_MENU_ACCELL}\r
60182     Ac := MakeAccelerator(FVIRTKEY or GetShiftState, Msg.wParam);\r
60183     Result := FindByCtlRef(Sender, Ac);\r
60184 {$ELSE}\r
60185     if Sender.fAccelTable <> 0 then\r
60186       Result := LongBool( TranslateAccelerator( Sender.fHandle, Sender.fAccelTable, Msg ) );\r
60187     if not Result then\r
60188     begin\r
60189       if Sender.fCurrentControl <> nil then\r
60190       if Sender.fCurrentControl.fAccelTable <> 0 then\r
60191         Result := LongBool( TranslateAccelerator( Sender.fCurrentControl.fHandle,\r
60192                             Sender.fCurrentControl.fAccelTable, Msg ) );\r
60193     end;\r
60194     if not Result then\r
60195     begin\r
60196       Form := Sender.ParentForm;\r
60197       if Form <> nil then\r
60198       if Form.fAccelTable <> 0 then\r
60199         Result := LongBool( TranslateAccelerator( Form.fHandle,\r
60200                             Form.fAccelTable, Msg ) );\r
60201     end;\r
60202 {$ENDIF}\r
60203   end;\r
60204   if Result then Exit;\r
60205   if (Msg.message = WM_SYSKEYUP) or\r
60206      (Msg.message = WM_SYSKEYDOWN) and (GetKeyState( VK_MENU ) < 0) then\r
60207   begin\r
60208     Rslt := 0;\r
60209     Form := Sender.ParentForm;\r
60210     if Form <> nil then\r
60211     begin\r
60212       { ----------------------- }\r
60213       //Form.Caption := Form.Caption + '<';\r
60214         if Char( Msg.wParam ) in [ 'A'..'Z', '0'..'9' ] then\r
60215         begin\r
60216           if HandleMnenonic( Form ) then\r
60217           begin\r
60218             Result := TRUE;\r
60219             Exit;\r
60220           end\r
60221             else\r
60222           begin\r
60223             { ---------------------- }\r
60224             //Form.Caption := Form.Caption + '?';\r
60225           end;\r
60226         end;\r
60227     end;\r
60228   end\r
60229     else\r
60230   if Msg.message = WM_KEYUP then\r
60231   begin\r
60232     Rslt := 0;\r
60233     Form := Sender.ParentForm;\r
60234     if Form <> nil then\r
60235     begin\r
60236       { ------------------------ }\r
60237       //Form.Caption := Form.Caption + '>';\r
60238         if Msg.wParam = VK_MENU then\r
60239         begin\r
60240               if Form.FPressedMnemonic <> 0 then\r
60241                 Form.FPressedMnemonic := Form.FPressedMnemonic or $80000000;\r
60242         end\r
60243           else\r
60244         if Char( Msg.wParam ) in [ 'A'..'Z', '0'..'9' ] then\r
60245         begin\r
60246             if HandleMnenonic( Form ) then\r
60247             begin\r
60248               Result := TRUE;\r
60249               Exit;\r
60250             end\r
60251               else\r
60252             begin\r
60253               { --------------------- }\r
60254               //Form.Caption := form.Caption + '-';\r
60255             end;\r
60256         end;\r
60257     end;\r
60258   end;\r
60259   Result := FALSE;\r
60260 end;\r
60262 //[function TControl.SupportMnemonics]\r
60263 function TControl.SupportMnemonics: PControl;\r
60264 begin\r
60265   fGlobalProcKeybd := WndProcMnemonics;\r
60266   Result := @Self;\r
60267 end;\r
60269 //*\r
60270 //[API RevokeDragDrop]\r
60271 function RevokeDragDrop(wnd: HWnd): HResult; stdcall;\r
60272   external 'ole32.dll' name 'RevokeDragDrop';\r
60274 //*\r
60275 //[function TControl.RE_NoOLEDragDrop]\r
60276 function TControl.RE_NoOLEDragDrop: PControl;\r
60277 begin\r
60278   RevokeDragDrop( Handle );\r
60279   Result := @Self;\r
60280 end;\r
60282 //*\r
60283 //[function WndProcOnResize]\r
60284 function WndProcOnResize( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60285 begin\r
60286   if Msg.message = WM_SIZE then\r
60287   begin\r
60288     if Assigned( Self_.fOnResize ) then\r
60289       Self_.fOnResize( Self_ );\r
60290   end;\r
60291   Result := False;\r
60292 end;\r
60294 //*\r
60295 //[procedure TControl.SetOnResize]\r
60296 procedure TControl.SetOnResize(const Value: TOnEvent);\r
60297 begin\r
60298   FOnResize := Value;\r
60299   AttachProc( WndProcOnResize );\r
60300 end;\r
60302 //[function WndProcMove]\r
60303 function WndProcMove( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60304 begin\r
60305   if Msg.message = WM_MOVE then\r
60306   begin\r
60307     if Assigned( Self_.FOnMove ) then\r
60308       Self_.FOnMove( Self_ );\r
60309   end;\r
60310   Result := False;\r
60311 end;\r
60313 //[procedure TControl.SetOnMove]\r
60314 procedure TControl.SetOnMove(const Value: TOnEvent);\r
60315 begin\r
60316   FOnMove := Value;\r
60317   AttachProc( WndProcMove );\r
60318 end;\r
60320 //[function WndProc_REBottomless]\r
60321 function WndProc_REBottomless( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60322 begin\r
60323   if Msg.message = WM_SIZE then\r
60324     Self_.Perform( EM_REQUESTRESIZE, 0, 0 );\r
60325   Result := False;\r
60326 end;\r
60328 //*\r
60329 //[function TControl.RE_Bottomless]\r
60330 function TControl.RE_Bottomless: PControl;\r
60331 begin\r
60332   AttachProc( WndProc_REBottomless );\r
60333   Result := @Self;\r
60334 end;\r
60336 //*\r
60337 //[procedure TControl.RE_Append]\r
60338 procedure TControl.RE_Append(const S: String; ACanUndo: Boolean);\r
60339 begin\r
60340   SelStart := TextSize;\r
60341   if S <> '' then\r
60342   begin\r
60343     ReplaceSelection( S, ACanUndo );\r
60344     SelStart := TextSize;\r
60345   end;\r
60346 end;\r
60348 //*\r
60349 //[procedure TControl.RE_InsertRTF]\r
60350 procedure TControl.RE_InsertRTF(const S: String);\r
60351 var MS: PStream;\r
60352 begin\r
60353   MS := NewMemoryStream;\r
60354   MS.Size := Length( S ) + 1;\r
60355   Move( S[ 1 ], MS.Memory^, Length( S ) + 1 );\r
60356   RE_LoadFromStream( MS, Length( S ), reRTF, TRUE );\r
60357   MS.Free;\r
60358 end;\r
60360 //*\r
60361 //[procedure TControl.DoSelChange]\r
60362 procedure TControl.DoSelChange;\r
60363 begin\r
60364   if Assigned( fOnSelChange ) then fOnSelChange( @Self )\r
60365   else\r
60366   if Assigned( fOnChange ) then fOnChange( @Self );\r
60367 end;\r
60369 //*\r
60370 //[function TControl.REGetUnderlineEx]\r
60371 function TControl.REGetUnderlineEx: TRichUnderline;\r
60372 begin\r
60373   Result := TRichUnderline( REGetFontAttr( (81 shl 16) or CFM_UNDERLINETYPE ) - 1 );\r
60374 end;\r
60376 //*\r
60377 //[procedure TControl.RESetUnderlineEx]\r
60378 procedure TControl.RESetUnderlineEx(const Value: TRichUnderline);\r
60379 begin\r
60380   RESetFontAttr( (81 shl 16) or CFM_UNDERLINETYPE, Ord( Value ) + 1 );\r
60381   RESetFontEffect( CFM_UNDERLINE, True );\r
60382 end;\r
60384 //*\r
60385 //[function TControl.GetTextSize]\r
60386 function TControl.GetTextSize: Integer;\r
60387 begin\r
60388   Result := 0;\r
60389   if fHandle <> 0 then\r
60390     Result := GetWindowTextLength( fHandle );\r
60391 end;\r
60393 //*\r
60394 //[function TControl.REGetTextSize]\r
60395 function TControl.REGetTextSize(Units: TRichTextSize): Integer;\r
60396 const TextLengthFlags: array[ TRichTextSizes ] of Integer =\r
60397       ( not GTL_UseCRLF, not GTL_Precise, GTL_Close, GTL_NUMBytes );\r
60398 var GTL: TGetTextLengthEx;\r
60399 begin\r
60400   GTL.flags := MakeFlags( @Units, TextLengthFlags );\r
60401   if not(rtsBytes in Units) then\r
60402     GTL.flags := GTL.flags or GTL_NUMCHARS;\r
60403   GTL.codepage := CP_ACP;\r
60404   Result := Perform( EM_GETTEXTLENGTHEX, Integer( @GTL ), 0 );\r
60405 end;\r
60407 //[function TControl.RE_TextSizePrecise]\r
60408 function TControl.RE_TextSizePrecise: Integer;\r
60409 var gtlex : TGetTextLengthEx;\r
60410 begin\r
60411   gtlex.flags := GTL_PRECISE;\r
60412   gtlex.codepage := CP_ACP;\r
60413   Result := Perform(EM_GETTEXTLENGTHEX,WPARAM(@gtlex), 0 );\r
60414 end;\r
60416 //*\r
60417 //[function TControl.REGetNumStyle]\r
60418 function TControl.REGetNumStyle: TRichNumbering;\r
60419 begin\r
60420   Result := TRichNumbering( ReGetParaAttr( 9 shl 16 ) );\r
60421 end;\r
60423 //*\r
60424 //[procedure TControl.RESetNumStyle]\r
60425 procedure TControl.RESetNumStyle(const Value: TRichNumbering);\r
60426 begin\r
60427   RESetParaAttr( (9 shl 16) or PFM_NUMBERING, Ord( Value ) );\r
60428 end;\r
60430 //*\r
60431 //[function TControl.REGetNumBrackets]\r
60432 function TControl.REGetNumBrackets: TRichNumBrackets;\r
60433 begin\r
60434   REGetParaAttr( 0 );\r
60435   Result := TRichNumBrackets( (fREParaFmtRec.wNumberingStyle shr 8) {and 3} );\r
60436 end;\r
60438 //*\r
60439 //[procedure TControl.RESetNumBrackets]\r
60440 procedure TControl.RESetNumBrackets(const Value: TRichNumBrackets);\r
60441 begin\r
60442   REGetParaAttr( 0 );\r
60443   fREParaFmtRec.wNumberingStyle := fREParaFmtRec.wNumberingStyle and $F8FF\r
60444                                 or Word( Ord( Value ) shl 8 );\r
60445   fREParaFmtRec.dwMask := PFM_NUMBERINGSTYLE;\r
60446   RE_ParaFmt := fREParaFmtRec;\r
60447 end;\r
60449 //*\r
60450 //[function TControl.REGetNumTab]\r
60451 function TControl.REGetNumTab: Integer;\r
60452 begin\r
60453   REGetParaAttr( 0 );\r
60454   Result := fREParaFmtRec.wNumberingTab;\r
60455 end;\r
60457 //*\r
60458 //[procedure TControl.RESetNumTab]\r
60459 procedure TControl.RESetNumTab(const Value: Integer);\r
60460 begin\r
60461   REGetParaAttr( 0 );\r
60462   fREParaFmtRec.wNumberingTab := Value;\r
60463   fREParaFmtRec.dwMask := PFM_NUMBERINGTAB;\r
60464   RE_ParaFmt := fREParaFmtRec;\r
60465 end;\r
60467 //*\r
60468 //[function TControl.REGetNumStart]\r
60469 function TControl.REGetNumStart: Integer;\r
60470 begin\r
60471   REGetParaAttr( 0 );\r
60472   Result := fREParaFmtRec.wNumberingStart;\r
60473 end;\r
60475 //*\r
60476 //[procedure TControl.RESetNumStart]\r
60477 procedure TControl.RESetNumStart(const Value: Integer);\r
60478 begin\r
60479   REGetParaAttr( 0 );\r
60480   fREParaFmtRec.wNumberingStart := Value;\r
60481   fREParaFmtRec.dwMask := PFM_NUMBERINGSTART;\r
60482   RE_ParaFmt := fREParaFmtRec;\r
60483 end;\r
60485 //*\r
60486 //[function TControl.REGetSpacing]\r
60487 function TControl.REGetSpacing( const Index: Integer ): Integer;\r
60488 begin\r
60489   REGetParaAttr( 0 );\r
60490   Result := PInteger( Integer(@fREParaFmtRec.dySpaceBefore) + (Index and $F) )^;\r
60491 end;\r
60493 //*\r
60494 //[procedure TControl.RESetSpacing]\r
60495 procedure TControl.RESetSpacing(const Index, Value: Integer);\r
60496 begin\r
60497   REGetParaAttr( 0 );\r
60498   PInteger( Integer(@fREParaFmtRec.dySpaceBefore) + (Index and $F) )^ := Value;\r
60499   fREParaFmtRec.dwMask := Index and not $F;\r
60500   RE_ParaFmt := fREParaFmtRec;\r
60501 end;\r
60503 //*\r
60504 //[function TControl.REGetSpacingRule]\r
60505 function TControl.REGetSpacingRule: Integer;\r
60506 begin\r
60507   REGetParaAttr( 0 );\r
60508   Result := fREParaFmtRec.bLineSpacingRule;\r
60509 end;\r
60511 //*\r
60512 //[procedure TControl.RESetSpacingRule]\r
60513 procedure TControl.RESetSpacingRule(const Value: Integer);\r
60514 begin\r
60515   REGetParaAttr( 0 );\r
60516   fREParaFmtRec.bLineSpacingRule := Value;\r
60517   fREParaFmtRec.dwMask := PFM_LINESPACING;\r
60518   RE_ParaFmt := fREParaFmtRec;\r
60519 end;\r
60521 //*\r
60522 //[function TControl.REGetLevel]\r
60523 function TControl.REGetLevel: Integer;\r
60524 begin\r
60525   REGetParaAttr( 0 );\r
60526   Result := fREParaFmtRec.bCRC;\r
60527 end;\r
60529 //*\r
60530 //[function TControl.REGetBorder]\r
60531 function TControl.REGetBorder(Side: TBorderEdge; const Index: Integer): Integer;\r
60532 begin\r
60533   REGetParaAttr( 0 );\r
60534   Result := PWORD( Integer(@fREParaFmtRec.wBorderSpace) + Index )^ shr (Ord(Side) * 4);\r
60535 end;\r
60537 //*\r
60538 //[procedure TControl.RESetBorder]\r
60539 procedure TControl.RESetBorder(Side: TBorderEdge; const Index: Integer;\r
60540   const Value: Integer);\r
60541 var Mask: Word;\r
60542     pW : PWord;\r
60543 begin\r
60544   REGetParaAttr( 0 );\r
60545   pw := PWORD( Integer(@fREParaFmtRec.wBorderSpace) + Index );\r
60546   Mask := $F shl (Ord(Side) * 4);\r
60547   pw^ := pw^ and not Mask or (Value shl (4 * Ord(Side)) );\r
60548   fREParaFmtRec.dwMask := PFM_BORDER;\r
60549   RE_ParaFmt := fREParaFmtRec;\r
60550 end;\r
60552 //*\r
60553 //[function TControl.REGetParaEffect]\r
60554 function TControl.REGetParaEffect(const Index: Integer): Boolean;\r
60555 begin\r
60556   Result := LongBool( HiWord( REGetParaAttr( 8 shl 16 ) ) and Index );\r
60557 end;\r
60559 //*\r
60560 //[procedure TControl.RESetParaEffect]\r
60561 procedure TControl.RESetParaEffect(const Index: Integer;\r
60562   const Value: Boolean);\r
60563 var Idx: Integer;\r
60564 begin\r
60565   REGetParaAttr( 0 );\r
60566   fREParaFmtRec.wReserved := Index;\r
60567   Idx := Index;\r
60568   //if Idx >= $4000 then Idx := $4000;\r
60569   fREParaFmtRec.dwMask := Idx shl 16;\r
60570   RE_ParaFmt := fREParaFmtRec;\r
60571 end;\r
60573 //*\r
60574 //[function WndProc_REMonitorIns]\r
60575 function WndProc_REMonitorIns( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60576 begin\r
60577   Result := False;\r
60578   if (Msg.message = WM_KEYDOWN) and (Msg.wParam = VK_INSERT) and\r
60579      ((GetKeyState(VK_CONTROL) or GetKeyState(VK_SHIFT) or GetKeyState(VK_MENU)) >= 0) then\r
60580   begin\r
60581     if not Self_.fReOvrDisable then\r
60582       Self_.fREOvr := not Self_.fREOvr\r
60583     else\r
60584       Result := True;\r
60585     if assigned( Self_.fOnREInsModeChg ) then\r
60586        Self_.fOnREInsModeChg( Self_ );\r
60587   end;\r
60588 end;\r
60590 //*\r
60591 //[function TControl.REGetOverwite]\r
60592 function TControl.REGetOverwite: Boolean;\r
60593 begin\r
60594   AttachProc( WndProc_REMonitorIns );\r
60595   Result := fREOvr;\r
60596 end;\r
60598 //*\r
60599 //[procedure TControl.RESetOverwrite]\r
60600 procedure TControl.RESetOverwrite(const Value: Boolean);\r
60601 begin\r
60602   if fREOvr = Value then Exit;\r
60603   Perform( WM_KEYDOWN, VK_INSERT, 0 );\r
60604   Perform( WM_KEYUP, VK_INSERT, 0 );\r
60605 end;\r
60607 //*\r
60608 //[procedure TControl.RESetOvrDisable]\r
60609 procedure TControl.RESetOvrDisable(const Value: Boolean);\r
60610 begin\r
60611   REGetOverwite;\r
60612   fReOvrDisable := Value;\r
60613 end;\r
60615 //*\r
60616 //[function WndProc_RichEdTransp_ParentPaint]\r
60617 function WndProc_RichEdTransp_ParentPaint( Self_:PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60618 var I: Integer;\r
60619     C: PControl;\r
60620 begin\r
60621   if (Msg.message = WM_PAINT) and (Msg.wParam = 0) then\r
60622   begin\r
60623     for I := 0 to Self_.fChildren.fCount - 1 do\r
60624     begin\r
60625       C := Self_.fChildren.fItems[ I ];\r
60626       if C.fIsCommonControl then\r
60627       begin\r
60628         Inc( C.fUpdCount );\r
60629         PostMessage( C.fHandle, CM_NCUPDATE, C.fUpdCount, WM_PAINT );\r
60630         InvalidateRect( C.fHandle, nil, False );\r
60631       end;\r
60632     end;\r
60633   end;\r
60634   Result := False;\r
60635 end;\r
60637 //*\r
60638 //[function WndProc_RichEdTransp_Update]\r
60639 function WndProc_RichEdTransp_Update( Self_:PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60640 var Rgn, Rgn1: HRgn;\r
60641     R, CR: TRect;\r
60642     Pt: TPoint;\r
60643     VW, HH, VH, HW: Integer;\r
60644 begin\r
60645   case Msg.message of\r
60646   WM_CHAR, WM_KILLFOCUS, WM_SETFOCUS:\r
60647     begin\r
60648       PostMessage( Self_.fHandle, CM_INVALIDATE, 0, 0 );\r
60649     end;\r
60650   WM_PAINT:\r
60651     if Msg.wParam = 0 then\r
60652     begin\r
60653       Inc( Self_.fUpdCount );\r
60654       PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );\r
60655     end;\r
60656   WM_SIZE:\r
60657     begin\r
60658       Inc( Self_.fUpdCount );\r
60659       PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );\r
60660       PostMessage( Self_.fHandle, CM_INVALIDATE, 0, 0 );\r
60661     end;\r
60662   WM_ERASEBKGND:\r
60663     if Msg.wParam = 0 then\r
60664     begin\r
60665       Inc( Self_.fUpdCount );\r
60666       PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );\r
60667     end;\r
60668   WM_HSCROLL, WM_VSCROLL:\r
60669     begin\r
60670       Self_.fREScrolling := LoWord( Msg.wParam ) <> SB_ENDSCROLL;\r
60671       Inc( Self_.fUpdCount );\r
60672       PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );\r
60673       if Self_.fREScrolling then\r
60674         Self_.Invalidate;\r
60675     end;\r
60676   CM_INVALIDATE:\r
60677     begin\r
60678       //Self_.Update;\r
60679       Self_.Parent.Invalidate;\r
60680       Self_.Invalidate;\r
60681       //Inc( Self_.fUpdCount );\r
60682       //PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );\r
60683     end;\r
60684   CM_NCUPDATE:\r
60685     if Msg.wParam = Self_.fUpdCount then\r
60686     begin\r
60687       //if Msg.lParam = WM_PAINT then\r
60688       //  UpdateWindow( Self_.fHandle );\r
60689       GetWindowRect( Self_.fHandle, R );\r
60690       Windows.GetClientRect( Self_.fHandle, CR );\r
60691       Pt.x := 0; Pt.y := 0;\r
60692       Pt := Self_.Client2Screen( Pt );\r
60693       OffsetRect( CR, Pt.x, Pt.y );\r
60694       Rgn := CreateRectRgn( R.Left, R.Top, R.Right, R.Bottom );\r
60695       if Self_.fREScrolling then\r
60696       begin\r
60697         VW := GetSystemMetrics( SM_CXVSCROLL );\r
60698         HH := GetSystemMetrics( SM_CYHSCROLL );\r
60699         VH := GetSystemMetrics( SM_CYVSCROLL );\r
60700         HW := GetSystemMetrics( SM_CXHSCROLL );\r
60701         if CR.Right + VW <= R.Right then\r
60702         begin\r
60703           Rgn1 := CreateRectRgn( CR.Right, CR.Top + VH, CR.Right + VW, CR.Bottom - VH );\r
60704           CombineRgn( Rgn, Rgn, Rgn1, RGN_DIFF );\r
60705           DeleteObject( Rgn1 );\r
60706         end;\r
60707         if CR.Bottom + HH <= R.Bottom then\r
60708         begin\r
60709           Rgn1 := CreateRectRgn( CR.Left + HW, CR.Bottom, CR.Right - HW, CR.Bottom + HH );\r
60710           CombineRgn( Rgn, Rgn, Rgn1, RGN_DIFF );\r
60711           DeleteObject( Rgn1 );\r
60712         end;\r
60713       end;\r
60714       Self_.Perform( WM_NCPAINT, Rgn, 0 );\r
60715       DeleteObject( Rgn ); // Unremarked By M.Gerasimov\r
60716     end;\r
60717   end;\r
60718   Result := False;\r
60719 end;\r
60721 //*\r
60722 //[function TControl.REGetTransparent]\r
60723 function TControl.REGetTransparent: Boolean;\r
60724 begin\r
60725   Result := Longbool(ExStyle and WS_EX_TRANSPARENT);\r
60726 end;\r
60728 //*\r
60729 //[procedure TControl.RESetTransparent]\r
60730 procedure TControl.RESetTransparent(const Value: Boolean);\r
60731 begin\r
60732   ExStyle := ExStyle or WS_EX_TRANSPARENT;\r
60733   fParent.AttachProc( WndProc_RichEdTransp_ParentPaint );\r
60734   AttachProc( WndProc_RichEdTransp_Update );\r
60735   fTransparent := Value;\r
60736 end;\r
60738 //*\r
60739 //[procedure TControl.RESetOnURL]\r
60740 procedure TControl.RESetOnURL(const Index: Integer; const Value: TOnEvent);\r
60741 begin\r
60742   if Index = 0 then\r
60743     fOnREOverURL := Value\r
60744   else\r
60745     fOnREURLClick := Value;\r
60746   RE_AutoURLDetect := assigned(fOnREOverURL) or assigned(fOnREURLClick);\r
60747 end;\r
60749 {$IFDEF F_P}\r
60750 //[function TControl.REGetOnURL]\r
60751 function TControl.REGetOnURL(const Index: Integer): TOnEvent;\r
60752 begin\r
60753   CASE Index OF\r
60754   0:   Result := fOnREOverURL;\r
60755   else Result := fOnREURLClick;\r
60756   END;\r
60757 end;\r
60758 {$ENDIF F_P}\r
60760 //*\r
60761 //[function TControl.REGetLangOptions]\r
60762 function TControl.REGetLangOptions(const Index: Integer): Boolean;\r
60763 begin\r
60764   Result := LongBool( Perform( EM_GETLANGOPTIONS, 0, 0 ) and Index);\r
60765 end;\r
60767 //*\r
60768 //[procedure TControl.RESetLangOptions]\r
60769 procedure TControl.RESetLangOptions(const Index: Integer;\r
60770   const Value: Boolean);\r
60771 var Mask: Integer;\r
60772 begin\r
60773   Mask := -1;\r
60774   if not Value then Inc( Mask );\r
60775   Perform( EM_SETLANGOPTIONS, 0, Perform( EM_GETLANGOPTIONS, 0, 0 ) and\r
60776            not Index or (Mask and Index) );\r
60777 end;\r
60779 //[API _TrackMouseEvent]\r
60780 function _TrackMouseEvent(lpEventTrack: PTrackMouseEvent): BOOL;\r
60781 external cctrl name '_TrackMouseEvent';\r
60783 //[function DoTrackMouseEvent]\r
60784 function DoTrackMouseEvent(lpEventTrack: PTrackMouseEvent): BOOL;\r
60785 var FunTrack: function(lpEventTrack: PTrackMouseEvent): BOOL; stdcall;\r
60786     ComCtlModule: THandle;\r
60787 begin\r
60788   Result := FALSE;\r
60789   ComCtlModule := GetModuleHandle( cctrl );\r
60790   if ComCtlModule = 0 then Exit;\r
60791   FunTrack := GetProcAddress( ComCtlModule, '_TrackMouseEvent' );\r
60792   if not Assigned( FunTrack ) then Exit;\r
60793   Result := FunTrack( lpEventTrack );\r
60794 end;\r
60796 //*\r
60797 //[function WndProcMouseEnterLeave]\r
60798 function WndProcMouseEnterLeave( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60799 var P: TPoint;\r
60800     MouseWasInControl: Boolean;\r
60801     Yes: Boolean;\r
60802     Track: TTrackMouseEvent;\r
60803 begin\r
60804   case Msg.message of\r
60805     WM_MOUSEFIRST..WM_MOUSELAST:\r
60806       begin\r
60807         MouseWasInControl := Self_.MouseInControl;\r
60808         if Assigned( Self_.fOnTestMouseOver ) then\r
60809           Yes := Self_.fOnTestMouseOver( Self_ )\r
60810         else\r
60811         begin\r
60812           GetCursorPos( P );\r
60813           P := Self_.Screen2Client( P );\r
60814           Yes := PointInRect( P, Self_.ClientRect );\r
60815         end;\r
60816         if MouseWasInControl <> Yes then\r
60817         begin\r
60818           Self_.Invalidate;\r
60819           if Yes then\r
60820           begin\r
60821             Self_.fMouseInControl := TRUE;\r
60822             if Assigned( Self_.fOnMouseEnter ) then\r
60823               Self_.fOnMouseEnter( Self_ );\r
60824             Track.cbSize := Sizeof( Track );\r
60825             Track.dwFlags := TME_LEAVE;\r
60826             Track.hwndTrack := Self_.Handle;\r
60827             //Track.dwHoverTime := 0;\r
60828             DoTrackMouseEvent( @ Track );\r
60829             Self_.Invalidate;\r
60830           end\r
60831              else\r
60832           begin\r
60833             Self_.fMouseInControl := FALSE;\r
60834             Track.cbSize := Sizeof( Track );\r
60835             Track.dwFlags := TME_LEAVE or TME_CANCEL;\r
60836             Track.hwndTrack := Self_.Handle;\r
60837             //Track.dwHoverTime := 0;\r
60838             DoTrackMouseEvent( @ Track );\r
60839             if Assigned( Self_.fOnMouseLeave ) then\r
60840               Self_.fOnMouseLeave( Self_ );\r
60841             Self_.Invalidate;\r
60842           end;\r
60843         end;\r
60844       end;\r
60845     WM_MOUSELEAVE:\r
60846       begin\r
60847         if Self_.fMouseInControl then\r
60848         begin\r
60849           Self_.fMouseInControl := FALSE;\r
60850           if Assigned( Self_.fOnMouseLeave ) then\r
60851             Self_.fOnMouseLeave( Self_ );\r
60852           Self_.Invalidate;\r
60853         end;\r
60854       end;\r
60855   end;\r
60856   Result := False;\r
60857 end;\r
60859 //[procedure ProvideMouseEnterLeave]\r
60860 procedure ProvideMouseEnterLeave( Self_: PControl );\r
60861 begin\r
60862   InitCommonControls;\r
60863   Self_.AttachProc( WndProcMouseEnterLeave );\r
60864   Self_.Invalidate;\r
60865 end;\r
60867 //[procedure TControl.SetFlat]\r
60868 procedure TControl.SetFlat(const Value: Boolean);\r
60869 begin\r
60870   //if fFlat = Value then Exit;\r
60871   fFlat := Value;\r
60872   fMouseInControl := FALSE;\r
60873   ProvideMouseEnterLeave( @Self );\r
60874   Invalidate;\r
60875 end;\r
60877 //[procedure TControl.SetOnMouseEnter]\r
60878 procedure TControl.SetOnMouseEnter(const Value: TOnEvent);\r
60879 begin\r
60880   fOnMouseEnter := Value;\r
60881   ProvideMouseEnterLeave( @Self );\r
60882 end;\r
60884 //[procedure TControl.SetOnMouseLeave]\r
60885 procedure TControl.SetOnMouseLeave(const Value: TOnEvent);\r
60886 begin\r
60887   fOnMouseLeave := Value;\r
60888   ProvideMouseEnterLeave( @Self );\r
60889 end;\r
60891 //[procedure TControl.SetOnTestMouseOver]\r
60892 procedure TControl.SetOnTestMouseOver(const Value: TOnTestMouseOver);\r
60893 begin\r
60894   fOnTestMouseOver := Value;\r
60895   ProvideMouseEnterLeave( @Self );\r
60896 end;\r
60898 //[function WndProcEdTransparent]\r
60899 function WndProcEdTransparent( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60900 begin\r
60901   if (Msg.message = WM_KEYDOWN) or\r
60902      (Msg.message = WM_MOUSEMOVE) and (GetKeyState( VK_LBUTTON ) < 0) or\r
60903      (Msg.message = WM_LBUTTONUP) or (Msg.message = WM_LBUTTONDOWN) then\r
60904     Self_.Invalidate;\r
60905   Result := False; // continue handling of a message anyway\r
60906 end;\r
60908 //[procedure TControl.EdSetTransparent]\r
60909 procedure TControl.EdSetTransparent(const Value: Boolean);\r
60910 begin\r
60911   Transparent := Value;\r
60912   AttachProc( WndProcEdTransparent );\r
60913 end;\r
60915 //[function WndProcSpeedButton]\r
60916 function WndProcSpeedButton( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
60917 begin\r
60918   Result := False;\r
60919   if Msg.message = WM_SETFOCUS then\r
60920   begin\r
60921     Result := TRUE;\r
60922     Rslt := 0;\r
60923   end;\r
60924 end;\r
60926 //[function TControl.LikeSpeedButton]\r
60927 function TControl.LikeSpeedButton: PControl;\r
60928 var Form: PControl;\r
60929 begin\r
60930   AttachProc( WndProcSpeedButton );\r
60931   fTabstop := False;\r
60932   Style := Style and not WS_TABSTOP;\r
60933   Form := ParentForm;\r
60934   if Form <> nil then\r
60935     if Form.fCurrentControl = @Self then\r
60936     begin\r
60937       Form.GotoControl( VK_TAB );\r
60938       if Form.fCurrentControl = @Self then\r
60939         Form.fCurrentControl := nil;\r
60940     end;\r
60941   Result := @Self;\r
60942 end;\r
60944 { -- Unicode -- }\r
60945 //[function TControl.SetUnicode]\r
60946 function TControl.SetUnicode(Unicode: Boolean): PControl;\r
60947 begin\r
60948   Perform( CCM_SETUNICODEFORMAT, Integer( Unicode ), 0 );\r
60949   Result := @ Self;\r
60950 end;\r
60952 { -- TabControl -- }\r
60954 //[function TControl.GetPages]\r
60955 function TControl.GetPages(Idx: Integer): PControl;\r
60956 var Item: TTCItem;\r
60957 begin\r
60958   Item.mask := TCIF_PARAM;\r
60959   if Perform( TCM_GETITEM, Idx, Integer( @Item ) ) = 0 then\r
60960     Result := nil\r
60961   else\r
60962     Result := Pointer( Item.lParam );\r
60963 end;\r
60965 //[function TControl.TCGetItemText]\r
60966 function TControl.TCGetItemText(Idx: Integer): String;\r
60967 var TI: TTCItem;\r
60968     Buffer: array[ 0..1023 ] of Char;\r
60969 begin\r
60970   TI.mask := TCIF_TEXT;\r
60971   TI.pszText := @Buffer[ 0 ];\r
60972   TI.cchTextMax := sizeof( Buffer );\r
60973   Buffer[ 0 ] := #0;\r
60974   Perform( TCM_GETITEM, Idx, Integer( @TI ) );\r
60975   Result := Buffer;\r
60976 end;\r
60978 //[procedure TControl.TCSetItemText]\r
60979 procedure TControl.TCSetItemText(Idx: Integer; const Value: String);\r
60980 var TI: TTCItem;\r
60981 begin\r
60982   TI.mask := TCIF_TEXT;\r
60983   TI.pszText := PChar( Value );\r
60984   Perform( TCM_SETITEM, Idx, Integer( @TI ) );\r
60985 end;\r
60987 //[function TControl.TCGetItemImgIDx]\r
60988 function TControl.TCGetItemImgIDx(Idx: Integer): Integer;\r
60989 var TI: TTCItem;\r
60990 begin\r
60991   TI.mask := TCIF_IMAGE;\r
60992   if Perform( TCM_GETITEM, Idx, Integer( @TI ) ) = 0 then\r
60993     Result := -1\r
60994   else\r
60995     Result := TI.iImage;\r
60996 end;\r
60998 //[procedure TControl.TCSetItemImgIdx]\r
60999 procedure TControl.TCSetItemImgIdx(Idx: Integer; const Value: Integer);\r
61000 var TI: TTCItem;\r
61001 begin\r
61002   TI.mask := TCIF_IMAGE;\r
61003   TI.iImage := Value;\r
61004   Perform( TCM_SETITEM, Idx, Integer( @TI ) );\r
61005 end;\r
61007 //[function TControl.TCGetItemRect]\r
61008 function TControl.TCGetItemRect(Idx: Integer): TRect;\r
61009 begin\r
61010   if Perform( TCM_GETITEMRECT, Idx, Integer( @Result ) ) = 0 then\r
61011   begin\r
61012     Result.Left := 0;\r
61013     Result.Right := 0;\r
61014     Result.Top := 0;\r
61015     Result.Bottom := 0;\r
61016   end;\r
61017 end;\r
61019 //[procedure TControl.TC_SetPadding]\r
61020 procedure TControl.TC_SetPadding(cx, cy: Integer);\r
61021 begin\r
61022   Perform( TCM_SETPADDING, 0, cx or (cy shl 16) );\r
61023 end;\r
61025 //[function TControl.TC_TabAtPos]\r
61026 function TControl.TC_TabAtPos(x, y: Integer): Integer;\r
61027 type TTCHittestInfo = packed record\r
61028        Pt: TPoint;\r
61029        Fl: DWORD;\r
61030      end;\r
61031 var HTI: TTCHitTestInfo;\r
61032 begin\r
61033   HTI.Pt.x := x;\r
61034   HTI.Pt.y := y;\r
61035   Result := Perform( TCM_HITTEST, 0, Integer( @HTI ) );\r
61036 end;\r
61038 //[function TControl.TC_DisplayRect]\r
61039 function TControl.TC_DisplayRect: TRect;\r
61040 begin\r
61041   Windows.GetClientRect( fHandle, Result );\r
61042   Perform( TCM_ADJUSTRECT, 0, Integer( @Result ) );\r
61043 end;\r
61045 //[function TControl.TC_IndexOf]\r
61046 function TControl.TC_IndexOf(const S: String): Integer;\r
61047 begin\r
61048   Result := TC_SearchFor( S, -1, FALSE );\r
61049 end;\r
61051 //[function TControl.TC_SearchFor]\r
61052 function TControl.TC_SearchFor(const S: String; StartAfter: Integer;\r
61053   Partial: Boolean): Integer;\r
61054 var I: Integer;\r
61055 begin\r
61056   Result := -1;\r
61057   for I := StartAfter+1 to Count-1 do\r
61058   begin\r
61059     if Partial and ( Copy( TC_Items[ I ], 1, Length( S ) ) = S ) or\r
61060        ( TC_Items[ I ] = S ) then\r
61061     begin\r
61062       Result := I;\r
61063       break;\r
61064     end;\r
61065   end;\r
61066 end;\r
61068 //[function TControl.TC_Insert]\r
61069 function TControl.TC_Insert(Idx: Integer; const TabText: String;\r
61070   TabImgIdx: Integer): PControl;\r
61071 var TI: TTCItem;\r
61072 begin\r
61073   Result := NewPanel( @Self, esNone );\r
61074   Result.FAlign := caClient;\r
61075   Result.fNotUseAlign := True;\r
61076   Result.fVisibleWoParent := TRUE;\r
61077   Result.Visible := Count = 0;\r
61078   TI.mask := TCIF_TEXT or TCIF_IMAGE or TCIF_PARAM;\r
61079   TI.iImage := TabImgIdx;\r
61080   TI.pszText := PChar( TabText );\r
61081   TI.lParam := Integer( Result );\r
61082   Perform( TCM_INSERTITEM, Idx, Integer( @TI ) );\r
61083   Result.BoundsRect := TC_DisplayRect;\r
61084 end;\r
61086 //[procedure TControl.TC_Delete]\r
61087 procedure TControl.TC_Delete(Idx: Integer);\r
61088 var Page: PControl;\r
61089 begin\r
61090   Page := TC_Pages[ Idx ];\r
61091   if Page = nil then Exit;\r
61092   Perform( TCM_DELETEITEM, Idx, 0 );\r
61093   Page.Free;\r
61094 end;\r
61096 { -- TreeView -- }\r
61098 //[function TControl.TVGetItemIdx]\r
61099 function TControl.TVGetItemIdx(const Index: Integer): THandle;\r
61100 begin\r
61101   Result := Perform( TVM_GETNEXTITEM, Index, 0 );\r
61102 end;\r
61104 //[procedure TControl.TVSetItemIdx]\r
61105 procedure TControl.TVSetItemIdx(const Index: Integer;\r
61106   const Value: THandle);\r
61107 begin\r
61108   Perform( TVM_SELECTITEM, Index, Value );\r
61109 end;\r
61111 //[function TControl.TVGetItemNext]\r
61112 function TControl.TVGetItemNext(Item: THandle; const Index: Integer): THandle;\r
61113 begin\r
61114   Result := Perform( TVM_GETNEXTITEM, Index, Item );\r
61115 end;\r
61117 //[function TControl.TVGetItemRect]\r
61118 function TControl.TVGetItemRect(Item: THandle; TextOnly: Boolean): TRect;\r
61119 begin\r
61120   Result.Left := Item;\r
61121   if Perform( TVM_GETITEMRECT, Integer( TextOnly ), Integer( @Result ) ) = 0 then\r
61122   begin\r
61123     Result.Left := 0;\r
61124     Result.Right := 0;\r
61125     Result.Top := 0;\r
61126     Result.Bottom := 0;\r
61127   end;\r
61128 end;\r
61130 //[function TControl.TVGetItemVisible]\r
61131 function TControl.TVGetItemVisible(Item: THandle): Boolean;\r
61132 var R: TRect;\r
61133 begin\r
61134   R := TVItemRect[ Item, False ];\r
61135   Result := R.Bottom > R.Top;\r
61136 end;\r
61138 //[procedure TControl.TVSetItemVisible]\r
61139 procedure TControl.TVSetItemVisible(Item: THandle; const Value: Boolean);\r
61140 begin\r
61141   if Value then\r
61142     Perform( TVM_ENSUREVISIBLE, 0, Item );\r
61143 end;\r
61145 //[function TControl.TVGetItemStateFlg]\r
61146 function TControl.TVGetItemStateFlg(Item: THandle; const Index: Integer): Boolean;\r
61147 var TVI: TTVItem;\r
61148 begin\r
61149   TVI.mask := TVIF_HANDLE or TVIF_STATE;\r
61150   TVI.hItem := Item;\r
61151   TVI.stateMask := Index;\r
61152   Result := False;\r
61153   if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then\r
61154     Result := (TVI.state and Index) <> 0;\r
61155 end;\r
61157 //[procedure TControl.TVSetItemStateFlg]\r
61158 procedure TControl.TVSetItemStateFlg(Item: THandle; const Index: Integer;\r
61159   const Value: Boolean);\r
61160 var TVI: TTVItem;\r
61161 begin\r
61162   TVI.mask := TVIF_HANDLE or TVIF_STATE;\r
61163   TVI.hItem := Item;\r
61164   TVI.stateMask := Index;\r
61165   TVI.state := $FFFFFFFF and Index;\r
61166   if not Value then\r
61167     TVI.state := 0;\r
61168   Perform( TVM_SETITEM, 0, Integer( @TVI ) );\r
61169 end;\r
61171 //[function TControl.TVGetItemImage]\r
61172 function TControl.TVGetItemImage(Item: THandle; const Index: Integer): Integer;\r
61173 var TVI: TTVItem;\r
61174 begin\r
61175   TVI.mask := TVIF_HANDLE or Loword( Index );\r
61176   TVI.hItem := Item;\r
61177   if Hiword( Index ) <> 0 then\r
61178   begin\r
61179     TVI.mask := TVIF_STATE or TVIF_HANDLE;\r
61180     TVI.stateMask := Loword( Index );\r
61181   end;\r
61182   Result := -1;\r
61183   if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then\r
61184   begin\r
61185     if Hiword( Index ) <> 0 then\r
61186       Result := (TVI.state shr Hiword( Index )) and $F\r
61187     else\r
61188     if Loword( Index ) = TVIF_IMAGE then\r
61189       Result := TVI.iImage\r
61190     else\r
61191       Result := TVI.iSelectedImage;\r
61192   end;\r
61193 end;\r
61195 //[procedure TControl.TVSetItemImage]\r
61196 procedure TControl.TVSetItemImage(Item: THandle; const Index: Integer;\r
61197   const Value: Integer);\r
61198 var TVI: TTVItem;\r
61199 begin\r
61200   TVI.mask := TVIF_HANDLE or Loword( Index );\r
61201   TVI.hItem := Item;\r
61202   TVI.iImage := Value;\r
61203   TVI.iSelectedImage := Value;\r
61204   if Hiword( Index ) <> 0 then\r
61205   begin\r
61206     TVI.mask := TVIF_STATE or TVIF_HANDLE;\r
61207     TVI.stateMask := Loword( Index );\r
61208     TVI.state := Value shl Hiword( Index );\r
61209   end;\r
61210   Perform( TVM_SETITEM, 0, Integer( @TVI ) );\r
61211 end;\r
61213 //[function TControl.TVGetItemText]\r
61214 function TControl.TVGetItemText(Item: THandle): String;\r
61215 var TVI: TTVItem;\r
61216     Buffer: array[ 0..4095 ] of Char;\r
61217 begin\r
61218   TVI.mask := TVIF_HANDLE or TVIF_TEXT;\r
61219   TVI.hItem := Item;\r
61220   TVI.pszText := @Buffer[ 0 ];\r
61221   Buffer[ 0 ] := #0;\r
61222   TVI.cchTextMax := Sizeof( Buffer );\r
61223   Perform( TVM_GETITEM, 0, Integer( @TVI ) );\r
61224   Result := Buffer;\r
61225 end;\r
61227 //[procedure TControl.TVSetItemText]\r
61228 procedure TControl.TVSetItemText(Item: THandle; const Value: String);\r
61229 var TVI: TTVItem;\r
61230 begin\r
61231   TVI.mask := TVIF_HANDLE or TVIF_TEXT;\r
61232   TVI.hItem := Item;\r
61233   TVI.pszText := PChar( Value );\r
61234   Perform( TVM_SETITEM, 0, Integer( @TVI ) );\r
61235 end;\r
61237 {$IFNDEF _FPC}\r
61238 {$IFNDEF _D2}\r
61239 //[function TControl.TVGetItemTextW]\r
61240 function TControl.TVGetItemTextW(Item: THandle): WideString;\r
61241 var TVI: TTVItemW;\r
61242     Buffer: array[ 0..4095 ] of WideChar;\r
61243 begin\r
61244   TVI.mask := TVIF_HANDLE or TVIF_TEXT;\r
61245   TVI.hItem := Item;\r
61246   TVI.pszText := @Buffer[ 0 ];\r
61247   Buffer[ 0 ] := #0;\r
61248   TVI.cchTextMax := High( Buffer ) + 1;\r
61249   Perform( TVM_GETITEMW, 0, Integer( @TVI ) );\r
61250   Result := Buffer;\r
61251 end;\r
61253 //[procedure TControl.TVSetItemTextW]\r
61254 procedure TControl.TVSetItemTextW(Item: THandle; const Value: WideString);\r
61255 var TVI: TTVItemW;\r
61256 begin\r
61257   TVI.mask := TVIF_HANDLE or TVIF_TEXT;\r
61258   TVI.hItem := Item;\r
61259   TVI.pszText := PWideChar( Value );\r
61260   Perform( TVM_SETITEMW, 0, Integer( @TVI ) );\r
61261 end;\r
61262 {$ENDIF _D2}\r
61263 {$ENDIF _FPC}\r
61265 //[function TControl.TVItemPath]\r
61266 function TControl.TVItemPath(Item: THandle; Delimiter: Char): String;\r
61267 begin\r
61268   if Item = 0 then\r
61269     Item := TVSelected;\r
61270   Result := '';\r
61271   while Item <> 0 do\r
61272   begin\r
61273     if Result <> '' then\r
61274       Result := Delimiter + Result;\r
61275     Result := TVItemText[ Item ] + Result;\r
61276     Item := TVItemParent[ Item ];\r
61277   end;\r
61278 end;\r
61280 {$IFNDEF _FPC}\r
61281 {$IFNDEF _D2}\r
61282 //[function TControl.TVItemPathW]\r
61283 function TControl.TVItemPathW(Item: THandle;\r
61284   Delimiter: WideChar): WideString;\r
61285 begin\r
61286   if Item = 0 then\r
61287     Item := TVSelected;\r
61288   Result := '';\r
61289   while Item <> 0 do\r
61290   begin\r
61291     if Result <> '' then\r
61292       Result := {$IFDEF _D3} '' + {$ENDIF} Delimiter + Result;\r
61293     Result := TVItemTextW[ Item ] + Result;\r
61294     Item := TVItemParent[ Item ];\r
61295   end;\r
61296 end;\r
61297 {$ENDIF _D2}\r
61298 {$ENDIF _FPC}\r
61300 //[function TControl.TV_GetItemHasChildren]\r
61301 function TControl.TV_GetItemHasChildren(Item: THandle): Boolean;\r
61302 var TVI: TTVItem;\r
61303 begin\r
61304   TVI.mask := TVIF_HANDLE or TVIF_CHILDREN;\r
61305   TVI.hItem := Item;\r
61306   Perform( TVM_GETITEM, 0, Integer( @TVI ) );\r
61307   Result := TVI.cChildren = 1;\r
61308 end;\r
61310 //[procedure TControl.TV_GetItemChildCount]\r
61311 function TControl.TV_GetItemChildCount(Item: THandle): Integer;\r
61312 var Node: THandle;\r
61313 begin\r
61314   Result := 0;\r
61315   Node := TVItemChild[ Item ];\r
61316   while Node <> 0 do\r
61317   begin\r
61318     Inc( Result );\r
61319     Node := TVItemNext[ Node ];\r
61320   end;\r
61321 end;\r
61323 //[procedure TControl.TV_SetItemHasChildren]\r
61324 procedure TControl.TV_SetItemHasChildren(Item: THandle;\r
61325   const Value: Boolean);\r
61326 var TVI: TTVItem;\r
61327 begin\r
61328   TVI.mask := TVIF_HANDLE or TVIF_CHILDREN;\r
61329   TVI.hItem := Item;\r
61330   TVI.cChildren := 1 and Integer( Value );\r
61331   Perform( TVM_SETITEM, 0, Integer( @TVI ) );\r
61332 end;\r
61334 //[function TControl.TVItemAtPos]\r
61335 function TControl.TVItemAtPos(x, y: Integer; var Where: DWORD): THandle;\r
61336 var HTI: TTVHitTestInfo;\r
61337 begin\r
61338   HTI.pt.x := x;\r
61339   HTI.pt.y := y;\r
61340   Result := Perform( TVM_HITTEST, 0, Integer( @HTI ) );\r
61341   Where := HTI.fl;\r
61342 end;\r
61344 type\r
61345   TTVInsertStruct = packed Record\r
61346     hParent: THandle;\r
61347     hAfter : THandle;\r
61348     item: TTVItem;\r
61349   end;\r
61350   TTVInsertStructEx = packed Record\r
61351     hParent: THandle;\r
61352     hAfter : THandle;\r
61353     item: TTVItemEx;\r
61354   end;\r
61356 //[function TControl.TVInsert]\r
61357 function TControl.TVInsert(nParent, nAfter: THandle;\r
61358   const Txt: String): THandle;\r
61359 var TVIns: TTVInsertStruct;\r
61360 begin\r
61361   TVIns.hParent := nParent;\r
61362   TVIns.hAfter := nAfter;\r
61363   TVIns.item.mask := TVIF_TEXT;\r
61364   TVIns.item.pszText := PChar( Txt );\r
61365   Result := Perform( TVM_INSERTITEM, 0, Integer( @TVIns ) );\r
61366   Invalidate;\r
61367 end;\r
61369 {$IFNDEF _FPC}\r
61370 {$IFNDEF _D2}\r
61371 type\r
61372   TTVInsertStructW = packed Record\r
61373     hParent: THandle;\r
61374     hAfter : THandle;\r
61375     item: TTVItemW;\r
61376   end;\r
61377   TTVInsertStructExW = packed Record\r
61378     hParent: THandle;\r
61379     hAfter : THandle;\r
61380     item: TTVItemExW;\r
61381   end;\r
61383 //[function TControl.TVInsertW]\r
61384 function TControl.TVInsertW(nParent, nAfter: THandle;\r
61385   const Txt: WideString): THandle;\r
61386 var TVIns: TTVInsertStructW;\r
61387 begin\r
61388   TVIns.hParent := nParent;\r
61389   TVIns.hAfter := nAfter;\r
61390   TVIns.item.mask := TVIF_TEXT;\r
61391   if Txt = '' then TVIns.item.pszText := nil\r
61392               else TVIns.item.pszText := PWideChar( @ Txt[ 1 ] );\r
61393   Result := Perform( TVM_INSERTITEMW, 0, Integer( @ TVIns ) );\r
61394   Invalidate;\r
61395 end;\r
61396 {$ENDIF _D2}\r
61397 {$ENDIF _FPC}\r
61399 //[procedure TControl.TVExpand]\r
61400 procedure TControl.TVExpand(Item: THandle; Flags: DWORD);\r
61401 begin\r
61402   Perform( TVM_EXPAND, Flags, Item );\r
61403 end;\r
61405 //[procedure TControl.TVSort]\r
61406 procedure TControl.TVSort( N: THandle );\r
61407 var a: Cardinal;\r
61408     b: Boolean;\r
61409 begin\r
61410   b := N = 0;\r
61411   if b then\r
61412   begin\r
61413     N := TVRoot;\r
61414   end;\r
61415   while N <> 0 do\r
61416     begin\r
61417       a := TVItemChild[N];\r
61418       if a > 0 then\r
61419         TVSort(a);\r
61420       Perform(TVM_SORTCHILDREN, 0, N);\r
61421       N := TVItemNext[N];\r
61422     end;\r
61423   if b then //moved by Truf\r
61424     Perform(TVM_SORTCHILDREN, 0, 0);  //+ by YS\r
61425 end;\r
61427 //[procedure TControl.TVDelete]\r
61428 procedure TControl.TVDelete(Item: THandle);\r
61429 begin\r
61430   Perform( TVM_DELETEITEM, 0, Item );\r
61431   Invalidate;\r
61432 end;\r
61434 //[function TControl.TVGetItemData]\r
61435 function TControl.TVGetItemData(Item: THandle): Pointer;\r
61436 var TVI: TTVItem;\r
61437 begin\r
61438   TVI.mask := TVIF_HANDLE or TVIF_PARAM;\r
61439   TVI.hItem := Item;\r
61440   Result := nil;\r
61441   if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then\r
61442     Result := Pointer( TVI.lParam );\r
61443 end;\r
61445 //[procedure TControl.TVSetItemData]\r
61446 procedure TControl.TVSetItemData(Item: THandle; const Value: Pointer);\r
61447 var TVI: TTVItem;\r
61448 begin\r
61449   TVI.mask := TVIF_HANDLE or TVIF_PARAM;\r
61450   TVI.hItem := Item;\r
61451   TVI.lParam := Integer( Value );\r
61452   Perform( TVM_SETITEM, 0, Integer( @TVI ) );\r
61453 end;\r
61455 //[procedure TControl.TVEditItem]\r
61456 procedure TControl.TVEditItem(Item: THandle);\r
61457 begin\r
61458   Perform( TVM_EDITLABEL, 0, Item );\r
61459 end;\r
61461 //[procedure TControl.TVStopEdit]\r
61462 procedure TControl.TVStopEdit(Cancel: Boolean);\r
61463 begin\r
61464   Perform( TVM_ENDEDITLABELNOW, Integer( Cancel ), 0 );\r
61465 end;\r
61467 //[function WndProcTVRightClickSelect]\r
61468 function WndProcTVRightClickSelect( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;\r
61469 var I: Integer;\r
61470     Where: DWORD;\r
61471 begin\r
61472   if Msg.message = WM_RBUTTONDOWN then\r
61473   begin\r
61474     I := Sender.TVItemAtPos( SmallInt( Msg.lParam and $FFFF ),\r
61475          SmallInt( Msg.lParam shr 16 ), Where  );\r
61476     if I <> 0 then\r
61477       Sender.TVSelected := I;\r
61478   end;\r
61479   Result := FALSE;\r
61480 end;\r
61482 //[procedure TControl.SetTVRightClickSelect]\r
61483 procedure TControl.SetTVRightClickSelect(const Value: Boolean);\r
61484 begin\r
61485   fTVRightClickSelect := Value;\r
61486   if Value then\r
61487     AttachProc( @WndProcTVRightClickSelect );\r
61488 end;\r
61490 //[procedure TControl.SetOnTVDelete]\r
61491 procedure TControl.SetOnTVDelete( const Value: TOnTVDelete );\r
61492 begin\r
61493   fOnTVDelete := Value;\r
61494   if fParent <> nil then\r
61495   begin\r
61496     fParent.Add2AutoFreeEx( Clear );\r
61497     fParent.DetachProc( WndProcNotify );\r
61498     fParent.AttachProcEx( WndProcNotify, TRUE );\r
61499   end;\r
61500   AttachProcEx( ProcTVDeleteItem, TRUE );\r
61501 end;\r
61503 //[function Clipboard2Text]\r
61504 function Clipboard2Text: String;\r
61505 var gbl: THandle;\r
61506     str: PChar;\r
61507 begin\r
61508   Result := '';\r
61509   if OpenClipboard( 0 ) then\r
61510   begin\r
61511     if IsClipboardFormatAvailable( CF_TEXT ) then\r
61512     begin\r
61513       gbl := GetClipboardData( CF_TEXT );\r
61514       if gbl <> 0 then\r
61515       begin\r
61516         str := GlobalLock( gbl );\r
61517         if str <> nil then\r
61518         begin\r
61519           Result := str;\r
61520           GlobalUnlock( gbl );\r
61521         end;\r
61522       end;\r
61523     end;\r
61524     CloseClipboard;\r
61525   end;\r
61526 end;\r
61528 {-}\r
61529 {$IFNDEF _D2}\r
61530 //[function Clipboard2WText]\r
61531 function Clipboard2WText: WideString;\r
61532 var gbl: THandle;\r
61533     str: PWideChar;\r
61534 begin\r
61535   Result := '';\r
61536   if OpenClipboard( 0 ) then\r
61537   begin\r
61538     if IsClipboardFormatAvailable( CF_UNICODETEXT ) then\r
61539     begin\r
61540       gbl := GetClipboardData( CF_UNICODETEXT );\r
61541       if gbl <> 0 then\r
61542       begin\r
61543         str := GlobalLock( gbl );\r
61544         if str <> nil then\r
61545         begin\r
61546           Result := str;\r
61547           GlobalUnlock( gbl );\r
61548         end;\r
61549       end;\r
61550     end;\r
61551     CloseClipboard;\r
61552   end;\r
61553 end;\r
61554 {$ENDIF}\r
61556 {+}\r
61557 //[function Text2Clipboard]\r
61558 function Text2Clipboard( const S: String ): Boolean;\r
61559 var gbl: THandle;\r
61560     str: PChar;\r
61561 begin\r
61562   Result := False;\r
61563   if not OpenClipboard( 0 ) then Exit;\r
61564   EmptyClipboard;\r
61565   if S <> '' then\r
61566   begin\r
61567     gbl := GlobalAlloc( GMEM_DDESHARE, Length( S ) + 1 );\r
61568     if gbl <> 0 then\r
61569     begin\r
61570       str := GlobalLock( gbl );\r
61571       Move( S[ 1 ], str^, Length( S ) + 1 );\r
61572       GlobalUnlock( gbl );\r
61573       Result := SetClipboardData( CF_TEXT, gbl ) <> 0;\r
61574     end;\r
61575   end\r
61576     else\r
61577       Result := True;\r
61578   CloseClipboard;\r
61579 end;\r
61581 {-}\r
61582 {$IFNDEF _D2}\r
61583 //[function WText2Clipboard]\r
61584 function WText2Clipboard( const WS: WideString ): Boolean;\r
61585 var gbl: THandle;\r
61586     str: PChar;\r
61587 begin\r
61588   Result := False;\r
61589   if not OpenClipboard( 0 ) then Exit;\r
61590   EmptyClipboard;\r
61591   if WS <> '' then\r
61592   begin\r
61593     gbl := GlobalAlloc( GMEM_DDESHARE, (Length( WS ) + 1) * 2 );\r
61594     if gbl <> 0 then\r
61595     begin\r
61596       str := GlobalLock( gbl );\r
61597       Move( WS[ 1 ], str^, (Length( WS ) + 1) * 2 );\r
61598       GlobalUnlock( gbl );\r
61599       Result := SetClipboardData( CF_UNICODETEXT, gbl ) <> 0;\r
61600     end;\r
61601   end\r
61602     else\r
61603       Result := True;\r
61604   CloseClipboard;\r
61605 end;\r
61606 {$ENDIF}\r
61608 {+}\r
61609 //[function TControl.Size]\r
61610 function TControl.Size(W, H: Integer): PControl;\r
61611 var C, P: PControl;\r
61612     dW, dH: Integer;\r
61613 begin\r
61614   C := @Self;\r
61615   while True do\r
61616   begin\r
61617     dW := 0; dH := 0;\r
61618     P := C.FParent;\r
61619     if C.ToBeVisible {or C.fCreateHidden {or (P <> nil) and (P.fVisible)} then\r
61620     begin\r
61621       if C.fAlign in [caLeft, caRight, caClient] then\r
61622       begin\r
61623         if H > 0 then\r
61624         begin\r
61625           dH := H - C.Height; H := 0;\r
61626         end;\r
61627       end;\r
61628       if C.fAlign in [caTop, caBottom, caClient] then\r
61629       begin\r
61630         if W > 0 then\r
61631         begin\r
61632           dW := W - C.Width; W := 0;\r
61633         end;\r
61634       end;\r
61635     end;\r
61636     if (W > 0) or (H > 0) then\r
61637     begin\r
61638       C.SetSize( W, H );\r
61639       if (P <> nil) // {Ralf Junker}\r
61640          and not P.IsApplet then\r
61641         C.ResizeParent;\r
61642       {\r
61643       if P <> nil then\r
61644       begin\r
61645         if not (C.FAlign in [caLeft,caRight,caClient]) then\r
61646           C.ResizeParentRight;\r
61647         if not (C.FAlign in [caTop,caBottom,caClient]) then\r
61648           C.ResizeParentBottom;\r
61649       end;\r
61650       }\r
61651     end;\r
61652     if (dW = 0) and (dH = 0) then break;\r
61653     C := P; //C.FParent;\r
61654     if C = nil then break;\r
61655     //if not C.fIsControl then break;\r
61656     if C.IsApplet then break;\r
61657     W := C.Width + dW;\r
61658     H := C.Height + dH;\r
61659   end;\r
61660   Result := @Self;\r
61661 end;\r
61663 //[procedure AutoSzProc]\r
61664 procedure AutoSzProc( Self_: PControl );\r
61665 var DeltaX, DeltaY: Integer;\r
61666     SZ: TSize; PT: TPoint;\r
61667     Txt: String;\r
61668     Chg: Boolean;\r
61669 begin\r
61670   Txt := Self_.fCaption;\r
61671   SZ.cx := 0;\r
61672   SZ.cy := 0;\r
61673   if Txt <> '' then\r
61674   begin\r
61675     if Assigned( Self_.fFont ) then\r
61676     if Self_.fFont.fData.Font.Italic then\r
61677        Txt := Txt + ' ';\r
61678     Self_.GetWindowHandle; // this line must be here.\r
61679     //-- otherwise, when handle is not yet allocated,\r
61680     // it is requested in TCanvas.GetHandle, and in result\r
61681     // of unpredictable recursion some memory can be currupted.\r
61682     Self_.Canvas.TextArea( Txt, SZ, PT );\r
61683   end;\r
61684   Chg := FALSE;\r
61685   if Self_.FAlign in [ caNone, caLeft, caRight ] then\r
61686   begin\r
61687     DeltaX := Self_.fCommandActions.aAutoSzX;\r
61688     if DeltaX > 0 then\r
61689     begin\r
61690       Self_.Width := SZ.cx + DeltaX;\r
61691       Chg := TRUE;\r
61692     end;\r
61693   end;\r
61694   if Self_.FAlign in [ caNone, caTop, caBottom ] then\r
61695   begin\r
61696     DeltaY := Self_.fCommandActions.aAutoSzY;\r
61697     if DeltaY > 0 then\r
61698     begin\r
61699       Self_.Height := SZ.cy + DeltaY;\r
61700       Chg := TRUE;\r
61701     end;\r
61702   end;\r
61703   if Chg then\r
61704   begin\r
61705     if Self_.fParent <> nil then\r
61706       Global_Align( Self_.fParent );\r
61707     Global_Align( Self_ );\r
61708   end;\r
61709 end;\r
61711 //[function TControl.AutoSize]\r
61712 function TControl.AutoSize(AutoSzOn: Boolean): PControl;\r
61713 begin\r
61714   if AutoSzOn then\r
61715   begin\r
61716     fAutoSize := AutoSzProc;\r
61717     fAutoSize( @Self );\r
61718   end\r
61719   else\r
61720     fAutoSize := nil;\r
61721   Result := @Self;\r
61722 end;\r
61724 //[function TControl.IsAutoSize]\r
61725 function TControl.IsAutoSize: Boolean;\r
61726 begin\r
61727   Result := Assigned( fAutoSize );\r
61728 end;\r
61730 //*\r
61731 //[function TControl.GetToBeVisible]\r
61732 function TControl.GetToBeVisible: Boolean;\r
61733 begin\r
61734   Result := fVisible or fCreateHidden or fVisibleWoParent;\r
61735   if fIsControl then\r
61736   if Parent <> nil then\r
61737   begin\r
61738     if fVisibleWoParent then\r
61739       Result := fVisible\r
61740     else\r
61741     begin\r
61742       Parent.Visible; // needed to provide correct fVisible for a form!\r
61743       Result := Result and Parent.ToBeVisible;\r
61744     end;\r
61745   end;\r
61746 end;\r
61748 { -- TTree -- }\r
61750 {$IFDEF USE_CONSTRUCTORS}\r
61751 //[function NewTree]\r
61752 function NewTree( AParent: PTree; const AName: String ): PTree;\r
61753 begin\r
61754   New( Result, CreateTree(  AParent, AName ) );\r
61755 end;\r
61756 //[END NewTree]\r
61757 {$ELSE not_USE_CONSTRUCTORS}\r
61758 //[function NewTree]\r
61759 function NewTree( AParent: PTree; const AName: String ): PTree;\r
61760 begin\r
61761   {-}\r
61762   New( Result, Create );\r
61763   {+}{++}(*Result := PTree.Create;*){--}\r
61764   if AParent <> nil then\r
61765     AParent.Add( Result );\r
61766   Result.fParent := AParent;\r
61767   Result.fName := AName;\r
61768 end;\r
61769 //[END NewTree]\r
61770 {$ENDIF USE_CONSTRUCTORS}\r
61772 { TTree }\r
61774 //[procedure TTree.Add]\r
61775 procedure TTree.Add(Node: PTree);\r
61776 var Previous: PTree;\r
61777 begin\r
61778   Node.Unlink;\r
61779   if fChildren = nil then\r
61780     fChildren := NewList;\r
61781   Previous := nil;\r
61782   if fChildren.fCount > 0 then\r
61783     Previous := fChildren.fItems[ fChildren.fCount - 1 ];\r
61784   if Previous <> nil then\r
61785   begin\r
61786     Previous.fNext := Node;\r
61787     Node.fPrev := Previous;\r
61788   end;\r
61789   fChildren.Add( Node );\r
61790   Node.fParent := @Self;\r
61791 end;\r
61793 //[procedure TTree.Clear]\r
61794 procedure TTree.Clear;\r
61795 var I: Integer;\r
61796 begin\r
61797   if fChildren = nil then Exit;\r
61798   for I := fChildren.fCount - 1 downto 0 do\r
61799     PTree( fChildren.fItems[ I ] ).Free;\r
61800 end;\r
61802 {$IFDEF USE_CONSTRUCTORS}\r
61803 //[constructor TTree.CreateTree]\r
61804 constructor TTree.CreateTree(AParent: PTree; const AName: String);\r
61805 begin\r
61806   inherited Create;\r
61807   if AParent <> nil then\r
61808     AParent.Add( @Self );\r
61809   fParent := AParent;\r
61810   fName := AName;\r
61811 end;\r
61812 {$ENDIF}\r
61814 //[destructor TTree.Destroy]\r
61815 destructor TTree.Destroy;\r
61816 begin\r
61817   Unlink;\r
61818   Clear;\r
61819   fName := '';\r
61820   inherited;\r
61821 end;\r
61823 //[function TTree.GetCount]\r
61824 function TTree.GetCount: Integer;\r
61825 begin\r
61826   Result := 0;\r
61827   if fChildren = nil then Exit;\r
61828   Result := fChildren.fCount;\r
61829 end;\r
61831 //[function TTree.GetIndexAmongSiblings]\r
61832 function TTree.GetIndexAmongSiblings: Integer;\r
61833 begin\r
61834   Result := -1;\r
61835   if fParent = nil then Exit;\r
61836   Result := fParent.fChildren.IndexOf( @Self );\r
61837 end;\r
61839 //[function TTree.GetItems]\r
61840 function TTree.GetItems(Idx: Integer): PTree;\r
61841 begin\r
61842   Result := nil;\r
61843   if fChildren = nil then Exit;\r
61844   Result := fChildren.Items[ Idx ];\r
61845 end;\r
61847 //[function TTree.GetLevel]\r
61848 function TTree.GetLevel: Integer;\r
61849 var Node: PTree;\r
61850 begin\r
61851   Result := 0;\r
61852   Node := fParent;\r
61853   while Node <> nil do\r
61854   begin\r
61855     Inc( Result );\r
61856     Node := Node.fParent;\r
61857   end;\r
61858 end;\r
61860 //[function TTree.GetRoot]\r
61861 function TTree.GetRoot: PTree;\r
61862 begin\r
61863   Result := @Self;\r
61864   while Result.fParent <> nil do\r
61865     Result := Result.fParent;\r
61866 end;\r
61868 //[function TTree.GetTotal]\r
61869 function TTree.GetTotal: Integer;\r
61870 var I: Integer;\r
61871 begin\r
61872   Result := Count;\r
61873   if Result <> 0 then\r
61874   begin\r
61875     for I := 0 to Count - 1 do\r
61876       Result := Result + Items[ I ].Total;\r
61877   end;\r
61878 end;\r
61880 //[procedure TTree.Init]\r
61881 procedure TTree.Init;\r
61882 begin\r
61883   if FParent <> nil then\r
61884     FParent.Add( @Self );\r
61885 end;\r
61887 //[procedure TTree.Insert]\r
61888 procedure TTree.Insert(Before, Node: PTree);\r
61889 var Previous: PTree;\r
61890 begin\r
61891   Node.Unlink;\r
61892   if fChildren = nil then\r
61893     fChildren := NewList;\r
61894   Previous := nil;\r
61895   if Before <> nil then\r
61896     Previous := Before.fPrev;\r
61897   if Previous <> nil then\r
61898   begin\r
61899     Previous.fNext := Node;\r
61900     Node.fPrev := Previous;\r
61901   end;\r
61902   if Before <> nil then\r
61903   begin\r
61904     Node.fNext := Before;\r
61905     Before.fPrev := Node;\r
61906     fChildren.Insert( fChildren.IndexOf( Before ), Node );\r
61907   end\r
61908     else\r
61909   fChildren.Add( Node );\r
61910   Node.fParent := @Self;\r
61911 end;\r
61913 //[function CompareTreeNodes]\r
61914 function CompareTreeNodes( const Data: Pointer; const e1, e2: DWORD ): Integer;\r
61915 var List: PList;\r
61916 begin\r
61917   List := Data;\r
61918   Result := AnsiCompareStr( PTree( List.fItems[ e1 ] ).fName,\r
61919                             PTree( List.fItems[ e2 ] ).fName );\r
61920 end;\r
61922 //[procedure SwapTreeNodes]\r
61923 procedure SwapTreeNodes( const Data: Pointer; const e1, e2: DWORD );\r
61924 var List: PList;\r
61925 begin\r
61926   List := Data;\r
61927   List.Swap( e1, e2 );\r
61928 end;\r
61930 //[procedure TTree.SwapNodes]\r
61931 procedure TTree.SwapNodes( i1, i2: Integer );\r
61932 begin\r
61933   fChildren.Swap( i1, i2 );\r
61934 end;\r
61936 //[procedure TTree.SortByName]\r
61937 procedure TTree.SortByName;\r
61938 begin\r
61939   if Count <= 1 then Exit;\r
61940   SortData( fChildren, fChildren.fCount, CompareTreeNodes, SwapTreeNodes );\r
61941 end;\r
61943 //[procedure TTree.Unlink]\r
61944 procedure TTree.Unlink;\r
61945 var I: Integer;\r
61946 begin\r
61947   if fPrev <> nil then\r
61948     fPrev.fNext := fNext;\r
61949   if fNext <> nil then\r
61950     fNext.fPrev := fPrev;\r
61951   if (fParent <> nil) then\r
61952   begin\r
61953     I := fParent.fChildren.IndexOf( @Self );\r
61954     fParent.fChildren.Delete( I );\r
61955     if fParent.fChildren.fCount = 0 then\r
61956     begin\r
61957       fParent.fChildren.Free;\r
61958       fParent.fChildren := nil;\r
61959     end;\r
61960   end;\r
61961   fPrev := nil;\r
61962   fNext := nil;\r
61963   fParent := nil;\r
61964 end;\r
61966 //[function TTree.IsParentOfNode]\r
61967 function TTree.IsParentOfNode(Node: PTree): Boolean;\r
61968 begin\r
61969   Result := TRUE;\r
61970   while Node <> nil do\r
61971   begin\r
61972     if Node = @ Self then Exit;\r
61973     Node := Node.Parent;\r
61974   end;\r
61975   Result := FALSE;\r
61976 end;\r
61978 //[function TTree.IndexOf]\r
61979 function TTree.IndexOf(Node: PTree): Integer;\r
61980 begin\r
61981   Result := -1;\r
61982   if not IsParentOfNode( Node ) then Exit;\r
61983   while Node <> @ Self do\r
61984   begin\r
61985     Inc( Result );\r
61986     while Node.PrevSibling <> nil do\r
61987     begin\r
61988       Node := Node.PrevSibling;\r
61989       Inc( Result, 1 + Node.Total );\r
61990     end;\r
61991     Node := Node.Parent;\r
61992   end;\r
61993 end;\r
61995 //-\r
61996 //[procedure TControl.ProcessPendingMessages]\r
61997 procedure TControl.ProcessPendingMessages;\r
61998 var Msg: TMsg;\r
61999 begin\r
62000   if LOWORD( GetQueueStatus( QS_ALLINPUT ) ) <> 0 then\r
62001   if PeekMessage( Msg, 0, 0, 0, PM_NOREMOVE {or PM_NOYIELD} )\r
62002   or PeekMessage( Msg, HWnd(-1), 0, 0, PM_NOREMOVE {or PM_NOYIELD} )\r
62003   then\r
62004     Applet.ProcessMessages;\r
62005 end;\r
62007 //[procedure TControl.ProcessPaintMessages]\r
62008 procedure TControl.ProcessPaintMessages;\r
62009 var Msg: TMsg;\r
62010 begin\r
62011   while PeekMessage( Msg, Handle, 15, 15, PM_NOREMOVE ) do\r
62012   //while GetQueueStatus( QS_PAINT ) <> 0 do\r
62013     Applet.ProcessMessage;\r
62014 end;\r
62024 ///////////////////////////////////////////////////////////////////////\r
62025 //\r
62026 //\r
62027 //                         W  I  N  D  O  W  S\r
62028 //\r
62029 //\r
62030 ///////////////////////////////////////////////////////////////////////\r
62034 { -- Set of window-related utility functions. -- }\r
62035 type\r
62036   PGUIThreadInfo = ^TGUIThreadInfo;\r
62037   tagGUITHREADINFO = packed record\r
62038     cbSize: DWORD;\r
62039     flags: DWORD;\r
62040     hwndActive: HWND;\r
62041     hwndFocus: HWND;\r
62042     hwndCapture: HWND;\r
62043     hwndMenuOwner: HWND;\r
62044     hwndMoveSize: HWND;\r
62045     hwndCaret: HWND;\r
62046     rcCaret: TRect;\r
62047   end;\r
62048   TGUIThreadInfo = tagGUITHREADINFO;\r
62050 const\r
62051   GUI_CARETBLINKING  = $00000001;\r
62052   GUI_INMOVESIZE     = $00000002;\r
62053   GUI_INMENUMODE     = $00000004;\r
62054   GUI_SYSTEMMENUMODE = $00000008;\r
62055   GUI_POPUPMENUMODE  = $00000010;\r
62057 {function GetGUIThreadInfo (idThread: DWORD; var pgui: TGUIThreadinfo): BOOL; stdcall;\r
62058          external user32 name 'GetGUIThreadInfo';}\r
62060 type TGUIThreadInfo_Proc = function( ThreadID: THandle; var GTI: TGUIThreadInfo )\r
62061                           : Boolean; stdcall;\r
62063 var Proc_GetGUIThreadInfo: TGuiThreadInfo_Proc;\r
62065 //[function GetWindowChild]\r
62066 function GetWindowChild( Wnd: HWnd; Kind: TWindowChildKind ): HWnd;\r
62067 var GTI: TGuiThreadInfo;\r
62068     ThreadID: THandle;\r
62069     Module: THandle;\r
62070 begin\r
62071   if not Assigned( Proc_GetGUIThreadInfo ) then\r
62072   begin\r
62073     Module := GetModuleHandle( 'User32' );\r
62074     Proc_GetGUIThreadInfo := GetProcAddress( Module, 'GetGUIThreadInfoA' );\r
62075     if not Assigned( Proc_GetGUIThreadInfo ) then\r
62076       Proc_GetGUIThreadInfo := Pointer( -1 );\r
62077   end;\r
62078   Result := Wnd;\r
62079   if Integer( @Proc_GetGUIThreadInfo ) = -1 then\r
62080     Exit;\r
62081   Result := 0;\r
62082   if Wnd = 0 then\r
62083     ThreadID := GetCurrentThreadID\r
62084   else\r
62085     ThreadID := GetWindowThreadProcessID( Wnd, nil );\r
62086   if ThreadID = 0 then Exit;\r
62087   GTI.cbSize := Sizeof( GTI );\r
62088   if Proc_GetGUIThreadInfo( ThreadId, GTI ) then\r
62089   begin\r
62090     case Kind of\r
62091     wcActive:  Result := GTI.hwndActive;\r
62092     wcFocus:   Result := GTI.hwndFocus;\r
62093     wcCapture: Result := GTI.hwndCapture;\r
62094     wcMenuOwner: Result := GTI.hwndMenuOwner;\r
62095     wcMoveSize:  Result := GTI.hwndMoveSize;\r
62096     wcCaret:     Result := GTI.hwndCaret;\r
62097     end;\r
62098   end;\r
62099 end;\r
62101 //[function GetFocusedChild]\r
62102 function GetFocusedChild( Wnd: HWnd ): HWnd;\r
62103 var Tr1, Tr2: THandle;\r
62104 begin\r
62105   Result := 0;\r
62106   Tr1 := GetCurrentThreadId;\r
62107   Tr2 := GetWindowThreadProcessId( Wnd, nil );\r
62108   if Tr1 = Tr2 then\r
62109     Result := GetFocus\r
62110   else\r
62111   if AttachThreadInput( Tr2, Tr1, True ) then\r
62112   begin\r
62113     Result := GetFocus;\r
62114     AttachThreadInput( Tr2, Tr1, False );\r
62115   end;\r
62116 end;\r
62118 //[function WaitFocusedWndChild]\r
62119 function WaitFocusedWndChild( Wnd: HWnd ): HWnd;\r
62120 var T1, T2: Integer;\r
62121     W: HWnd;\r
62122 begin\r
62123   Sleep( 50 );\r
62124   T1 := GetTickCount;\r
62125   while True do\r
62126   begin\r
62127     W := GetTopWindow( Wnd );\r
62128     if W = 0 then W := Wnd;\r
62129     W := GetFocusedChild( W );\r
62130     if W <> 0 then\r
62131     begin\r
62132       Wnd := W;\r
62133       break;\r
62134     end;\r
62135     T2 := GetTickCount;\r
62136     if Abs( T1 - T2 ) > 100 then break;\r
62137   end;\r
62138   Result := Wnd;\r
62139 end;\r
62141 //[function Stroke2Window]\r
62142 function Stroke2Window( Wnd: HWnd; const S: String ): Boolean;\r
62143 var P: PChar;\r
62144 begin\r
62145   Result := False;\r
62146   //Wnd := GetTopWindow( Wnd );\r
62147   Wnd := WaitFocusedWndChild( Wnd );\r
62148   if Wnd = 0 then Exit;\r
62149   P := PChar( S );\r
62150   while P^ <> #0 do\r
62151   begin\r
62152     PostMessage( Wnd, WM_CHAR, Integer( P^ ), 1 );\r
62153     Inc( P );\r
62154   end;\r
62155   Result := True;\r
62156 end;\r
62158 //[function Stroke2WindowEx]\r
62159 function Stroke2WindowEx( Wnd: HWnd; const S: String; Wait: Boolean ): Boolean;\r
62160 var P: PChar;\r
62161     EndChar: Char;\r
62162     MsgDn, MsgUp, SCA: Integer;\r
62164     function Compare( Pattern: PChar ): Boolean;\r
62165     var Pos: PChar;\r
62166         C1, C2: Char;\r
62167     begin\r
62168       Pos := P;\r
62169       while Pattern^ <> #0 do\r
62170       begin\r
62171         C1 := Pattern^;\r
62172         C2 := Pos^;\r
62173         if C1 in [ 'a'..'z' ] then\r
62174           C1 := Char( Ord( C1 ) - $20 );\r
62175         if C2 in [ 'a'..'z' ] then\r
62176           C2 := Char( Ord( C2 ) - $20 );\r
62177         if C1 <> C2 then\r
62178         begin\r
62179           Result := False;\r
62180           Exit;\r
62181         end;\r
62182         Inc( Pos );\r
62183         Inc( Pattern );\r
62184       end;\r
62185       while Pos^ = ' ' do Inc( Pos );\r
62186       P := Pos;\r
62187       Result := True;\r
62188     end;\r
62190     procedure Send( Msg, KeyCode: Integer );\r
62191     var lParam: Integer;\r
62192     begin\r
62193       Wnd := WaitFocusedWndChild( Wnd );\r
62194       if Wnd = 0 then Exit;\r
62195       lParam := 1;\r
62196       if longBool( SCA and 4 ) then\r
62197         lParam := $20000001;\r
62198       if Msg = MsgUp then\r
62199         lParam := lParam or Integer($D0000000);\r
62200       PostMessage( Wnd, Msg, KeyCode, lParam );\r
62201       Applet.ProcessMessages;\r
62202       if Wait then\r
62203         Sleep( 50 );\r
62204     end;\r
62206     function CompareSend( Pattern: PChar; Value2Send: Integer ): Boolean;\r
62207     begin\r
62208       if Compare( Pattern ) then\r
62209       begin\r
62210         Send( MsgDn, Value2Send );\r
62211         Send( MsgUp, Value2Send );\r
62212         Result := True;\r
62213       end\r
62214          else\r
62215         Result := False;\r
62216     end;\r
62218     function ParseKeys( EndChar: Char ): PChar;\r
62219     var FN: Integer;\r
62220     begin\r
62221       SCA := 0;\r
62222       while not (P^ in [ #0, EndChar ]) do\r
62223       begin\r
62224         if Compare( 'Shift' ) then SCA := SCA or 1\r
62225         else\r
62226         if Compare( 'Ctrl' ) then SCA := SCA or 2\r
62227         else\r
62228         if Compare( 'Alt' ) then SCA := SCA or 4\r
62229         else\r
62230           break;\r
62231       end;\r
62232       MsgDn := WM_KEYDOWN;\r
62233       MsgUp := WM_KEYUP;\r
62234       if LongBool( SCA and 4 ) then\r
62235       begin\r
62236         MsgDn := WM_SYSKEYDOWN;\r
62237         MsgUp := WM_SYSKEYUP;\r
62238         keybd_event( VK_MENU, 0, 0, 0 );\r
62239         Send( WM_SYSKEYDOWN, VK_MENU );\r
62240       end;\r
62241       if LongBool( SCA and 2 ) then\r
62242       begin\r
62243         keybd_event( VK_CONTROL, 0, 0, 0 );\r
62244         Send( WM_KEYDOWN, VK_CONTROL );\r
62245       end;\r
62246       if Longbool( SCA and 1 ) then\r
62247       begin\r
62248         keybd_event( VK_SHIFT, 0, 0, 0 );\r
62249         Send( WM_KEYDOWN, VK_SHIFT );\r
62250       end;\r
62251       while not (P^ in [ #0, EndChar ]) do\r
62252       begin\r
62253         if (P^ = 'F') and (P[ 1 ] in [ '1'..'9' ]) then\r
62254         begin\r
62255           Inc( P );\r
62256           FN := Ord( P^ ) - Ord( '0' );\r
62257           if (FN = 1) and (P[ 1 ] in [ '0'..'2' ]) then\r
62258           begin\r
62259             Inc( P );\r
62260             FN := 10 + Ord( P^ ) - Ord( '0' );\r
62261           end;\r
62262           repeat Inc( P ) until P^ <> ' ';\r
62263           FN := FN + $6F;\r
62264           Send( MsgDn, FN );\r
62265           Send( MsgUp, FN );\r
62266         end\r
62267            else\r
62268         if Compare( 'Numpad' ) then\r
62269         begin\r
62270           if P^ in [ '0'..'9' ] then\r
62271           begin\r
62272             FN := Ord( P^ ) - Ord( '0' ) + $60;\r
62273             repeat Inc( P^ ) until P^ <> ' ';\r
62274             Send( MsgDn, FN );\r
62275             Send( MsgUp, FN );\r
62276           end;\r
62277         end\r
62278            else\r
62279         if not (CompareSend( 'Add', $6B ) or\r
62280                 CompareSend( 'Gray+', $6B ) or\r
62281                 CompareSend( 'Apps', $5D ) or\r
62282                 CompareSend( 'BackSpace', $08 ) or\r
62283                 CompareSend( 'BkSp', $08 ) or\r
62284                 CompareSend( 'BS', $08 ) or\r
62285                 CompareSend( 'Break', $13 ) or\r
62286                 CompareSend( 'CapsLock', $14 ) or\r
62287                 CompareSend( 'Clear', $0C ) or\r
62288                 CompareSend( 'Decimal', $6E ) or\r
62289                 CompareSend( 'Del', $2E ) or\r
62290                 CompareSend( 'Delete', $2E ) or\r
62291                 CompareSend( 'Divide', $6F ) or\r
62292                 CompareSend( 'Gray/', $6F ) or\r
62293                 CompareSend( 'Down', $28 ) or\r
62294                 CompareSend( 'End', $23 ) or\r
62295                 CompareSend( 'Enter', $0D ) or\r
62296                 CompareSend( 'Return', $0D ) or\r
62297                 CompareSend( 'CR', $0D ) or\r
62298                 CompareSend( 'Esc', $1B ) or\r
62299                 CompareSend( 'Escape', $1B ) or\r
62300                 CompareSend( 'Help', $2F ) or\r
62301                 CompareSend( 'Home', $24 ) or\r
62302                 CompareSend( 'Ins', $2D ) or\r
62303                 CompareSend( 'Insert', $2D ) or\r
62304                 CompareSend( 'Left', $25 ) or\r
62305                 CompareSend( 'LWin', $5B ) or\r
62306                 CompareSend( 'Multiply', $6A ) or\r
62307                 CompareSend( 'Gray*', $6A ) or\r
62308                 CompareSend( 'NumLock', $90 ) or\r
62309                 CompareSend( 'PgDn', $22 ) or\r
62310                 CompareSend( 'PgUp', $21 ) or\r
62311                 CompareSend( 'PrintScrn', $2C ) or\r
62312                 CompareSend( 'Right', $27 ) or\r
62313                 CompareSend( 'RWin', $5C ) or\r
62314                 CompareSend( 'Separator', $6C ) or\r
62315                 CompareSend( 'ScrollLock', $91 ) or\r
62316                 CompareSend( 'Subtract', $6D ) or\r
62317                 CompareSend( 'Tab', $09 ) or\r
62318                 CompareSend( 'Gray-', $6D ) or\r
62319                 CompareSend( 'Up', $26 )) then break;\r
62320       end;\r
62321       while not (P^ in [ #0, EndChar ]) do\r
62322       begin\r
62323         if P^ in [ 'A'..'Z', '0'..'9' ] then\r
62324         begin\r
62325           Send( MsgDn, Integer( P^ ) );\r
62326           Send( MsgUp, Integer( P^ ) );\r
62327         end\r
62328         else\r
62329         if P^ in [ #1..#255 ] then\r
62330           Stroke2Window( Wnd, '' + P^ );\r
62331         repeat Inc( P ) until (P^ <> ' ');\r
62332       end;\r
62333       if P^ = EndChar then\r
62334         Inc( P );\r
62335       if Longbool( SCA and 1 ) then\r
62336       begin\r
62337         Send( WM_KEYUP, VK_SHIFT );\r
62338         keybd_event( VK_SHIFT, 0, KEYEVENTF_KEYUP, 0 );\r
62339       end;\r
62340       if LongBool( SCA and 2 ) then\r
62341       begin\r
62342         Send( WM_KEYUP, VK_CONTROL );\r
62343         keybd_event( VK_CONTROL, 0, KEYEVENTF_KEYUP, 0 );\r
62344       end;\r
62345       if LongBool( SCA and 4 ) then\r
62346       begin\r
62347         Send( WM_SYSKEYUP, VK_MENU );\r
62348         keybd_event( VK_MENU, 0, KEYEVENTF_KEYUP, 0 );\r
62349       end;\r
62350       Result := P;\r
62351     end;\r
62353 begin\r
62354   Result := False;\r
62355   Wnd := GetTopWindow( Wnd );\r
62356   Wnd := GetFocusedChild( Wnd );\r
62357   if Wnd = 0 then Exit;\r
62358   P := PChar( S );\r
62359   while P^ <> #0 do\r
62360   begin\r
62361     if not (P^ in [ '[', '{' ]) then\r
62362     begin\r
62363       Stroke2Window( Wnd, '' + P^ );\r
62364       Inc( P );\r
62365     end\r
62366       else\r
62367     begin\r
62368       if P^ = '[' then\r
62369         EndChar := ']'\r
62370       else\r
62371         EndChar := '}';\r
62372       Inc( P );\r
62373       P := ParseKeys( EndChar );\r
62374     end;\r
62375   end;\r
62376   Result := True;\r
62377 end;\r
62379 type\r
62380   PHWnd = ^HWnd;\r
62382   TFindWndRec = packed Record\r
62383     ThreadID : DWord;\r
62384     WndFound : HWnd;\r
62385   end;\r
62386   PFindWndRec = ^TFindWndRec;\r
62388 //[function EnumWindowsProc]\r
62389 function EnumWindowsProc( Wnd : HWnd; Find : PFindWndRec ) : Boolean;\r
62390 stdcall;\r
62391 var Id : DWord;\r
62392 begin\r
62393   Result := True;\r
62394   Id := GetWindowThreadProcessId( Wnd, @Id );\r
62395   if Id = Find.ThreadID then\r
62396   begin\r
62397     Find.WndFound := Wnd;\r
62398     Result := False;\r
62399   end;\r
62400 end;\r
62402 //[function FindWindowByThreadID]\r
62403 function FindWindowByThreadID( ThreadID : DWORD ) : HWnd;\r
62404 var Find : TFindWndRec;\r
62405 begin\r
62406   Find.ThreadID := ThreadID;\r
62407   Find.WndFound := 0;\r
62408   EnumWindows( @EnumWindowsProc, Integer( @Find ) );\r
62409   Result := Find.WndFound;\r
62410 end;\r
62412 //[function GetDesktopRect]\r
62413 function GetDesktopRect : TRect;\r
62414 var W1, W2 : HWnd;\r
62415 begin\r
62416   Result := MakeRect( 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) );\r
62417   W2 := findwindow(nil,'Program Manager');\r
62418   W1 := findwindowex(W2,0,'SHELLDLL_DefView',nil);\r
62419   if W1 = 0 then Exit;\r
62420   GetWindowRect( W1, Result );\r
62421 end;\r
62423 //[function GetWorkArea]\r
62424 function GetWorkArea: TRect;\r
62425 begin\r
62426   SystemParametersInfo( SPI_GETWORKAREA, 0, @ Result, 0 );\r
62427 end;\r
62429 //[function ExecuteWait]\r
62430 function ExecuteWait( const AppPath, CmdLine, DfltDirectory: String;\r
62431          Show: DWORD; TimeOut: DWORD; ProcID: PDWORD ): Boolean;\r
62432 var Flags: DWORD;\r
62433     Startup: TStartupInfo;\r
62434     ProcInf: TProcessInformation;\r
62435     DfltDir: PChar;\r
62436     App: String;\r
62437 begin\r
62438   Result := FALSE;\r
62439   Flags := CREATE_NEW_CONSOLE;\r
62440   if Show = SW_HIDE then\r
62441     Flags := Flags or {$IFDEF F_P}$08000000{$ELSE}CREATE_NO_WINDOW{$ENDIF};\r
62442   FillChar( Startup, SizeOf( Startup ), 0 );\r
62443   Startup.cb := Sizeof( Startup );\r
62444   Startup.wShowWindow := Show;\r
62445   Startup.dwFlags := STARTF_USESHOWWINDOW;\r
62446   if ProcID <> nil then\r
62447     ProcID^ := 0;\r
62448   DfltDir := nil;\r
62449   if DfltDirectory <> '' then\r
62450     DfltDir := PChar( DfltDirectory );\r
62451   if ProcID <> nil then\r
62452     ProcID^ := 0;\r
62453   App := AppPath;\r
62454   if (pos( ' ', App ) > 0) and (pos( '"', App ) <= 0) then\r
62455     App := '"' + App + '"';\r
62456   if (App <> '') and (CmdLine <> '') then\r
62457     App := App + ' ';\r
62458   if CreateProcess( nil, PChar( App + CmdLine ), nil,\r
62459      nil, FALSE, Flags, nil, DfltDir, Startup,\r
62460      ProcInf ) then\r
62461   begin\r
62462     if WaitForSingleObject( ProcInf.hProcess, TimeOut ) = WAIT_OBJECT_0 then\r
62463     begin\r
62464       CloseHandle( ProcInf.hProcess );\r
62465       Result := TRUE;\r
62466     end\r
62467       else\r
62468     begin\r
62469       if ProcID <> nil then\r
62470         ProcID^ := ProcInf.hProcess;\r
62471     end;\r
62472     CloseHandle( ProcInf.hThread );\r
62473   end;\r
62474 end;\r
62476 //[function ExecuteIORedirect]\r
62477 function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: String;\r
62478          Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;\r
62479 var Flags: DWORD;\r
62480     Startup: TStartupInfo;\r
62481     ProcInf: TProcessInformation;\r
62482     DfltDir: PChar;\r
62483     SecurityAttributes: TSecurityAttributes;\r
62484     SaveStdOut, SaveStdIn: THandle;\r
62485     ChildStdOutRd, ChildStdOutWr: THandle;\r
62486     ChildStdInRd, ChildStdInWr: THandle;\r
62487     ChildStdOutRdDup: THandle;\r
62488     ChildStdInWrDup: THandle;\r
62490     procedure Do_CloseHandle( var Handle: THandle );\r
62491     begin\r
62492       if Handle <> 0 then\r
62493       begin\r
62494         CloseHandle( Handle );\r
62495         Handle := 0;\r
62496       end;\r
62497     end;\r
62499     procedure Close_Handles;\r
62500     begin\r
62501       Do_CloseHandle( ChildStdOutRd );\r
62502       Do_CloseHandle( ChildStdOutWr );\r
62503       Do_CloseHandle( ChildStdInRd );\r
62504       Do_CloseHandle( ChildStdInWr );\r
62505     end;\r
62507     function RedirectInputOutput: Boolean;\r
62508     begin\r
62509       Result := FALSE;\r
62510       if (OutPipeRd <> nil) or (OutPipeWr <> nil) then\r
62511       begin\r
62512         // redirect output\r
62513         SaveStdOut := GetStdHandle(STD_OUTPUT_HANDLE);\r
62514         if not CreatePipe( ChildStdOutRd, ChildStdOutWr, @ SecurityAttributes, 0 ) then\r
62515           Exit;\r
62516         if not SetStdHandle( STD_OUTPUT_HANDLE, ChildStdOutWr ) then\r
62517           Exit;\r
62518         if not DuplicateHandle( GetCurrentProcess, ChildStdOutRd,\r
62519            GetCurrentProcess, @ ChildStdOutRdDup, 0, FALSE,\r
62520            2 {DUPLICATE_SAME_ACCESS} ) then\r
62521           Exit;\r
62522         Do_CloseHandle( ChildStdOutRd );\r
62523         if OutPipeRd <> nil then\r
62524           OutPipeRd^ := ChildStdOutRdDup;\r
62525         if OutPipeWr <> nil then\r
62526           OutPipeWr^ := ChildStdOutWr;\r
62527       end;\r
62528       if InPipe <> nil then\r
62529       begin\r
62530         // redirect input\r
62531         SaveStdIn := GetStdHandle(STD_INPUT_HANDLE);\r
62532         if not CreatePipe( ChildStdInRd, ChildStdInWr, @ SecurityAttributes, 0 ) then\r
62533           Exit;\r
62534         if not SetStdHandle( STD_INPUT_HANDLE, ChildStdInRd ) then\r
62535           Exit;\r
62536         if not DuplicateHandle( GetCurrentProcess, ChildStdInWr,\r
62537            GetCurrentProcess, @ ChildStdInWrDup, 0, FALSE,\r
62538            2 {DUPLICATE_SAME_ACCESS} ) then\r
62539           Exit;\r
62540         Do_CloseHandle( ChildStdInWr );\r
62541         if InPipe <> nil then\r
62542           InPipe^ := ChildStdInWrDup;\r
62543         Do_CloseHandle( ChildStdInRd );\r
62544       end;\r
62545       Result := TRUE;\r
62546     end;\r
62548     procedure Restore_Saved_StdInOut;\r
62549     begin\r
62550       //if SaveStdOut <> 0 then\r
62551         SetStdHandle( STD_OUTPUT_HANDLE, SaveStdOut );\r
62552       //if SaveStdin <> 0 then\r
62553         SetStdHandle( STD_INPUT_HANDLE, SaveStdIn );\r
62554     end;\r
62556 begin\r
62557   Result := FALSE;\r
62558   Flags := 0;\r
62559   if Show = SW_HIDE then\r
62560     Flags := Flags or {$IFDEF F_P}$08000000{$ELSE}CREATE_NO_WINDOW{$ENDIF};\r
62561   FillChar( Startup, SizeOf( Startup ), 0 );\r
62562   Startup.cb := Sizeof( Startup );\r
62563   {Startup.wShowWindow := Show;\r
62564   Startup.dwFlags := STARTF_USESHOWWINDOW;}\r
62565   if ProcID <> nil then\r
62566     ProcID^ := 0;\r
62567   DfltDir := nil;\r
62568   SecurityAttributes.nLength := Sizeof( SecurityAttributes );\r
62569   SecurityAttributes.lpSecurityDescriptor := nil;\r
62570   SecurityAttributes.bInheritHandle := TRUE;\r
62571   SaveStdOut := 0;\r
62572   SaveStdIn := 0;\r
62573   ChildStdOutRd := 0;\r
62574   ChildStdOutWr := 0;\r
62575   ChildStdInRd := 0;\r
62576   ChildStdInWr := 0;\r
62577   if not RedirectInputOutput then\r
62578   begin\r
62579     Close_Handles;\r
62580     Exit;\r
62581   end;;\r
62582   if DfltDirectory <> '' then\r
62583     DfltDir := PChar( DfltDirectory );\r
62584   if CreateProcess( nil, PChar( '"' + AppPath + '" ' + CmdLine ),\r
62585      nil, nil, TRUE, Flags, nil, DfltDir, Startup,\r
62586      ProcInf ) then\r
62587   begin\r
62588     if ProcID <> nil then\r
62589       ProcID^ := ProcInf.hProcess\r
62590     else\r
62591       CloseHandle( ProcInf.hProcess );\r
62592     CloseHandle( ProcInf.hThread );\r
62593     Restore_Saved_StdInOut;\r
62594     Result := TRUE;\r
62595   end\r
62596     else\r
62597   begin\r
62598     Restore_Saved_StdInOut;\r
62599     Close_Handles;\r
62600     Exit;\r
62601   end;\r
62602 end;\r
62604 //[function ExecuteConsoleAppIORedirect]\r
62605 function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;\r
62606          Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD ): Boolean;\r
62607 var PipeIn, PipeOutRd, PipeOutWr: THandle;\r
62608     ProcID: DWORD;\r
62609     BytesCount: DWORD;\r
62610     Buffer: array[ 0..4096 ] of Char;\r
62611     BufStr: String;\r
62612     PPipeIn: PHandle;\r
62613 begin\r
62614   Result := FALSE;\r
62615   PPipeIn := @ PipeIn;\r
62616   if InStr = '' then\r
62617     PPipeIn := nil;\r
62618   PipeOutRd := 0;\r
62619   PipeOutWr := 0;\r
62620   if not ExecuteIORedirect( AppPath, CmdLine, DfltDirectory, Show, @ ProcID,\r
62621                      PPipeIn, @ PipeOutWr, @ PipeOutRd ) then Exit;\r
62622   if PPipeIn <> nil then\r
62623   begin\r
62624     if InStr <> '' then\r
62625       WriteFile( PipeIn, InStr[ 1 ], Length( InStr ), BytesCount, nil );\r
62626     CloseHandle( PipeIn );\r
62627   end;\r
62628   OutStr := '';\r
62629   if WaitForSingleObject( ProcID, WaitTimeOut ) = WAIT_OBJECT_0 then\r
62630   begin\r
62631     CloseHandle( ProcID );\r
62632     CloseHandle( PipeOutWr );\r
62633     while ReadFile( PipeOutRd, Buffer, Sizeof( Buffer ), BytesCount, nil ) do\r
62634     begin\r
62635       SetLength( BufStr, BytesCount );\r
62636       Move( Buffer[ 0 ], BufStr[ 1 ], BytesCount );\r
62637       OutStr := OutStr + BufStr;\r
62638     end;\r
62639   end\r
62640     else\r
62641     CloseHandle( PipeOutWr );\r
62642   CloseHandle( PipeOutRd );\r
62643   Result := TRUE;\r
62644 end;\r
62646 {$IFDEF _D2}\r
62647 //[API OpenProcessToken]\r
62648 function OpenProcessToken(ProcessHandle: THandle; DesiredAccess: DWORD;\r
62649   var TokenHandle: THandle): BOOL; stdcall;\r
62650   external advapi32 name 'OpenProcessToken';\r
62651 {$ENDIF}\r
62653 //[function WindowsShutdown]\r
62654 function WindowsShutdown( const Machine : String; Force, Reboot : Boolean ) : Boolean;\r
62655 var\r
62656   hToken: THandle;\r
62657   tkp, tkp_prev: TTokenPrivileges;\r
62658   dwRetLen :DWORD;\r
62659   Flags: Integer;\r
62660 begin\r
62661   Result := False;\r
62662   if Integer( GetVersion ) < 0 then // Windows95/98/Me\r
62663   begin\r
62664     if Machine <> '' then Exit;\r
62665     Flags := EWX_SHUTDOWN;\r
62666     if Reboot then\r
62667       Flags := Flags or EWX_REBOOT;\r
62668     if Force then\r
62669       Flags := Flags or EWX_FORCE;\r
62670     Result := ExitWindowsEx( Flags, 0 );\r
62671     Exit;\r
62672   end;\r
62674   OpenProcessToken(GetCurrentProcess(),\r
62675                    TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,\r
62676                    hToken);\r
62678   if not LookupPrivilegeValue(PChar(Machine),\r
62679 'SeShutdownPrivilege',tkp.Privileges[0].Luid)\r
62680      then\r
62681          Exit;\r
62683   tkp_prev:=tkp;\r
62684   tkp.PrivilegeCount:=1;\r
62685   tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;\r
62686   AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof(tkp), tkp_prev,\r
62687 dwRetLen);\r
62689   if not LookupPrivilegeValue(PChar(Machine),\r
62690                               'SeRemoteShutdownPrivilege',\r
62691                               tkp.Privileges[0].Luid)\r
62692      then\r
62693          Exit;\r
62695   tkp.PrivilegeCount:=1;\r
62696   tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;\r
62697   AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof(tkp), tkp_prev,\r
62698 dwRetLen);\r
62700   Result := InitiateSystemShutdown(PChar(Machine),nil, 0, Force, Reboot);\r
62701 end;\r
62703 var SaveWinVer: Byte = $FF;\r
62705 //[function WinVer]\r
62706 function WinVer : TWindowsVersion;\r
62707 {* Returns Windows version. }\r
62708 var OVI: TOsVersionInfo;\r
62709 begin\r
62710   if SaveWinVer <> $FF then Result := TWindowsVersion( SaveWinVer )\r
62711   else\r
62712   begin\r
62713     OVI.dwOSVersionInfoSize := Sizeof( OVI );\r
62714     GetVersionEx( OVI );\r
62715     with OVI do\r
62716     if dwPlatformId = VER_PLATFORM_WIN32_NT then\r
62717     begin\r
62718       Result := wvNT;\r
62719       if dwMajorVersion >= 6 then\r
62720         Result := wvLongHorn\r
62721       else begin\r
62722              if dwMajorVersion >= 5 then\r
62723                if dwMinorVersion >=1 then\r
62724                  Result := wvXP\r
62725                else\r
62726                  Result := wvY2K;\r
62727            end;\r
62728     end\r
62729     {if dwPlatformId = VER_PLATFORM_WIN32_NT then\r
62730     begin\r
62731       Result := wvNT;\r
62732       if dwMajorVersion >= 5 then\r
62733         Result := wvY2K;\r
62734     end}\r
62735        else\r
62736     if dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then\r
62737     begin\r
62738       Result := wv95;\r
62739       if (dwMajorVersion > 4) or (dwMajorVersion = 4)\r
62740       and (dwMinorVersion >= 10)  then\r
62741         Result := wv98;\r
62742     end\r
62743        else\r
62744        Result := wv31; // Windows 3.1 (WIN32s)\r
62745     SaveWinVer := Ord( Result );\r
62746   end;\r
62747 end;\r
62749 //[function IsWinVer]\r
62750 function IsWinVer( Ver : TWindowsVersions ) : Boolean;\r
62751 {* Returns True if Windows version is in given range of values. }\r
62752 begin\r
62753   Result := WinVer in Ver;\r
62754 end;\r
62756 //[procedure TControl.SetAlphaBlend]\r
62757 procedure TControl.SetAlphaBlend(const Value: Integer);\r
62758 const\r
62759   LWA_COLORKEY=$00000001;\r
62760   LWA_ALPHA=$00000002;\r
62761   ULW_COLORKEY=$00000001;\r
62762   ULW_ALPHA=$00000002;\r
62763   ULW_OPAQUE=$00000004;\r
62764   WS_EX_LAYERED=$00080000;\r
62765 type\r
62766   TSetLayeredWindowAttributes=\r
62767     function( hwnd: Integer; crKey: TColor; bAlpha: Byte; dwFlags: DWORD )\r
62768     : Boolean; stdcall;\r
62769 var\r
62770   SetLayeredWindowAttributes: TSetLayeredWindowAttributes;\r
62771   User32: THandle;\r
62772   dw: DWORD;\r
62773 begin\r
62774   if Value = fAlphaBlend then Exit;\r
62775   fAlphaBlend := Value;\r
62776   User32 := GetModuleHandle( 'User32' );\r
62777   SetLayeredWindowAttributes := GetProcAddress( User32,\r
62778                              'SetLayeredWindowAttributes' );\r
62779   if Assigned( SetLayeredWindowAttributes ) then\r
62780   begin\r
62781     dw := GetWindowLong( GetWindowHandle, GWL_EXSTYLE );\r
62782     if Byte( Value ) < 255 then\r
62783     begin\r
62784       SetWindowLong( fHandle, GWL_EXSTYLE, dw or WS_EX_LAYERED );\r
62785       SetLayeredWindowAttributes( fHandle, 0, Value and $FF, LWA_ALPHA);\r
62786     end\r
62787        else\r
62788       SetWindowLong( fHandle, GWL_EXSTYLE, dw and not WS_EX_LAYERED );\r
62789   end;\r
62790 end;\r
62792 //[function TControl.SetPosition]\r
62793 function TControl.SetPosition( X, Y: Integer ): PControl;\r
62794 begin\r
62795   Left := X;\r
62796   Top := Y;\r
62797   Result := @Self;\r
62798 end;\r
62800 //[function NewColorDialog]\r
62801 function NewColorDialog( FullOpen: TColorCustomOption ): PColorDialog;\r
62802 var I: Integer;\r
62803 begin\r
62804   {-}\r
62805   New( Result, Create );\r
62806   {+}{++}(*Result := PColorDialog.Create;*){--}\r
62807   Result.ColorCustomOption := FullOpen;\r
62808   for I := 1 to 16 do\r
62809     Result.CustomColors[ I ] := clWhite;\r
62810 end;\r
62811 //[END NewColorDialog]\r
62813 { TColorDialog }\r
62815 //[function TColorDialog.Execute]\r
62816 function TColorDialog.Execute: Boolean;\r
62817 var CD: TChooseColor;\r
62818 begin\r
62819   CD.lStructSize := Sizeof( CD );\r
62820   CD.hWndOwner := OwnerWindow;\r
62821   //CD.hInstance := 0;\r
62822   CD.rgbResult := Color2RGB( Color );\r
62823   CD.lpCustColors := @CustomColors[ 1 ];\r
62824   CD.Flags := CC_RGBINIT;\r
62825   case ColorCustomOption of\r
62826   ccoFullOpen: CD.Flags := CD.Flags or CC_FULLOPEN;\r
62827   ccoPreventFullOpen: CD.Flags := CD.Flags or CC_PREVENTFULLOPEN;\r
62828   end;\r
62829   Result := ChooseColor( CD );\r
62830   if Result then\r
62831     Color := CD.rgbResult;\r
62832 end;\r
62834 //[procedure TControl.SetMaxProgress]\r
62835 procedure TControl.SetMaxProgress(const Index, Value: Integer);\r
62836 begin\r
62837   // ignore index, and set Value via PBM_SETRANGE32:     ()\r
62838   Perform( PBM_SETRANGE32, 0, Value );\r
62839 end;\r
62841 //[procedure TControl.SetDroppedWidth]\r
62842 procedure TControl.SetDroppedWidth(const Value: Integer);\r
62843 begin\r
62844   FDroppedWidth := Value;\r
62845   Perform( CB_SETDROPPEDWIDTH, Value, 0 );\r
62846 end;\r
62848 //[function TControl.LVGetItemState]\r
62849 function TControl.LVGetItemState(Idx: Integer): TListViewItemState;\r
62850 type\r
62851   PListViewItemState = ^TListViewItemState;\r
62852 var I: Byte;\r
62853 begin\r
62854   I := Perform( LVM_GETITEMSTATE, Idx,\r
62855                 LVIS_CUT or LVIS_DROPHILITED or LVIS_FOCUSED or LVIS_SELECTED );\r
62856   Result := PListViewItemState( @ I )^;\r
62857 end;\r
62859 //[procedure TControl.LVSetItemState]\r
62860 procedure TControl.LVSetItemState(Idx: Integer; const Value: TListViewItemState);\r
62861 var Data: TLVItem;\r
62862 begin\r
62863   //FillChar( Data, Sizeof( Data ), 0 );\r
62864   //Data.mask := LVIF_DI_SETITEM or LVIF_STATE;\r
62865   Data.stateMask := LVIS_FOCUSED or LVIS_SELECTED or LVIS_CUT or LVIS_DROPHILITED;\r
62866   Data.state     := PByte( @ Value )^;\r
62867   //Data.iItem     := Idx;\r
62868   Perform( LVM_SETITEMSTATE, Idx, Integer( @Data ) );\r
62869 end;\r
62871 //[procedure TControl.LVSelectAll]\r
62872 procedure TControl.LVSelectAll;\r
62873 begin\r
62874   LVSetItemState( -1, [ lvisSelect ] );\r
62875 end;\r
62877 //[function TControl.LVItemInsert]\r
62878 function TControl.LVItemInsert(Idx: Integer; const aText: String): Integer;\r
62879 var LVI: TLVItem;\r
62880 begin\r
62881   LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;\r
62882   LVI.iItem := Idx;\r
62883   LVI.iSubItem := 0;\r
62884   LVI.pszText := PChar( aText );\r
62885   Result := Perform( LVM_INSERTITEM, 0, Integer( @LVI ) );\r
62886 end;\r
62888 {$IFNDEF _FPC}\r
62889 {$IFNDEF _D2}\r
62890 //[function TControl.LVItemInsertW]\r
62891 function TControl.LVItemInsertW(Idx: Integer;\r
62892   const aText: WideString): Integer;\r
62893 var LVI: TLVItemW;\r
62894 begin\r
62895   LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;\r
62896   LVI.iItem := Idx;\r
62897   LVI.iSubItem := 0;\r
62898   LVI.pszText := PWideChar( aText );\r
62899   Result := Perform( LVM_INSERTITEMW, 0, Integer( @LVI ) );\r
62900 end;\r
62901 {$ENDIF _D2}\r
62902 {$ENDIF _FPC}\r
62904 //[function TControl.LVItemAdd]\r
62905 function TControl.LVItemAdd(const aText: String): Integer;\r
62906 begin\r
62907   Result := LVItemInsert( Count, aText );\r
62908 end;\r
62910 {$IFNDEF _FPC}\r
62911 {$IFNDEF _D2}\r
62912 //[function TControl.LVItemAddW]\r
62913 function TControl.LVItemAddW(const aText: WideString): Integer;\r
62914 begin\r
62915   Result := LVItemInsertW( Count, aText );\r
62916 end;\r
62917 {$ENDIF _D2}\r
62918 {$ENDIF _FPC}\r
62920 //[function TControl.LVGetSttImgIdx]\r
62921 function TControl.LVGetSttImgIdx(Idx: Integer): Integer;\r
62922 begin\r
62923   Result := Perform( LVM_GETITEMSTATE, Idx, LVIS_STATEIMAGEMASK ) shr 12;\r
62924 end;\r
62926 //[procedure TControl.LVSetSttImgIdx]\r
62927 procedure TControl.LVSetSttImgIdx(Idx: Integer; const Value: Integer);\r
62928 var LVI: TLVItem;\r
62929 begin\r
62930   LVI.stateMask := LVIS_STATEIMAGEMASK;\r
62931   LVI.state := Value shl 12;\r
62932   Perform( LVM_SETITEMSTATE, Idx, Integer( @LVI ) );\r
62933 end;\r
62935 //[function TControl.LVGetOvlImgIdx]\r
62936 function TControl.LVGetOvlImgIdx(Idx: Integer): Integer;\r
62937 begin\r
62938   Result := Perform( LVM_GETITEMSTATE, Idx, LVIS_OVERLAYMASK ) shr 8;\r
62939 end;\r
62941 //[procedure TControl.LVSetOvlImgIdx]\r
62942 procedure TControl.LVSetOvlImgIdx(Idx: Integer; const Value: Integer);\r
62943 var LVI: TLVItem;\r
62944 begin\r
62945   LVI.stateMask := LVIS_OVERLAYMASK;\r
62946   LVI.state := Value shl 8;\r
62947   Perform( LVM_SETITEMSTATE, Idx, Integer( @LVI ) );\r
62948 end;\r
62950 //[function TControl.LVGetItemData]\r
62951 function TControl.LVGetItemData(Idx: Integer): DWORD;\r
62952 var LVI: TLVItem;\r
62953 begin\r
62954   LVI.mask := LVIF_PARAM;\r
62955   LVI.iItem := Idx;\r
62956   LVI.iSubItem := 0;\r
62957   Perform( LVM_GETITEM, 0, Integer( @LVI ) );\r
62958   Result := LVI.lParam;\r
62959 end;\r
62961 //[procedure TControl.LVSetItemData]\r
62962 procedure TControl.LVSetItemData(Idx: Integer; const Value: DWORD);\r
62963 var LVI: TLVItem;\r
62964 begin\r
62965   LVI.mask := LVIF_PARAM;\r
62966   LVI.iItem := Idx;\r
62967   LVI.iSubItem := 0;\r
62968   LVI.lParam := Value;\r
62969   Perform( LVM_SETITEM, 0, Integer( @LVI ) );\r
62970 end;\r
62972 //[function TControl.LVGetItemIndent]\r
62973 function TControl.LVGetItemIndent(Idx: Integer): Integer;\r
62974 var LI: TLVItem;\r
62975 begin\r
62976   LI.mask := LVIF_INDENT;\r
62977   LI.iItem := Idx;\r
62978   LI.iSubItem := 0;\r
62979   Perform( LVM_GETITEM, 0, Integer( @LI ) );\r
62980   Result := LI.iIndent;\r
62981 end;\r
62983 //[procedure TControl.LVSetItemIndent]\r
62984 procedure TControl.LVSetItemIndent(Idx: Integer; const Value: Integer);\r
62985 var LI: TLVItem;\r
62986 begin\r
62987   LI.mask := LVIF_INDENT or LVIF_DI_SETITEM;\r
62988   LI.iItem := Idx;\r
62989   LI.iSubItem := 0;\r
62990   LI.iIndent := Value;\r
62991   Perform( LVM_SETITEM, 0, Integer( @LI ) );\r
62992 end;\r
62994 type\r
62995   TNMLISTVIEW = packed Record\r
62996     hdr: TNMHDR;\r
62997     iItem: Integer;\r
62998     iSubItem: Integer;\r
62999     uNewState: Integer;\r
63000     uOldState: Integer;\r
63001     uChanged: Integer;\r
63002     ptAction: Integer;\r
63003     lParam: DWORD;\r
63004   end;\r
63005   PNMLISTVIEW = ^TNMLISTVIEW;\r
63007 //[function WndProc_LVDeleteItem]\r
63008 function WndProc_LVDeleteItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )\r
63009                           : Boolean;\r
63010 var Hdr: PNMHDR;\r
63011     LV: PNMListView;\r
63012 begin\r
63013   Result := FALSE;\r
63014   if Msg.message = WM_NOTIFY then\r
63015   begin\r
63016     Hdr := Pointer(Msg.lParam);\r
63017     if Hdr.hwndFrom = Sender.Handle then\r
63018     begin\r
63019       LV := Pointer( Hdr );\r
63020       if Hdr.code = LVN_DELETEITEM then\r
63021       begin\r
63022         if Assigned( Sender.OnDeleteLVItem ) then\r
63023           Sender.OnDeleteLVItem( Sender, LV.iItem );\r
63024         Result := TRUE;\r
63025       end\r
63026         else\r
63027       if Hdr.code = LVN_DELETEALLITEMS then\r
63028       begin\r
63029         if Assigned( Sender.OnDeleteAllLVItems ) then\r
63030         begin\r
63031           Sender.OnDeleteAllLVItems( Sender );\r
63032           Rslt := 0;\r
63033           if Assigned( Sender.OnDeleteLVItem ) then\r
63034             Rslt := 1;\r
63035         end;\r
63036         Result := TRUE;\r
63037       end;\r
63038     end;\r
63039   end;\r
63040 end;\r
63042 //[procedure TControl.SetOnDeleteAllLVItems]\r
63043 procedure TControl.SetOnDeleteAllLVItems(const Value: TOnEvent);\r
63044 begin\r
63045   fOnDeleteAllLVItems := Value;\r
63046   AttachProc( @WndProc_LVDeleteItem );\r
63047 end;\r
63049 //[procedure TControl.SetOnDeleteLVItem]\r
63050 procedure TControl.SetOnDeleteLVItem(const Value: TOnDeleteLVItem);\r
63051 begin\r
63052   fOnDeleteLVItem := Value;\r
63053   AttachProc( @WndProc_LVDeleteItem );\r
63054 end;\r
63056 //[function WndProc_LVData]\r
63057 function WndProc_LVData( Sender: PControl; var Msg: TMsg; var Rslt: Integer )\r
63058                           : Boolean;\r
63059 var Hdr: PNMHDR;\r
63060     DI: PLVDispInfo;\r
63061     Store: Boolean;\r
63062     Txt: String;\r
63063     LV: PControl;\r
63064     {$IFDEF UNICODE_CTRLS}\r
63065     TxtW: WideString;\r
63066     {$ENDIF UNICODE_CTRLS}\r
63067 begin\r
63068   Result := FALSE;\r
63069   if Msg.message = WM_NOTIFY then\r
63070   begin\r
63071     Hdr := Pointer(Msg.lParam);\r
63072     if Hdr.hwndFrom = Sender.Handle then\r
63073     begin\r
63074       if (Hdr.code = LVN_GETDISPINFO)\r
63075          {$IFDEF UNICODE_CTRLS}\r
63076          or (Hdr.code = LVN_GETDISPINFOW)\r
63077          {$ENDIF UNICODE_CTRLS}\r
63078       then\r
63079       begin\r
63080         DI := Pointer( Hdr );\r
63081         LV := Sender;\r
63082         if LV <> nil then\r
63083         begin\r
63084           Txt := '';\r
63085           DI.item.iImage := -1;\r
63086           DI.item.state := 0;\r
63087           Store := FALSE;\r
63088           if (Assigned( LV.OnLVData )\r
63089                {$IFDEF UNICODE_CTRLS}\r
63090                or Assigned( LV.OnLVDataW )\r
63091                {$ENDIF UNICODE_CTRLS}\r
63092              )\r
63093              and (DI.item.iItem >= 0) then\r
63094           begin\r
63095             {$IFDEF UNICODE_CTRLS}\r
63096             TxtW := '';\r
63097             if Assigned( LV.ONLVDataW ) then\r
63098               LV.OnLVDataW( LV, DI.item.iItem, DI.item.iSubItem, TxtW,\r
63099                             DI.item.iImage, DWORD( DI.item.state ), Store )\r
63100             else\r
63101             {$ENDIF UNICODE_CTRLS}\r
63102             LV.OnLVData( LV, DI.item.iItem, DI.item.iSubItem, Txt,\r
63103                              DI.item.iImage, DWORD( DI.item.state ), Store );\r
63104             {$IFNDEF UNICODE_CTRLS}\r
63105             if (LV.fCaption = nil) or (Integer( StrLen( LV.fCaption ) ) <=\r
63106                Length( Txt ) ) then\r
63107             {$ENDIF UNICODE_CTRLS}\r
63108             begin\r
63109               if LV.fCaption <> nil then\r
63110                 FreeMem( LV.fCaption );\r
63111               {$IFDEF UNICODE_CTRLS}\r
63112               GetMem( LV.fCaption, (Length( Txt ) + Length( TxtW ) + 1)\r
63113                       * Sizeof( WideChar ) );\r
63114               {$ELSE NOT_UNICODE_CTRLS}\r
63115               GetMem( LV.fCaption, Length( Txt ) + 1 );\r
63116               {$ENDIF NOT_UNICODE_CTRLS}\r
63117             end;\r
63118             {$IFDEF UNICODE_CTRLS}\r
63119             PWord( @ LV.fCaption[ 0 ] )^ := 0;\r
63120             {$ELSE}\r
63121             LV.fCaption[ 0 ] := #0;\r
63122             {$ENDIF}\r
63123             if Txt {$IFDEF UNICODE_CTRLS} + TxtW {$ENDIF UNICODE_CTRLS}\r
63124                <> '' then\r
63125             begin\r
63126               {$IFDEF UNICODE_CTRLS}\r
63127               if Hdr.code = LVN_GETDISPINFOW then\r
63128               begin\r
63129                 if Txt <> '' then\r
63130                   TxtW := Txt;\r
63131                 Move( TxtW[ 1 ], LV.fCaption[ 0 ], (Length( TxtW ) + 1) * Sizeof( WideChar ) );\r
63132               end else\r
63133               {$ENDIF UNICODE_CTRLS}\r
63134               StrCopy( LV.fCaption, @Txt[ 1 ] );\r
63135             end;\r
63136             DI.item.pszText := LV.fCaption;\r
63137             if Store then\r
63138               DI.item.mask := DI.item.mask or LVIF_DI_SETITEM;\r
63139           end;\r
63140           Result := TRUE;\r
63141         end;\r
63142       end;\r
63143     end;\r
63144   end;\r
63145 end;\r
63147 //[procedure TControl.SetOnLVData]\r
63148 procedure TControl.SetOnLVData(const Value: TOnLVData);\r
63149 begin\r
63150   fOnLVData := Value;\r
63151   AttachProc( @WndProc_LVData );\r
63152   Perform( LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK or LVIS_STATEIMAGEMASK, 0 );\r
63153 end;\r
63155 {$IFNDEF _FPC}\r
63156 {$IFNDEF _D2}\r
63157 //[procedure TControl.SetOnLVDataW]\r
63158 procedure TControl.SetOnLVDataW(const Value: TOnLVDataW);\r
63159 begin\r
63160   fOnLVDataW := Value;\r
63161   AttachProc( @WndProc_LVData );\r
63162   Perform( LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK or LVIS_STATEIMAGEMASK, 0 );\r
63163 end;\r
63164 {$ENDIF _D2}\r
63165 {$ENDIF _FPC}\r
63167 //[function WndProc_LVCustomDraw]\r
63168 function WndProc_LVCustomDraw( Sender: PControl; var Msg: TMsg;\r
63169                                var Rslt: Integer ): Boolean;\r
63170 var NMCustDraw: PNMLVCustomDraw;\r
63171     NMHdr: PNMHdr;\r
63172     ItemIdx, SubItemIdx: Integer;\r
63173     S: TListViewItemState;\r
63174     ItemState: TDrawState;\r
63175 begin\r
63176   Result := FALSE;\r
63177   if Msg.message = WM_NOTIFY then\r
63178   begin\r
63179     NMHdr := Pointer( Msg.lParam );\r
63180     if (NMHdr.code = NM_CUSTOMDRAW) and Assigned( Sender.fOnLVCustomDraw ) then\r
63181     begin\r
63182       NMCustDraw := Pointer( Msg.lParam );\r
63183       ItemIdx := -1;\r
63184       SubItemIdx := -1;\r
63185       if LongBool( NMCustDraw.nmcd.dwDrawStage and CDDS_ITEM ) then\r
63186         ItemIdx := NMCustDraw.nmcd.dwItemSpec;\r
63187       if LongBool( NMCustDraw.nmcd.dwDrawStage and CDDS_SUBITEM ) then\r
63188         SubItemIdx := NMCustDraw.iSubItem;\r
63189       ItemState := [ ];\r
63190       if ItemIdx >= 0 then\r
63191       begin\r
63192         S := Sender.LVItemState[ ItemIdx ];\r
63193         if lvisFocus in S then\r
63194           ItemState := ItemState + [ odsFocused ];\r
63195         if lvisSelect in S then\r
63196           ItemState := ItemState + [ odsSelected ];\r
63197         if lvisBlend in S then\r
63198           ItemState := ItemState + [ odsGrayed ];\r
63199         if lvisHighlight in S then\r
63200           ItemState := ItemState + [ odsMarked ];\r
63201       end;\r
63203       Sender.Canvas;\r
63205       Rslt := Sender.FOnLVCustomDraw( Sender, {Sender.Canvas.Handle} NMCustDraw.nmcd.hdc,\r
63206            NMCustDraw.nmcd.dwDrawStage, ItemIdx, SubItemIdx, NMCustDraw.nmcd.rc,\r
63207            ItemState, TColor( NMCustDraw.clrText ), TColor( NMCustDraw.clrTextBk ) );\r
63209       Result := TRUE;\r
63210     end;\r
63211   end;\r
63212 end;\r
63214 //[procedure TControl.SetOnLVCustomDraw]\r
63215 procedure TControl.SetOnLVCustomDraw(const Value: TOnLVCustomDraw);\r
63216 begin\r
63217   fOnLVCustomDraw := Value;\r
63218   AttachProc( @WndProc_LVCustomDraw );\r
63219 end;\r
63221 //[function CompareLVItems]\r
63222 function CompareLVItems( Idx1, Idx2: Integer; ListView: PControl ): Integer; stdcall;\r
63223 begin\r
63224   if Assigned( ListView.fOnCompareLVItems ) then\r
63225     Result := ListView.fOnCompareLVItems( ListView, Idx1, Idx2 )\r
63226   else\r
63227     Result := 0;\r
63228 end;\r
63230 //[procedure TControl.LVSort]\r
63231 procedure TControl.LVSort;\r
63232 begin\r
63233   Perform( LVM_SORTITEMSEX, Integer(@Self), Integer(@CompareLVItems) );\r
63234 end;\r
63236 //[function CompareLVItemsData]\r
63237 function CompareLVItemsData( D1, D2: DWORD; ListView: PControl ): Integer; stdcall;\r
63238 begin\r
63239   if Assigned( ListView.fOnCompareLVItems ) then\r
63240     Result := ListView.fOnCompareLVItems( ListView, D1, D2 )\r
63241   else\r
63242     Result := 0;\r
63243 end;\r
63245 //[procedure TControl.LVSortData]\r
63246 procedure TControl.LVSortData;\r
63247 begin\r
63248   Perform( LVM_SORTITEMS, Integer( @Self ), Integer( @CompareLVItemsData ) );\r
63249 end;\r
63251 //[function WndProc_LVColumnClick]\r
63252 function WndProc_LVColumnClick( Sender: PControl; var Msg: TMsg; var Rslt: Integer )\r
63253                           : Boolean;\r
63254 var Hdr: PNMHDR;\r
63255     LV: PNMListView;\r
63256 begin\r
63257   Result := FALSE;\r
63258   if Msg.message = WM_NOTIFY then\r
63259   begin\r
63260     Hdr := Pointer(Msg.lParam);\r
63261     if Hdr.hwndFrom = Sender.Handle then\r
63262     begin\r
63263       LV := Pointer( Hdr );\r
63264       if Hdr.code = LVN_COLUMNCLICK then\r
63265       begin\r
63266         if Assigned( Sender.OnColumnClick ) then\r
63267           Sender.OnColumnClick( Sender, LV.iSubItem );\r
63268         Result := TRUE;\r
63269       end;\r
63270     end;\r
63271   end;\r
63272 end;\r
63274 //[procedure TControl.SetOnColumnClick]\r
63275 procedure TControl.SetOnColumnClick(const Value: TOnLVColumnClick);\r
63276 begin\r
63277   fOnColumnClick := Value;\r
63278   AttachProc( @WndProc_LVColumnClick );\r
63279 end;\r
63281 //[function WndProc_LVStateChange]\r
63282 function WndProc_LVStateChange( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;\r
63283 var NMOD: PNMLVODStateChange;\r
63284     NMLV: PNMLISTVIEW;\r
63285 begin\r
63286   if Msg.message = WM_NOTIFY then\r
63287   begin\r
63288     NMOD := Pointer( Msg.lParam );\r
63289     NMLV := Pointer( Msg.lParam );\r
63290     if NMOD.hdr.code = LVN_ODSTATECHANGED then\r
63291     begin\r
63292       if Assigned( Sender.OnLVStateChange ) then\r
63293         Sender.OnLVStateChange( Sender, NMOD.iFrom, NMOD.iTo,\r
63294                                 NMOD.uOldState, NMOD.uNewState );\r
63295     end\r
63296       else\r
63297     if NMLV.hdr.code = LVN_ITEMCHANGED then\r
63298     begin\r
63299       if Assigned( Sender.OnLVStateChange ) then\r
63300         Sender.OnLVStateChange( Sender, NMLV.iItem, NMLV.iItem,\r
63301                                 NMLV.uOldState, NMLV.uNewState );\r
63302     end;\r
63303   end;\r
63304   Result := FALSE;\r
63305 end;\r
63307 //[procedure TControl.SetOnLVStateChange]\r
63308 procedure TControl.SetOnLVStateChange(const Value: TOnLVStateChange);\r
63309 begin\r
63310   FOnLVStateChange := Value;\r
63311   AttachProc( WndProc_LVStateChange );\r
63312 end;\r
63314 //[function WndProc_LVDelete]\r
63315 function WndProc_LVDelete( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;\r
63316 var NMLV: PNMLISTVIEW;\r
63317 begin\r
63318   if Msg.message = WM_NOTIFY then\r
63319   begin\r
63320     NMLV := Pointer( Msg.lParam );\r
63321     if NMLV.hdr.code = LVN_DELETEITEM then\r
63322     begin\r
63323       if Assigned( Sender.OnLVDelete ) then\r
63324         Sender.OnLVDelete( Sender, NMLV.iItem );\r
63325     end;\r
63326   end;\r
63327   Result := FALSE;\r
63328 end;\r
63330 //[procedure TControl.SetOnLVDelete]\r
63331 procedure TControl.SetOnLVDelete(const Value: TOnLVDelete);\r
63332 begin\r
63333   FOnLVDelete := Value;\r
63334   Add2AutoFreeEx( Clear );\r
63335   AttachProcEx( WndProc_LVDelete, TRUE );\r
63336   if fParent <> nil then\r
63337   begin\r
63338     fParent.DetachProc( WndProcNotify );\r
63339     fParent.AttachProcEx( WndProcNotify, TRUE );\r
63340   end;\r
63341 end;\r
63343 //[function CompareLVColumns]\r
63344 function CompareLVColumns( Idx1, Idx2: Integer; Sender: PControl ): Integer; stdcall;\r
63345 var S1, S2: String;\r
63346 begin\r
63347   //--- changed by Mike Gerasimov:\r
63348   S1 := Sender.LVItems[ Idx1, Sender.fColumn ];\r
63349   S2 := Sender.LVItems[ Idx2, Sender.fColumn ];\r
63350   If lvoSortAscending in Sender.fLVOptions Then\r
63351    Result := AnsiCompareStrNoCase( S1, S2 )\r
63352   Else\r
63353    If lvoSortDescending in Sender.fLVOptions Then\r
63354     Result := AnsiCompareStrNoCase( S2, S1 )\r
63355    Else\r
63356     Result:=0;\r
63357 end;\r
63359 //[procedure TControl.LVSortColumn]\r
63360 procedure TControl.LVSortColumn(Idx: Integer);\r
63361 begin\r
63362   fColumn := Idx;\r
63363   Perform( LVM_SORTITEMSEX, Integer(@Self), Integer(@CompareLVColumns) );\r
63364 end;\r
63366 //[function TControl.LVIndexOf]\r
63367 function TControl.LVIndexOf(const S: String): Integer;\r
63368 begin\r
63369   Result := LVSearchFor( S, -1, FALSE );\r
63370 end;\r
63372 {$IFNDEF _FPC}\r
63373 {$IFNDEF _D2}\r
63374 //[function TControl.LVIndexOfW]\r
63375 function TControl.LVIndexOfW(const S: WideString): Integer;\r
63376 begin\r
63377   Result := LVSearchForW( S, -1, FALSE );\r
63378 end;\r
63379 {$ENDIF _D2}\r
63380 {$ENDIF _FPC}\r
63382 //[function TControl.LVSearchFor]\r
63383 function TControl.LVSearchFor(const S: String; StartAfter: Integer;\r
63384   Partial: Boolean): Integer;\r
63385 var f: TLVFindInfo;\r
63386 begin\r
63387     f.lParam := 0;\r
63388     f.flags  := LVFI_STRING;\r
63389     if Partial then\r
63390       f.flags := LVFI_STRING or LVFI_PARTIAL;\r
63391     f.psz    := @s[1];\r
63392     result := Perform(LVM_FINDITEM,StartAfter,integer(@f));\r
63393 end;\r
63395 {$IFNDEF _FPC}\r
63396 {$IFNDEF _D2}\r
63397 //[function TControl.LVSearchForW]\r
63398 function TControl.LVSearchForW(const S: WideString; StartAfter: Integer;\r
63399   Partial: Boolean): Integer;\r
63400 var f: TLVFindInfoW;\r
63401 begin\r
63402     f.lParam := 0;\r
63403     f.flags  := LVFI_STRING;\r
63404     if Partial then\r
63405       f.flags := LVFI_STRING or LVFI_PARTIAL;\r
63406     f.psz    := @s[1];\r
63407     result := Perform(LVM_FINDITEMW,StartAfter,integer(@f));\r
63408 end;\r
63409 {$ENDIF _D2}\r
63410 {$ENDIF _FPC}\r
63412 function WndProcLVMeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
63413 const\r
63414   ClsName: PChar = 'obj_SysListView32'#0;\r
63415 var\r
63416   pMI: PMeasureItemStruct;\r
63417   pLV: PControl;\r
63418   H: Integer;\r
63419   wnd: HWND;\r
63420   wId: DWORD;\r
63422 begin\r
63424   Result := FALSE;\r
63425   if Msg.message = WM_MEASUREITEM then begin\r
63426     pMI := Pointer(Msg.lParam);\r
63427     with pMI^ do begin\r
63428       if CtlType=ODT_LISTVIEW then begin\r
63429         wnd := 0;\r
63431         repeat\r
63432           wnd := FindWindowEx(Sender.GetWindowHandle,wnd,ClsName,nil);\r
63433           wId := GetWindowLong(wnd,GWL_ID);\r
63434           if CtlID = wId then begin\r
63435             pLV := Pointer(GetProp(wnd,ID_SELF));\r
63436             if pLV <> nil then begin\r
63437               H := pLV.Perform(WM_MEASUREITEM,0,0);\r
63438               if H > 0 then begin\r
63439                 itemHeight := H;\r
63440                 Rslt:=1;\r
63441                 Result := TRUE;\r
63442               end;\r
63443               break;\r
63444             end;\r
63445           end;\r
63446         until wnd = 0;\r
63448       end;\r
63449     end;\r
63450   end;\r
63451 end;\r
63453 function WndProcLVMeasureItem2( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
63454 begin\r
63455   Result := FALSE;\r
63456   if (Msg.message = WM_MEASUREITEM) and (Msg.wParam = 0) then begin\r
63457     Rslt := Sender.fLVItemHeight;\r
63458     Result := TRUE;\r
63459   end;\r
63461 end;\r
63463 function TControl.SetLVItemHeight(Value: Integer): PControl;\r
63464 begin\r
63465   Set_LVItemHeight( Value );\r
63466   Result := @ Self;\r
63467 end;\r
63469 procedure TControl.Set_LVItemHeight(Value: Integer);\r
63470 begin\r
63471   if fLVItemHeight <> Value then begin\r
63472     if fLVItemHeight = 0 then begin\r
63473       Parent.AttachProc(WndProcLVMeasureItem);\r
63474       AttachProc(WndProcLVMeasureItem2);\r
63475     end;\r
63476     fLVItemHeight := Value;\r
63477   end;\r
63478 end;\r
63480 //[function TControl.IndexOf]\r
63481 function TControl.IndexOf(const S: String): Integer;\r
63482 begin\r
63483   Result := SearchFor( S, -1, FALSE );\r
63484 end;\r
63486 //[function TControl.SearchFor]\r
63487 function TControl.SearchFor(const S: String; StartAfter: Integer;\r
63488   Partial: Boolean): Integer;\r
63489 var Cmd: Integer;\r
63490     I: Integer;\r
63491 begin\r
63492   Cmd := fCommandActions.aFindItem;\r
63493   if Partial then\r
63494     Cmd := fCommandActions.aFindPartial;\r
63495   if Cmd <> 0 then\r
63496     Result := Perform( Cmd, StartAfter, Integer( PChar( S ) ) )\r
63497   else\r
63498   begin\r
63499     Result := -1;\r
63500     for I := StartAfter+1 to Count-1 do\r
63501     begin\r
63502       if Partial and ( Copy( Items[ I ], 1, Length( S ) ) = S ) or\r
63503          ( Items[ I ] = S ) then\r
63504       begin\r
63505         Result := I;\r
63506         break;\r
63507       end;\r
63508     end;\r
63509   end;\r
63510 end;\r
63512 //[function TControl.DefaultBtnProc]\r
63513 function TControl.DefaultBtnProc(var Msg: TMsg;\r
63514   var Rslt: Integer): Boolean;\r
63515 var Btn: PControl;\r
63516     F: PControl;\r
63517     //Msg1: TMsg;\r
63518 begin\r
63519   if Assigned( fOldOnMessage ) then\r
63520   begin\r
63521     Result := fOldOnMessage( Msg, Rslt );\r
63522     if Result then Exit;\r
63523   end;\r
63524   Result := FALSE;\r
63525   if AppletTerminated then Exit;\r
63526   F := Applet;\r
63527   if not F.fIsForm then\r
63528   begin\r
63529     F := F.fCurrentControl;\r
63530     if F = nil then Exit;\r
63531   end;\r
63532   Btn := nil;\r
63533   if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP)) and\r
63534      ((Msg.wParam = VK_RETURN) or (Msg.wParam = VK_ESCAPE)) then\r
63535   begin\r
63536     if (Msg.wParam = VK_RETURN) and\r
63537        (F.fDefaultBtnCtl <> nil) and\r
63538        F.fDefaultBtnCtl.ToBeVisible and\r
63539        F.fDefaultBtnCtl.Enabled and\r
63540        ((F.fCurrentControl=nil) or (not F.fCurrentControl.fCancelBtn and\r
63541                                     not F.fCurrentControl.fIgnoreDefault)\r
63542                                 or (F.fCurrentControl = F.fDefaultBtnCtl)\r
63543        ) then\r
63544        Btn := F.fDefaultBtnCtl\r
63545       else\r
63546     if (Msg.wParam = VK_ESCAPE) and\r
63547        (F.fCancelBtnCtl <> nil) and\r
63548        F.fCancelBtnCtl.ToBeVisible and\r
63549        F.fCancelBtnCtl.Enabled then\r
63550        Btn := F.fCancelBtnCtl\r
63551       else\r
63552     if (Msg.wParam = VK_RETURN) and\r
63553        (F.fAllBtnReturnClick or fAllBtnReturnClick) and\r
63554        (F.ActiveControl <> nil) and\r
63555        (F.ActiveControl.IsButton) and\r
63556        (F.ActiveControl.Count = 0) then\r
63557        Btn := F.ActiveControl;\r
63558     if Btn <> nil then\r
63559     begin\r
63560       if Msg.message = WM_KEYDOWN then\r
63561         Btn.Focused := TRUE;\r
63562       Btn.Perform( Msg.message, DWORD( ' ' ), Msg.lParam );\r
63563       Msg.wParam := 0;\r
63564       Result := TRUE;\r
63565       Rslt := 0;\r
63566       Exit;\r
63567     end\r
63568   end;\r
63569   Result := FALSE;\r
63570 end;\r
63572 //[procedure TControl.SetDefaultBtn]\r
63573 procedure TControl.SetDefaultBtn(const Index: Integer;\r
63574   const Value: Boolean);\r
63575 var F, C: PControl;\r
63576 begin\r
63577   if Index = 13 then\r
63578   begin\r
63579     fDefaultBtn := Value;\r
63580     fCancelBtn := FALSE;\r
63581   end\r
63582     else\r
63583   if Index = 27 then\r
63584   begin\r
63585     fCancelBtn := Value;\r
63586     fDefaultBtn := FALSE;\r
63587   end;\r
63588   if Applet = nil then Exit;\r
63589   F := ParentForm;\r
63590   if F <> nil then\r
63591   begin\r
63592     if Value then\r
63593     begin\r
63594       if @ Applet.fOnMessage <> @ TControl.DefaultBtnProc  then\r
63595         Applet.fOldOnMessage := Applet.fOnMessage; // fixed by YS\r
63596       Applet.fOnMessage := Applet.DefaultBtnProc;\r
63597     end\r
63598       else\r
63599     begin\r
63600       Applet.fOnMessage := Applet.fOldOnMessage;\r
63601       Applet.fOldOnMessage := nil;\r
63602     end;\r
63603     C := nil;\r
63604     if Value then C := @ Self;\r
63605     if Index = 13 then\r
63606     begin\r
63607       F.fDefaultBtnCtl := C;\r
63608       if Value then\r
63609         Style := Style or BS_DEFPUSHBUTTON\r
63610       else\r
63611         Style := Style and not BS_DEFPUSHBUTTON;\r
63612     end\r
63613     else\r
63614     if Index = 27 then\r
63615       F.fCancelBtnCtl := C;\r
63616   end;\r
63617 end;\r
63619 {$IFDEF F_P}\r
63620 //[function TControl.GetDefaultBtn]\r
63621 function TControl.GetDefaultBtn(const Index: Integer): Boolean;\r
63622 begin\r
63623   CASE Index OF\r
63624   13: Result := fDefaultBtn;\r
63625   27: Result := fCancelBtn;\r
63626   END;\r
63627 end;\r
63628 {$ENDIF F_P}\r
63630 //[function TControl.AllBtnReturnClick]\r
63631 function TControl.AllBtnReturnClick: PControl;\r
63632 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}\r
63633 begin\r
63634   // nothing: already implemented in WndProcBtnReturnClick\r
63635   Result := @ Self;\r
63636 end;\r
63637 {$ELSE}\r
63638 var F: PControl;\r
63639 begin\r
63640   SetDefaultBtn( 0, TRUE );\r
63641   F := ParentForm;\r
63642   if F <> nil then\r
63643     F.fAllBtnReturnClick := TRUE;\r
63644   Result := @ Self;\r
63645 end;\r
63646 {$ENDIF}\r
63648 //[function WndProc_CNDrawItem]\r
63649 function WndProc_CNDrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )\r
63650                           : Boolean;\r
63651 type PDrawAction = ^TDrawAction;\r
63652      PDrawState = ^TDrawState;\r
63653 var DI: PDrawItemStruct;\r
63654 begin\r
63655   Result := FALSE;\r
63656   if Msg.message = CN_DRAWITEM then\r
63657   begin\r
63658     DI := Pointer( Msg.lParam );\r
63659     if Assigned( Sender.OnDrawItem ) then\r
63660     begin\r
63661       if Sender.OnDrawItem( Sender, DI.hDC, DI.rcItem, DI.itemID,\r
63662                          PDrawAction( @ DI.itemAction )^,\r
63663                          PDrawState( @ DI.itemState )^ )\r
63664         then Rslt := 1\r
63665         else Rslt := 0;\r
63666       Result := TRUE;\r
63667     end\r
63668       else Rslt := 0;\r
63669   end;\r
63670 end;\r
63672 //[procedure TControl.SetOnDrawItem]\r
63673 procedure TControl.SetOnDrawItem(const Value: TOnDrawItem);\r
63674 begin\r
63675   fOnDrawItem := Value;\r
63676   if Parent <> nil then\r
63677     Parent.AttachProc( @WndProc_DrawItem );\r
63678   AttachProc( @WndProc_CNDrawItem );\r
63679 end;\r
63681 //[function WndProc_MeasureItem]\r
63682 function WndProc_MeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )\r
63683                           : Boolean;\r
63684 var MI: PMeasureItemStruct;\r
63685     Control: PControl;\r
63686     I: Integer;\r
63687 begin\r
63688   Result := FALSE;\r
63689   if Msg.message = WM_MEASUREITEM then\r
63690   begin\r
63691     MI := Pointer( Msg.lParam );\r
63692     for I := 0 to Sender.ChildCount - 1 do\r
63693     begin\r
63694       Control := Sender.Children[ I ];\r
63695       if Control.Menu = MI.CtlID then\r
63696       begin\r
63697         if Assigned( Control.OnMeasureItem ) then\r
63698         begin\r
63699           MI.itemHeight := Control.OnMeasureItem( Control, MI.itemID );\r
63700           if MI.itemHeight > 0 then\r
63701           begin\r
63702             Rslt := 1;\r
63703             Result := TRUE;\r
63704           end;\r
63705         end;\r
63706         break;\r
63707       end;\r
63708     end;\r
63709   end;\r
63710 end;\r
63712 //[procedure TControl.SetOnMeasureItem]\r
63713 procedure TControl.SetOnMeasureItem(const Value: TOnMeasureItem);\r
63714 begin\r
63715   fOnMeasureItem := Value;\r
63716   if Parent <> nil then\r
63717     Parent.AttachProc( @WndProc_MeasureItem );\r
63718 end;\r
63720 //[function TControl.GetItemData]\r
63721 function TControl.GetItemData(Idx: Integer): DWORD;\r
63722 begin\r
63723   Result := 0;\r
63724   if fCommandActions.aGetItemData <> 0 then\r
63725     Result := Perform( fCommandActions.aGetItemData, Idx, 0 );\r
63726 end;\r
63728 //[procedure TControl.SetItemData]\r
63729 procedure TControl.SetItemData(Idx: Integer; const Value: DWORD);\r
63730 begin\r
63731   if fCommandActions.aSetItemData <> 0 then\r
63732     Perform( fCommandActions.aSetItemData, Idx, Value );\r
63733 end;\r
63735 //[function TControl.GetLVCurItem]\r
63736 function TControl.GetLVCurItem: Integer;\r
63737 begin\r
63738   Result := Perform( LVM_GETNEXTITEM, -1, LVNI_SELECTED );\r
63739 end;\r
63741 //[procedure TControl.SetLVCurItem]\r
63742 procedure TControl.SetLVCurItem(const Value: Integer);\r
63743 begin\r
63744   if (lvoMultiselect in LVOptions) or (Value <> LVCurItem ) then\r
63745     LVItemState[ -1 ] := [ ];\r
63746   if Value >= 0 then\r
63747     LVItemState[ Value ] := [ lvisSelect, lvisFocus ];\r
63748 end;\r
63750 //[function TControl.LVNextItem]\r
63751 function TControl.LVNextItem(IdxPrev: Integer; Attrs: DWORD): Integer;\r
63752 begin\r
63753   Result := Perform( LVM_GETNEXTITEM, IdxPrev, Attrs );\r
63754 end;\r
63756 //[function TControl.LVNextSelected]\r
63757 function TControl.LVNextSelected(IdxPrev: Integer): Integer;\r
63758 begin\r
63759   Result := Perform( LVM_GETNEXTITEM, IdxPrev, LVNI_SELECTED );\r
63760 end;\r
63762 //[procedure TControl.Close]\r
63763 procedure TControl.Close;\r
63764 begin\r
63765   PostMessage( Handle, WM_CLOSE, 0, 0 );\r
63766 end;\r
63768 //[function WndProcMinimize]\r
63769 function WndProcMinimize( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
63770 var Wnd: PControl;\r
63771 begin\r
63772   Result := FALSE;\r
63773   if (Msg.message = WM_SYSCOMMAND) and ((Msg.wParam and $FFF0) = SC_MINIMIZE)then\r
63774   begin\r
63775     if Applet <> nil then\r
63776     begin\r
63777       Wnd := Applet.FMinimizeWnd;\r
63778       if Wnd <> nil then\r
63779         SetWindowPos( Applet.Handle, 0, Wnd.Left, Wnd.Top, Wnd.Width, 0,\r
63780                       SWP_NOZORDER or SWP_NOREDRAW);\r
63781     end;\r
63782   end;\r
63783 end;\r
63785 //[procedure TControl.MinimizeNormalAnimated]\r
63786 procedure TControl.MinimizeNormalAnimated;\r
63787 var App: PControl;\r
63788 begin\r
63789   App := Applet;\r
63790   if App = nil then\r
63791     App := @Self;\r
63792   App.FMinimizeWnd := @Self;\r
63793   App.AttachProc( @WndProcMinimize );\r
63794 end;\r
63796 //[function WndProcDropFiles]\r
63797 function WndProcDropFiles( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
63798 var hDrop: THandle;\r
63799     Pt: TPoint;\r
63800     FList: String;\r
63801     I, N: Integer;\r
63802     Buf: array[ 0..MAX_PATH ] of Char;\r
63803 begin\r
63804   if Msg.message = WM_DROPFILES then\r
63805   if Assigned( Sender.FOnDropFiles ) then\r
63806   begin\r
63807     hDrop := Msg.wParam;\r
63808     DragQueryPoint( hDrop, Pt );\r
63809     N := DragQueryFile( hDrop, $FFFFffff, nil, 0 );\r
63810     FList := '';\r
63811     for I := 0 to N-1 do\r
63812     begin\r
63813       if FList <> '' then\r
63814         FList := FList + #13;\r
63815       DragQueryFile( hDrop, I, Buf, Sizeof( Buf ) );\r
63816       FList := FList + Buf;\r
63817     end;\r
63818     DragFinish( hDrop );\r
63819     Sender.FOnDropFiles( Sender, FList, Pt );\r
63820     Rslt := 0;\r
63821     Result := TRUE;\r
63822     Exit;\r
63823   end;\r
63824   Result := FALSE;\r
63825 end;\r
63827 //[procedure TControl.SetOnDropFiles]\r
63828 procedure TControl.SetOnDropFiles(const Value: TOnDropFiles);\r
63829 begin\r
63830   FOnDropFiles := Value;\r
63831   AttachProc( @WndProcDropFiles );\r
63832   DragAcceptFiles( GetWindowHandle, Assigned( Value ) );\r
63833 end;\r
63835 //[function WndProcShowHide]\r
63836 function WndProcShowHide( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
63837 var IsVisible: Boolean;\r
63838 begin\r
63839   if Msg.message = WM_SHOWWINDOW then\r
63840   if Msg.hwnd = Sender.Handle then\r
63841   begin\r
63842     IsVisible := IsWindowVisible( Sender.Handle );\r
63843     if LongBool( Msg.wParam ) then\r
63844     begin\r
63845       Sender.fVisible := TRUE;\r
63846       if not IsVisible then\r
63847       if Assigned( Sender.FOnShow ) then\r
63848         Sender.FOnShow( Sender );\r
63849     end\r
63850       else\r
63851     begin\r
63852       Sender.fVisible := FALSE;\r
63853       if IsVisible then\r
63854       if Assigned( Sender.FOnHide ) then\r
63855         Sender.FOnHide( Sender );\r
63856     end;\r
63857   end;\r
63858   Result := FALSE;\r
63859 end;\r
63861 //[procedure TControl.SetOnHide]\r
63862 procedure TControl.SetOnHide(const Value: TOnEvent);\r
63863 begin\r
63864   FOnHide := Value;\r
63865   AttachProc( WndProcShowHide );\r
63866 end;\r
63868 //[procedure TControl.SetOnShow]\r
63869 procedure TControl.SetOnShow(const Value: TOnEvent);\r
63870 begin\r
63871   FOnShow := Value;\r
63872   AttachProc( WndProcShowHide );\r
63873 end;\r
63875 //[function TControl.BringToFront]\r
63876 function TControl.BringToFront: PControl;\r
63877 begin\r
63878   SetWindowPos( GetWindowHandle, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or\r
63879                 SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_SHOWWINDOW );\r
63880   Result := @Self;\r
63881 end;\r
63883 //[function TControl.SendToBack]\r
63884 function TControl.SendToBack: PControl;\r
63885 begin\r
63886   SetWindowPos( GetWindowHandle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or\r
63887                 SWP_NOACTIVATE or SWP_NOOWNERZORDER );\r
63888   Result := @Self;\r
63889 end;\r
63891 //[procedure TControl.DragStart]\r
63892 procedure TControl.DragStart;\r
63893 begin\r
63894   PostMessage( GetWindowHandle, WM_SYSCOMMAND, $F012, 0 );\r
63895 end;\r
63897 //[function WndProcDragWindow]\r
63898 function WndProcDragWindow( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
63899 var P: TPoint;\r
63900 begin\r
63901   if Msg.message = WM_MOUSEMOVE then\r
63902   begin\r
63903     if Sender.FDragging then\r
63904     begin\r
63905       GetCursorPos( P );\r
63906       P.x := P.x - Sender.fMouseStartPos.x + Sender.fDragStartPos.x;\r
63907       P.y := P.y - Sender.fMouseStartPos.y + Sender.fDragStartPos.y;\r
63908       Sender.Position := P;\r
63909     end;\r
63910   end;\r
63911   Result := FALSE;\r
63912 end;\r
63914 //[procedure TControl.DragStartEx]\r
63915 procedure TControl.DragStartEx;\r
63916 var StartBounds: TRect;\r
63917 begin\r
63918   GetCursorPos( fMouseStartPos );\r
63919   StartBounds := BoundsRect;\r
63920   fDragStartPos.x := StartBounds.Left;\r
63921   fDragStartPos.y := StartBounds.Top;\r
63922   SetCapture( GetWindowHandle );\r
63923   fDragging := TRUE;\r
63924   AttachProc( WndProcDragWindow );\r
63925 end;\r
63927 //[procedure TControl.DragStopEx]\r
63928 procedure TControl.DragStopEx;\r
63929 begin\r
63930   if FDragging then\r
63931   begin\r
63932     ReleaseCapture;\r
63933     FDragging := FALSE;\r
63934   end;\r
63935 end;\r
63937 //[function CallDragCallBack]\r
63938 function CallDragCallBack( Sender: PControl; var Stop: Boolean ): Boolean;\r
63939 var P: TPoint;\r
63940     Shape, ShapeWas: Integer;\r
63941 begin\r
63942   GetCursorPos( P );\r
63943   Shape := LoadCursor( 0, IDC_HAND );\r
63944   ShapeWas := Shape;\r
63945   Result := Sender.fDragCallback( Sender, P.x, P.y, Shape, Stop );\r
63946   if not Stop then\r
63947   begin\r
63948     if not Result then\r
63949       if Shape = ShapeWas then\r
63950         Shape := LoadCursor( 0, IDC_NO );\r
63951     ScreenCursor := Shape;\r
63952   end\r
63953     else\r
63954   begin\r
63955     ScreenCursor := 0;\r
63956     Shape := Sender.fCursor;\r
63957   end;\r
63958   Windows.SetCursor( Shape );\r
63959 end;\r
63961 //[function WndProcDrag]\r
63962 function WndProcDrag( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;\r
63963 var Stop: Boolean;\r
63964 begin\r
63965   if Sender.fDragging then\r
63966   begin\r
63967     Stop := FALSE;\r
63968     case Msg.message of\r
63969     WM_MOUSEMOVE:\r
63970       CallDragCallBack( Sender, Stop );\r
63971     WM_LBUTTONUP, WM_RBUTTONUP:\r
63972       begin\r
63973         Stop := TRUE;\r
63974         CallDragCallBack( Sender, Stop );\r
63975       end;\r
63976     else\r
63977       begin\r
63978         Result := FALSE;\r
63979         Exit;\r
63980       end;\r
63981     end;\r
63982     if Stop then\r
63983     begin\r
63984       ReleaseCapture;\r
63985       Sender.fDragging := FALSE;\r
63986     end\r
63987       else\r
63988     begin\r
63989       Result := TRUE;\r
63990       exit;\r
63991     end;\r
63992   end;\r
63993   Result := FALSE;\r
63994 end;\r
63996 //[procedure TControl.DragItem]\r
63997 procedure TControl.DragItem(OnDrag: TOnDrag);\r
63998 begin\r
63999   fDragCallback := OnDrag;\r
64000   fDragging := TRUE;\r
64001   SetCapture( GetWindowHandle );\r
64002   AttachProc( WndProcDrag );\r
64003 end;\r
64005 {-}\r
64006 {$IFDEF USE_CONSTRUCTORS} //****************************************************//\r
64007                                                                                 //\r
64008 //[constructor TControl.CreateWindowed]\r
64009 constructor TControl.CreateWindowed(AParent: PControl; AClassName: PChar;       //\r
64010   ACtl3D: Boolean);                                                             //\r
64011 begin                                                                           //\r
64012   CreateParented( AParent );                                                    //\r
64013   fOnDynHandlers := WndProcDummy;                                               //\r
64014   fWndProcKeybd := WndProcDummy;                                                //\r
64015   fWndProcResizeFlicks := WndProcDummy;                                         //\r
64016   fCommandActions.aClear := ClearText;                                          //\r
64017   fWindowed := True;                                                            //\r
64018   fControlClassName := AClassName;                                              //\r
64019                                                                                 //\r
64020   fControlClick := DummyObjProc;                                                //\r
64021                                                                                 //\r
64022   fColor := clBtnFace;                                                          //\r
64023   fTextColor := clWindowText;                                                   //\r
64024   fMargin := 2;                                                                 //\r
64025   fCtl3D := True;                                                               //\r
64026   fCtl3Dchild := True;                                                          //\r
64027   if AParent <> nil then                                                        //\r
64028   begin                                                                         //\r
64029      fWndProcResizeFlicks := AParent.fWndProcResizeFlicks;                      //\r
64030      fGotoControl := AParent.fGotoControl;                                      //\r
64031      fDoubleBuffered := AParent.fDoubleBuffered;                                //\r
64032      fTransparent := AParent.fTransparent;                                      //\r
64033      fCtl3Dchild := AParent.fCtl3Dchild;                                        //\r
64034      if AParent.fCtl3Dchild then                                                //\r
64035        fCtl3D := ACtl3D                                                         //\r
64036      else                                                                       //\r
64037        fCtl3D := False;                                                         //\r
64038      fMargin := AParent.fMargin;                                                //\r
64039      with fBoundsRect do                                                        //\r
64040      begin                                                                      //\r
64041        Left := AParent.fMargin + AParent.fClientLeft;                           //\r
64042        Top  := AParent.fMargin + AParent.fClientTop;                            //\r
64043        Right := Left + 64;                                                      //\r
64044        Bottom := Top + 64;                                                      //\r
64045      end;                                                                       //\r
64046      fTextColor := AParent.fTextColor;                                          //\r
64047      fFont := fFont.Assign( AParent.fFont );                                    //\r
64048      if fFont <> nil then                                                       //\r
64049      begin                                                                      //\r
64050        fFont.fOnChange := FontChanged;                                          //\r
64051        FontChanged( fFont );                                                    //\r
64052      end;                                                                       //\r
64053      fColor := AParent.fColor;                                                  //\r
64054      fBrush := fBrush.Assign( AParent.fBrush );                                 //\r
64055      if fBrush <> nil then                                                      //\r
64056      begin                                                                      //\r
64057        fBrush.fOnChange := BrushChanged;                                        //\r
64058        BrushChanged( fBrush );                                                  //\r
64059      end;                                                                       //\r
64060   end;                                                                          //\r
64061 end;                                                                            //\r
64062                                                                                 //\r
64063 //[constructor TControl.CreateApplet]\r
64064 constructor TControl.CreateApplet(const ACaption: String);                      //\r
64065 begin                                                                           //\r
64066   AppButtonUsed := True;                                                        //\r
64067   CreateWindowed( nil, 'App', TRUE );                                           //\r
64068   FIsApplet := TRUE;                                                            //\r
64069   fStyle := WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX              //\r
64070     or WS_CAPTION;                                                              //\r
64071   fExStyle := WS_EX_APPWINDOW;                                                  //\r
64072   FCreateWndExt := CreateAppButton;                                             //\r
64073   AttachProc( WndProcApp );                                                     //\r
64074   Caption := ACaption;                                                          //\r
64075 end;                                                                            //\r
64076                                                                                 //\r
64077 //[constructor TControl.CreateForm]\r
64078 constructor TControl.CreateForm(AParent: PControl; const ACaption: String);     //\r
64079 begin                                                                           //\r
64080   CreateWindowed( AParent, 'Form', TRUE );                                      //\r
64081   AttachProc( WndProcForm );                                                    //\r
64082   AttachProc( WndProcDoEraseBkgnd );                                            //\r
64083   Caption := ACaption;                                                          //\r
64084 end;                                                                            //\r
64085                                                                                 //\r
64086 //[constructor TControl.CreateControl]\r
64087 constructor TControl.CreateControl(AParent: PControl; AClassName: PChar;        //\r
64088   AStyle: DWORD; ACtl3D: Boolean; Actions: PCommandActions);                    //\r
64089 var Form: PControl;                                                             //\r
64090 begin                                                                           //\r
64091   CreateWindowed( AParent, AClassName, ACtl3D );                                //\r
64092   if Actions <> nil then                                                        //\r
64093     fCommandActions := Actions^;                                                //\r
64094   fIsControl := True;                                                           //\r
64095   fStyle := AStyle or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;                       //\r
64096   fVisible := (Style and WS_VISIBLE) <> 0;                                      //\r
64097   fTabstop := (Style and WS_TABSTOP) <> 0;                                      //\r
64098   if (AParent <> nil) then                                                      //\r
64099   begin                                                                         //\r
64100     Inc( AParent.ParentForm.fTabOrder );                                        //\r
64101     fTabOrder := AParent.ParentForm.fTabOrder;                                  //\r
64102   end;                                                                          //\r
64103   fLookTabKeys := [ tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn ];             //\r
64104   if fCtl3D then                                                                //\r
64105   begin                                                                         //\r
64106     fStyle := fStyle and not WS_BORDER;                                         //\r
64107     fExStyle := fExStyle or WS_EX_CLIENTEDGE;                                   //\r
64108   end;                                                                          //\r
64109   if (Style and WS_TABSTOP) <> 0 then                                           //\r
64110   begin                                                                         //\r
64111     Form := ParentForm;                                                         //\r
64112     if Form <> nil then                                                         //\r
64113     if Form.FCurrentControl = nil then                                          //\r
64114        Form.FCurrentControl := @Self;                                           //\r
64115   end;                                                                          //\r
64116   //fCreateParamsExt := CreateParams2;                                          //\r
64117   fMenu := CtlIdCount;                                                          //\r
64118   Inc( CtlIdCount );                                                            //\r
64119   AttachProc( WndProcCtrl );                                                    //\r
64120 end;                                                                            //\r
64121                                                                                 //\r
64122 //[constructor TControl.CreateButton]\r
64123 constructor TControl.CreateButton(AParent: PControl;                            //\r
64124   const ACaption: String);                                                      //\r
64125 begin                                                                           //\r
64126   CreateControl( AParent, 'BUTTON',                                             //\r
64127             WS_VISIBLE or WS_CHILD or                                           //\r
64128             BS_PUSHLIKE or WS_TABSTOP, False, @ButtonActions );                 //\r
64129   with fBoundsRect do                                                           //\r
64130     Bottom := Top + 22;                                                         //\r
64131   fTextAlign := taCenter;                                                       //\r
64132   Caption := ACaption;                                                          //\r
64133 end;                                                                            //\r
64134                                                                                 //\r
64135 //[constructor TControl.CreateBitBtn]\r
64136 constructor TControl.CreateBitBtn(AParent: PControl;                            //\r
64137   const ACaption: String; AOptions: TBitBtnOptions; ALayout: TGlyphLayout;      //\r
64138   AGlyphBitmap: HBitmap; AGlyphCount: Integer);                                 //\r
64139 var                                                                             //\r
64140     B: TBitmapInfo;                                                             //\r
64141     W, H: Integer;                                                              //\r
64142 begin                                                                           //\r
64143   CreateControl( AParent, 'BUTTON', WS_VISIBLE or WS_CHILD or                   //\r
64144             WS_TABSTOP or BS_OWNERDRAW, False, @ButtonActions );                //\r
64145   fBitBtnOptions := AOptions;                                                   //\r
64146   fGlyphLayout := ALayout;                                                      //\r
64147   fGlyphBitmap := AGlyphBitmap;                                                 //\r
64148   with fBoundsRect do                                                           //\r
64149   begin                                                                         //\r
64150     Bottom := Top + 22;                                                         //\r
64151     W := 0; H := 0;                                                             //\r
64152     if AGlyphBitmap <> 0 then                                                   //\r
64153     begin                                                                       //\r
64154       if bboImageList in AOptions then                                          //\r
64155         ImageList_GetIconSize( AGlyphBitmap, W, H )                             //\r
64156       else                                                                      //\r
64157         begin                                                                   //\r
64158           if GetObject( AGlyphBitmap, Sizeof(B), @B ) > 0 then                  //\r
64159           begin                                                                 //\r
64160             W := B.bmiHeader.biWidth;                                           //\r
64161             H := B.bmiHeader.biHeight;                                          //\r
64162             if AGlyphCount = 0 then                                             //\r
64163               AGlyphCount := W div H;                                           //\r
64164             if AGlyphCount > 1 then                                             //\r
64165               W := W div AGlyphCount;                                           //\r
64166           end;                                                                  //\r
64167         end;                                                                    //\r
64168       if W > 0 then                                                             //\r
64169         if ACaption = '' then                                                   //\r
64170           Right := Left + W                                                     //\r
64171         else                                                                    //\r
64172           Right := Right + W;                                                   //\r
64173       if H > 0 then                                                             //\r
64174         Bottom := Top + H;                                                      //\r
64175       if not ( bboNoBorder in AOptions ) then                                   //\r
64176       begin                                                                     //\r
64177         if W > 0 then                                                           //\r
64178           Inc( Right, 2 );                                                      //\r
64179         if H > 0 then                                                           //\r
64180           Inc( Bottom, 2 );                                                     //\r
64181       end;                                                                      //\r
64182     end;                                                                        //\r
64183     fGlyphWidth := W;                                                           //\r
64184     fGlyphHeight := H;                                                          //\r
64185   end;                                                                          //\r
64186   fGlyphCount := AGlyphCount;                                                   //\r
64187   if AParent <> nil then                                                        //\r
64188     AParent.AttachProc( WndProc_DrawItem );                                     //\r
64189   AttachProc( WndProcBitBtn );                                                  //\r
64190   fTextAlign := taCenter;                                                       //\r
64191   Caption := ACaption;                                                          //\r
64192 end;                                                                            //\r
64193                                                                                 //\r
64194 //[constructor TControl.CreateLabel]\r
64195 constructor TControl.CreateLabel(AParent: PControl;                             //\r
64196   const ACaption: String);                                                      //\r
64197 begin                                                                           //\r
64198   CreateControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or                   //\r
64199                          SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY,         //\r
64200                          False, @LabelActions );                                //\r
64201   fIsStaticControl := True;                                                     //\r
64202   fSizeRedraw := True;                                                          //\r
64203   fBoundsRect.Bottom := fBoundsRect.Top + 22;                                   //\r
64204   Caption := ACaption;                                                          //\r
64205 end;                                                                            //\r
64206                                                                                 //\r
64207 //[constructor TControl.CreateWordWrapLabel]\r
64208 constructor TControl.CreateWordWrapLabel(AParent: PControl;                     //\r
64209   const ACaption: String);                                                      //\r
64210 begin                                                                           //\r
64211   CreateLabel( AParent, ACaption );                                             //\r
64212   fBoundsRect.Bottom := fBoundsRect.Top + 44;                                   //\r
64213   fStyle := fStyle and not SS_LEFTNOWORDWRAP;                                   //\r
64214 end;                                                                            //\r
64215                                                                                 //\r
64216 //[constructor TControl.CreateLabelEffect]\r
64217 constructor TControl.CreateLabelEffect(AParent: PControl; ACaption: String;     //\r
64218   AShadowDeep: Integer);                                                        //\r
64219 begin                                                                           //\r
64220   CreateLabel( AParent, ACaption );                                             //\r
64221   fIsStaticControl := False;                                                    //\r
64222   AttachProc( WndProcLabelEffect );                                             //\r
64223   fTextAlign := taCenter;                                                       //\r
64224   fTextColor := clBtnShadow;                                                    //\r
64225   fShadowDeep := AShadowDeep;                                                   //\r
64226   fIgnoreWndCaption := True;                                                    //\r
64227   with fBoundsRect do                                                           //\r
64228   begin                                                                         //\r
64229     Bottom := Top + 40;                                                         //\r
64230   end;                                                                          //\r
64231 end;                                                                            //\r
64232                                                                                 //\r
64233 //[constructor TControl.CreatePaintBox]\r
64234 constructor TControl.CreatePaintBox(AParent: PControl);                         //\r
64235 begin                                                                           //\r
64236   CreateLabel( AParent, '' );                                                   //\r
64237   with fBoundsRect do                                                           //\r
64238   begin                                                                         //\r
64239     Right := Left + 40;                                                         //\r
64240     Bottom := Top + 40;                                                         //\r
64241   end;                                                                          //\r
64242 end;                                                                            //\r
64243                                                                                 //\r
64244 {$IFDEF ASM_VERSION}                                                            //\r
64245 //[constructor TControl.CreateGradientPanel]\r
64246 constructor TControl.CreateGradientPanel(AParent: PControl; AColor1,            //\r
64247   AColor2: TColor);                                                             //\r
64248 asm     //cmd    //opd                                                          //\r
64249         XOR      EDX, EDX                                                       //\r
64250         PUSH     EDX                                                            //\r
64251         CALL     CreateLabel                                                    //\r
64252         MOV      ECX, AColor1                                                   //\r
64253         MOV      [EAX].fColor1, ECX                                             //\r
64254         MOV      ECX, AColor2                                                   //\r
64255         MOV      [EAX].fColor2, ECX                                             //\r
64256         MOV      EDX, [EAX].fBoundsRect.Left                                    //\r
64257         ADD      EDX, 40                                                        //\r
64258         MOV      [EAX].fBoundsRect.Right, EDX                                   //\r
64259         MOV      EDX, [EAX].fBoundsRect.Top                                     //\r
64260         ADD      EDX, 40                                                        //\r
64261         MOV      [EAX].fBoundsRect.Bottom, EDX                                  //\r
64262         PUSH     EAX                                                            //\r
64263         MOV      EDX, offset[ WndProcGradient ]                                 //\r
64264         CALL     AttachProc                                                     //\r
64265         POP      EAX                                                            //\r
64266 end;                                                                            //\r
64267 {$ELSE ASM_VERSION} //Pascal                                                                //\r
64268 constructor TControl.CreateGradientPanel(AParent: PControl; AColor1,            //\r
64269   AColor2: TColor);                                                             //\r
64270 begin                                                                           //\r
64271   CreateLabel( AParent, '' );                                                   //\r
64272   AttachProc( WndProcGradient );                                                //\r
64273   fColor2 := AColor2;                                                           //\r
64274   fColor1 := AColor1;                                                           //\r
64275   with fBoundsRect do                                                           //\r
64276   begin                                                                         //\r
64277     Right := Left + 40;                                                         //\r
64278     Bottom := Top + 40;                                                         //\r
64279   end;                                                                          //\r
64280 end;                                                                            //\r
64281 {$ENDIF ASM_VERSION}                                                                        //\r
64282                                                                                 //\r
64283 //[constructor TControl.CreateGradientPanelEx]\r
64284 constructor TControl.CreateGradientPanelEx(AParent: PControl; AColor1,          //\r
64285   AColor2: TColor; AStyle: TGradientStyle; ALayout: TGradientLayout);           //\r
64286 begin                                                                           //\r
64287   CreateLabel( AParent, '' );                                                   //\r
64288   AttachProc( WndProcGradientEx );                                              //\r
64289   fColor2 := AColor2;                                                           //\r
64290   fColor1 := AColor1;                                                           //\r
64291   fGradientStyle := AStyle;                                                     //\r
64292   fGradientLayout := ALayout;                                                   //\r
64293   with fBoundsRect do                                                           //\r
64294   begin                                                                         //\r
64295     Right := Left + 40;                                                         //\r
64296     Bottom := Top + 40;                                                         //\r
64297   end;                                                                          //\r
64298 end;                                                                            //\r
64299                                                                                 //\r
64300 //[constructor TControl.CreateGroupbox]\r
64301 constructor TControl.CreateGroupbox(AParent: PControl;                          //\r
64302   const ACaption: String);                                                      //\r
64303 begin                                                                           //\r
64304   CreateButton( AParent, ACaption );                                            //\r
64305   with fBoundsRect do                                                           //\r
64306   begin                                                                         //\r
64307     Right := Left + 100;                                                        //\r
64308     Bottom := Top + 100;                                                        //\r
64309   end;                                                                          //\r
64310   fStyle := WS_VISIBLE or WS_CHILD or BS_GROUPBOX or WS_TABSTOP;                //\r
64311   fClientTop := 22;                                                             //\r
64312   fClientLeft := 2;                                                             //\r
64313   fClientBottom := 2;                                                           //\r
64314   fClientRight := 2;                                                            //\r
64315   fTabstop := False;                                                            //\r
64316   //AttachProc( WndProcGroupBox );                                                //\r
64317 end;                                                                            //\r
64318                                                                                 //\r
64319 //[constructor TControl.CreateCheckbox]\r
64320 constructor TControl.CreateCheckbox(AParent: PControl;                          //\r
64321   const ACaption: String);                                                      //\r
64322 begin                                                                           //\r
64323   CreateButton( AParent, ACaption );                                            //\r
64324   with fBoundsRect do                                                           //\r
64325   begin                                                                         //\r
64326     Right := Left + 72;                                                         //\r
64327   end;                                                                          //\r
64328   fStyle := WS_VISIBLE or WS_CHILD or                                           //\r
64329             BS_AUTOCHECKBOX or WS_TABSTOP;                                      //\r
64330 end;                                                                            //\r
64331                                                                                 //\r
64332 //[constructor TControl.CreateRadiobox]\r
64333 constructor TControl.CreateRadiobox(AParent: PControl;                          //\r
64334   const ACaption: String);                                                      //\r
64335 begin                                                                           //\r
64336   CreateCheckbox( AParent, ACaption );                                          //\r
64337   fStyle := WS_VISIBLE or WS_CHILD or                                           //\r
64338             BS_RADIOBUTTON or WS_TABSTOP or WS_GROUP;                           //\r
64339   fControlClick := ClickRadio;                                                  //\r
64340   if AParent <> nil then                                                        //\r
64341   begin                                                                         //\r
64342     AParent.fRadioLast := fMenu;                                                //\r
64343     if AParent.fRadio1st = 0 then                                               //\r
64344     begin                                                                       //\r
64345        AParent.fRadio1st := fMenu;                                              //\r
64346        SetRadioChecked;                                                         //\r
64347     end;                                                                        //\r
64348   end;                                                                          //\r
64349 end;                                                                            //\r
64350                                                                                 //\r
64351 //[constructor TControl.CreateEditbox]\r
64352 constructor TControl.CreateEditbox(AParent: PControl;                           //\r
64353   AOptions: TEditOptions);                                                      //\r
64354 var Flags: Integer;                                                             //\r
64355 begin                                                                           //\r
64356   Flags := MakeFlags( @AOptions, EditFlags );                                   //\r
64357   if not(eoMultiline in AOptions) then                                          //\r
64358      Flags := Flags and not(WS_HSCROLL or WS_VSCROLL);                          //\r
64359   CreateControl( AParent, 'EDIT', WS_VISIBLE or WS_CHILD or WS_TABSTOP          //\r
64360                          or WS_BORDER or Flags, True, @EditActions );           //\r
64361 //YS  fCursor := LoadCursor( 0, IDC_IBEAM );                                      // //YS\r
64362   with fBoundsRect do                                                           //\r
64363   begin                                                                         //\r
64364     Right := Left + 100;                                                        //\r
64365     Bottom := Top + 22;                                                         //\r
64366     if eoMultiline in AOptions then                                             //\r
64367     begin                                                                       //\r
64368        Right := Right + 100;                                                    //\r
64369        Bottom := Top + 200;                                                     //\r
64370     end;                                                                        //\r
64371   end;                                                                          //\r
64372   fColor := clWindow;                                                           //\r
64373   fLookTabKeys := [ tkTab, tkUpDown, tkPageUpPageDn ];                          //\r
64374   if eoMultiline in AOptions then                                               //\r
64375      fLookTabKeys := [ tkTab ];                                                 //\r
64376   if eoWantTab in AOptions then                                                 //\r
64377      fLookTabKeys := fLookTabKeys - [ tkTab ];                                  //\r
64378 end;                                                                            //\r
64379                                                                                 //\r
64380 //[constructor TControl.CreatePanel]\r
64381 constructor TControl.CreatePanel(AParent: PControl; AStyle: TEdgeStyle);        //\r
64382 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 ); //\r
64383 begin                                                                           //\r
64384   CreateControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or                   //\r
64385                          SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY, False,  //\r
64386                          @LabelActions );                                       //\r
64387   with fBoundsRect do                                                           //\r
64388   begin                                                                         //\r
64389     Right := Left + 100;                                                        //\r
64390     Bottom := Top + 100;                                                        //\r
64391   end;                                                                          //\r
64392   Style := Style or Edgestyles[ AStyle ];                                       //\r
64393   ExStyle := ExStyle or WS_EX_CONTROLPARENT;                                    //\r
64394 end;                                                                            //\r
64395                                                                                 //\r
64396 //[constructor TControl.CreateSplitter]\r
64397 constructor TControl.CreateSplitter(AParent: PControl; AMinSizePrev,            //\r
64398   AMinSizeNext: Integer; EdgeStyle: TEdgeStyle);                                //\r
64399 var PrevCtrl: PControl;                                                         //\r
64400     Sz0: Integer;                                                               //\r
64401 begin                                                                           //\r
64402   CreatePanel( AParent, EdgeStyle );                                            //\r
64403   fSplitMinSize1 := AMinSizePrev;                                               //\r
64404   fSplitMinSize2 := AMinSizeNext;                                               //\r
64405   Sz0 := 4;                                                                     //\r
64406   with fBoundsRect do                                                           //\r
64407   begin                                                                         //\r
64408     Right := Left + Sz0;                                                        //\r
64409     Bottom := Top + Sz0;                                                        //\r
64410   end;                                                                          //\r
64411   if AParent <> nil then                                                        //\r
64412   begin                                                                         //\r
64413     if AParent.fChildren.fCount > 1 then                                        //\r
64414     begin                                                                       //\r
64415       PrevCtrl := AParent.fChildren.fItems[ AParent.fChildren.fCount - 2 ];     //\r
64416       case PrevCtrl.FAlign of                                                   //\r
64417       caLeft, caRight:                                                          //\r
64418         begin                                                                   //\r
64419           fCursor := LoadCursor( 0, IDC_SIZEWE );                               //\r
64420         end;                                                                    //\r
64421       caTop, caBottom:                                                          //\r
64422         begin                                                                   //\r
64423           fCursor := LoadCursor( 0, IDC_SIZENS );                               //\r
64424         end;                                                                    //\r
64425       end;                                                                      //\r
64426       Align := PrevCtrl.FAlign;                                                 //\r
64427     end;                                                                        //\r
64428   end;                                                                          //\r
64429   AttachProc( WndProcSplitter );                                                //\r
64430 end;                                                                            //\r
64431                                                                                 //\r
64432 //[constructor TControl.CreateListbox]\r
64433 constructor TControl.CreateListbox(AParent: PControl;                           //\r
64434   AOptions: TListOptions);                                                      //\r
64435 var Flags: Integer;                                                             //\r
64436 begin                                                                           //\r
64437   Flags := MakeFlags( @AOptions, ListFlags );                                   //\r
64438   CreateControl( AParent, 'LISTBOX', WS_VISIBLE or WS_CHILD or WS_TABSTOP       //\r
64439                  or WS_BORDER or WS_VSCROLL                                     //\r
64440                  or LBS_NOTIFY or Flags, True, @ListActions );                  //\r
64441   with fBoundsRect do                                                           //\r
64442   begin                                                                         //\r
64443     Right := Right + 100;                                                       //\r
64444     Bottom := Top + 200;                                                        //\r
64445   end;                                                                          //\r
64446   fColor := clWindow;                                                           //\r
64447   fLookTabKeys := [ tkTab, tkLeftRight ];                                       //\r
64448 end;                                                                            //\r
64449                                                                                 //\r
64450 //[constructor TControl.CreateCombobox]\r
64451 constructor TControl.CreateCombobox(AParent: PControl;                          //\r
64452   AOptions: TComboOptions);                                                     //\r
64453 var Flags: Integer;                                                             //\r
64454 begin                                                                           //\r
64455   Flags := MakeFlags( @AOptions, ComboFlags );                                  //\r
64456   CreateControl( AParent, 'COMBOBOX',                                           //\r
64457                  WS_VISIBLE or WS_CHILD or WS_VSCROLL or                        //\r
64458                  CBS_DROPDOWN or CBS_HASSTRINGS or WS_TABSTOP or Flags,         //\r
64459                  True, @ComboActions );                                         //\r
64460   fCreateWndExt := CreateComboboxWnd;                                           //\r
64461   fDropDownProc := ComboboxDropDown;                                            //\r
64462   fClsStyle := fClsStyle or CS_DBLCLKS;                                         //\r
64463   with fBoundsRect do                                                           //\r
64464   begin                                                                         //\r
64465     Right := Left + 100;                                                        //\r
64466     Bottom := Top + 22;                                                         //\r
64467   end;                                                                          //\r
64468   fColor := clWindow;                                                           //\r
64469   fLookTabKeys := [ tkTab ];                                                    //\r
64470   if coReadOnly in AOptions then                                                //\r
64471     fLookTabKeys := [ tkTab, tkLeftRight ];                                     //\r
64472 end;                                                                            //\r
64473                                                                                 //\r
64474 //[constructor TControl.CreateCommonControl]\r
64475 constructor TControl.CreateCommonControl(AParent: PControl;                     //\r
64476   AClassName: PChar; AStyle: DWORD; ACtl3D: Boolean;                            //\r
64477   Actions: PCommandActions);                                                    //\r
64478 begin                                                                           //\r
64479   {*************} DoInitCommonControls( ICC_WIN95_CLASSES );                      //\r
64480   CreateControl( AParent, AClassName, AStyle, ACtl3D, Actions );                //\r
64481   fIsCommonControl := True;                                                     //\r
64482   if AParent <> nil then                                                        //\r
64483   begin                                                                         //\r
64484     AttachProc( WndProcParentResize );                                          //\r
64485     AParent.AttachProc( WndProcResize );                                        //\r
64486     AttachProc( WndProcCommonNotify );                                          //\r
64487     AParent.AttachProc( WndProcNotify );                                        //\r
64488   end;                                                                          //\r
64489 end;                                                                            //\r
64490                                                                                 //\r
64491 //[constructor TControl.CreateRichEdit1]\r
64492 constructor TControl.CreateRichEdit1(AParent: PControl;                         //\r
64493   AOptions: TEditOptions);                                                      //\r
64494 var Flags, I: Integer;                                                          //\r
64495 begin                                                                           //\r
64496   if FRichEditModule = 0 then                                                   //\r
64497   begin                                                                         //\r
64498     for I := 0 to 2 do                                                          //\r
64499     begin                                                                       //\r
64500       FRichEditModule := LoadLibrary( RichEditLibnames[ I ] );                  //\r
64501       if FRichEditModule > HINSTANCE_ERROR then break;                          //\r
64502       RichEditClass := 'RichEdit';                                              //\r
64503     end;                                                                        //\r
64504     if FRichEditModule <= HINSTANCE_ERROR then                                  //\r
64505       FRichEditModule := 0;                                                     //\r
64506   end;                                                                          //\r
64507   Flags := MakeFlags( @AOptions, RichEditFlags );                               //\r
64508   CreateCommonControl( AParent, RichEditClass, WS_VISIBLE or WS_CHILD           //\r
64509                        or WS_TABSTOP or WS_BORDER or ES_MULTILINE or Flags,     //\r
64510                        True, @RichEditActions );                                //\r
64511                                                                                 //\r
64512   AttachProc( WndProcRichEditNotify );                                          //\r
64513   fDoubleBuffered := False;                                                     //\r
64514   fCannotDoubleBuf := True;                                                     //\r
64515   with fBoundsRect do                                                           //\r
64516   begin                                                                         //\r
64517     Right := Right + 100;                                                       //\r
64518     Bottom := Top + 200;                                                        //\r
64519   end;                                                                          //\r
64520   fColor := clWindow;                                                           //\r
64521   fLookTabKeys := [ tkTab ];                                                    //\r
64522   if eoWantTab in AOptions then                                                 //\r
64523      fLookTabKeys := [ ];                                                       //\r
64524   Perform( EM_SETEVENTMASK, 0,                                                  //\r
64525     ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or                         //\r
64526     ENM_PROTECTED or $04000000 {ENM_LINK} );                                    //\r
64527   Perform( EM_SETBKGNDCOLOR, 0, Color2RGB(fColor));                             //\r
64528 end;                                                                            //\r
64529                                                                                 //\r
64530                                                                                 //\r
64531 //[constructor TControl.CreateRichEdit]\r
64532 constructor TControl.CreateRichEdit(AParent: PControl;                          //\r
64533   AOptions: TEditOptions);                                                      //\r
64534 var OldRichEditClass, OldRichEditLib: PChar;                                    //\r
64535 begin                                                                           //\r
64536   if OleInit then                                                               //\r
64537   begin                                                                         //\r
64538     OldRichEditClass := RichEditClass;                                          //\r
64539     RichEditClass := 'RichEdit20A';                                             //\r
64540     OldRichEditLib := RichEditLib;                                              //\r
64541     RichEditLib := 'RICHED20.DLL';                                              //\r
64542     CreateRichEdit1( AParent, AOptions );                                       //\r
64543     fCharFmtDeltaSz := 24;                                                      //\r
64544     // sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat );                 //\r
64545     fParaFmtDeltaSz := sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat ); //\r
64546     RichEditClass := OldRichEditClass;                                          //\r
64547     RichEditLib := OldRichEditLib;                                              //\r
64548   end                                                                           //\r
64549      else                                                                       //\r
64550     CreateRichEdit1( AParent, AOptions );                                       //\r
64551 end;                                                                            //\r
64552                                                                                 //\r
64553 //[constructor TControl.CreateProgressbar]\r
64554 constructor TControl.CreateProgressbar(AParent: PControl);                      //\r
64555 const ProgressBarFlags: array[ TProgressbarOption ] of Integer =                //\r
64556       (PBS_VERTICAL, PBS_SMOOTH );                                              //\r
64557 begin                                                                           //\r
64558   CreateCommonControl( AParent, PROGRESS_CLASS,                                 //\r
64559             WS_CHILD or WS_VISIBLE, True, nil );                                //\r
64560   with fBoundsRect do                                                           //\r
64561   begin                                                                         //\r
64562     Right := Left + 300;                                                        //\r
64563     Bottom := Top + 20;                                                         //\r
64564   end;                                                                          //\r
64565   fMenu := 0;                                                                   //\r
64566   fTextColor := clHighlight;                                                    //\r
64567 end;                                                                            //\r
64568                                                                                 //\r
64569 //[constructor TControl.CreateProgressbarEx]\r
64570 constructor TControl.CreateProgressbarEx(AParent: PControl;                     //\r
64571   AOptions: TProgressbarOptions);                                               //\r
64572 const ProgressBarFlags: array[ TProgressbarOption ] of Integer =                //\r
64573       (PBS_VERTICAL, PBS_SMOOTH );                                              //\r
64574 begin                                                                           //\r
64575   CreateProgressbar( AParent );                                                 //\r
64576   fStyle := fStyle or DWORD( MakeFlags( @AOptions, ProgressBarFlags ) );        //\r
64577 end;                                                                            //\r
64578                                                                                 //\r
64579 //[constructor TControl.CreateListView]\r
64580 constructor TControl.CreateListView(AParent: PControl;                          //\r
64581   AStyle: TListViewStyle; AOptions: TListViewOptions; AImageListSmall,          //\r
64582   AImageListNormal, AImageListState: PImageList);                               //\r
64583 begin                                                                           //\r
64584   CreateCommonControl( AParent, WC_LISTVIEW, ListViewStyles[ AStyle ] or        //\r
64585                  LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP,   //\r
64586                  True, @ListViewActions );                                      //\r
64587   fLVOptions := AOptions;                                                       //\r
64588   fLVStyle := AStyle;                                                           //\r
64589   fCreateWndExt := ApplyImageLists2ListView;                                    //\r
64590   with fBoundsRect do                                                           //\r
64591   begin                                                                         //\r
64592     Right := Left + 200;                                                        //\r
64593     Bottom := Top + 150;                                                        //\r
64594   end;                                                                          //\r
64595   ImageListSmall := AImageListSmall;                                            //\r
64596   ImageListNormal := AImageListNormal;                                          //\r
64597   ImageListState := AImageListState;                                            //\r
64598   fLVTextBkColor := clWindow;                                                   //\r
64599   fLookTabKeys := [ tkTab ];                                                    //\r
64600 end;                                                                            //\r
64601                                                                                 //\r
64602 //[constructor TControl.CreateTreeView]\r
64603 constructor TControl.CreateTreeView(AParent: PControl;                          //\r
64604   AOptions: TTreeViewOptions; AImgListNormal, AImgListState: PImageList);       //\r
64605 var Flags: Integer;                                                             //\r
64606 begin                                                                           //\r
64607   Flags := MakeFlags( @AOptions, TreeViewFlags );                               //\r
64608   CreateCommonControl( AParent, WC_TREEVIEW, Flags or WS_VISIBLE or             //\r
64609             WS_CHILD or WS_TABSTOP, True, @TreeViewActions );                   //\r
64610   fCreateWndExt := ApplyImageLists2Control;                                     //\r
64611   fColor := clWindow;                                                           //\r
64612   AttachProc( WndProcTreeView );                                                //\r
64613   with fBoundsRect do                                                           //\r
64614   begin                                                                         //\r
64615     Right := Left + 150;                                                        //\r
64616     Bottom := Top + 200;                                                        //\r
64617   end;                                                                          //\r
64618   ImageListNormal := AImgListNormal;                                            //\r
64619   ImageListState := AImgListState;                                              //\r
64620   fLookTabKeys := [ tkTab ];                                                    //\r
64621 end;                                                                            //\r
64622                                                                                 //\r
64623 //[constructor TControl.CreateTabControl]\r
64624 constructor TControl.CreateTabControl(AParent: PControl; ATabs: array of String;//\r
64625          AOptions: TTabControlOptions;                                          //\r
64626          AImgList: PImageList; AImgList1stIdx: Integer);                        //\r
64627 var I, II : Integer;                                                            //\r
64628     Flags: Integer;                                                             //\r
64629 begin                                                                           //\r
64630   Flags := MakeFlags( @AOptions, TabControlFlags );                             //\r
64631   if tcoFocusTabs in AOptions then                                              //\r
64632     Flags := Flags or (WS_TABSTOP or TCS_FOCUSONBUTTONDOWN);                    //\r
64633   CreateCommonControl( AParent, WC_TABCONTROL,                                  //\r
64634             Flags or (WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or         //\r
64635             WS_VISIBLE), True, @TabControlActions );                            //\r
64636   if not( tcoBorder in AOptions ) then                                           //\r
64637     fExStyle := fExStyle and not WS_EX_CLIENTEDGE;                              //\r
64638   AttachProc( WndProcTabControl );                                              //\r
64639   with fBoundsRect do                                                           //\r
64640   begin                                                                         //\r
64641     Right := Left + 100;                                                        //\r
64642     Bottom := Top + 100;                                                        //\r
64643   end;                                                                          //\r
64644   if AImgList <> nil then                                                       //\r
64645     Perform( TCM_SETIMAGELIST, 0, AImgList.Handle );                            //\r
64646   II := AImgList1stIdx;                                                         //\r
64647   for I := 0 to High( ATabs ) do                                                //\r
64648   begin                                                                         //\r
64649     TC_Insert( I, ATabs[ I ], II );                                             //\r
64650     Inc( II );                                                                  //\r
64651   end;                                                                          //\r
64652   fLookTabKeys := [ tkTab ];                                                    //\r
64653 end;                                                                            //\r
64654                                                                                 //\r
64655 //[constructor TControl.CreateToolbar]\r
64656 constructor TControl.CreateToolbar(AParent: PControl;                           //\r
64657   AAlign: TControlAlign; AOptions: TToolbarOptions; ABitmap: HBitmap;           //\r
64658   AButtons: array of PChar; ABtnImgIdxArray: array of Integer);                 //\r
64659 var Flags: DWORD;                                                               //\r
64660 begin                                                                           //\r
64661   if not( tboTextBottom in AOptions ) then                                      //\r
64662     AOptions := AOptions + [ tboTextRight ];                                    //\r
64663   if tboTextRight in AOptions then                                              //\r
64664     AOptions := AOptions - [ tboTextBottom ];                                   //\r
64665   Flags := MakeFlags( @AOptions, ToolbarOptions );                              //\r
64666   CreateCommonControl( AParent, TOOLBARCLASSNAME, ToolbarAligns[ Align ] or     //\r
64667                        WS_CHILD or WS_VISIBLE {or WS_TABSTOP}                   //\r
64668                        or TBSTYLE_TOOLTIPS or Flags,                            //\r
64669                        (not (Align in [caNone])) and                            //\r
64670                         not (tboNoDivider in AOptions),  nil );                 //\r
64671   fCommandActions.aClear := ClearToolbar;                                       //\r
64672   fCommandActions.aGetCount := TB_BUTTONCOUNT;                                  //\r
64673   with fBoundsRect do                                                           //\r
64674   begin                                                                         //\r
64675     if AAlign in [ caNone ] then                                                //\r
64676     begin                                                                       //\r
64677       Bottom := Top + 26;                                                       //\r
64678       Right := Left + 1000;                                                     //\r
64679     end                                                                         //\r
64680        else                                                                     //\r
64681     begin                                                                       //\r
64682       Left := 0; Right := 0;                                                    //\r
64683       Top := 0; Bottom := 0;                                                    //\r
64684     end;                                                                        //\r
64685   end;                                                                          //\r
64686   Perform(TB_SETEXTENDEDSTYLE, 0, Perform(TB_GETEXTENDEDSTYLE, 0, 0) or         //\r
64687       TBSTYLE_EX_DRAWDDARROWS);                                                 //\r
64688                                                                                 //\r
64689   AttachProc( WndProcToolbarCtrl );                                             //\r
64690   Perform( TB_BUTTONSTRUCTSIZE, Sizeof( TTBButton ), 0 );                       //\r
64691   Perform( TB_SETINDENT, fMargin, 0 );                                          //\r
64692   with fBoundsRect do                                                           //\r
64693   begin                                                                         //\r
64694     if AAlign in [ caLeft, caRight ] then                                       //\r
64695       Right := Left + 24                                                        //\r
64696     else if not (AAlign in [caNone]) then                                       //\r
64697       Bottom := Top + 22;                                                       //\r
64698   end;                                                                          //\r
64699   if ABitmap <> 0 then                                                          //\r
64700     TBAddBitmap( ABitmap );                                                     //\r
64701   TBAddButtons( AButtons, ABtnImgIdxArray );                                    //\r
64702   Perform( WM_SIZE, 0, 0 );                                                     //\r
64703 end;                                                                            //\r
64704                                                                                 //\r
64705 //[constructor TImageList.CreateImageList]\r
64706 constructor TImageList.CreateImageList(POwner: Pointer);                        //\r
64707 var AOwner: PControl;                                                           //\r
64708 begin                                                                           //\r
64709   {*************} DoInitCommonControls( ICC_WIN95_CLASSES );                    //\r
64710   Create;                                                                       //\r
64711   FAllocBy := 1;                                                                //\r
64712   FMasked := True;                                                              //\r
64713   if POwner = nil then exit;                                                    //\r
64714   FBkColor := TColor( CLR_NONE );\r
64715   //ImageList_SetBkColor( FHandle, CLR_NONE );\r
64716                                                                                 //\r
64717   AOwner := POwner;                                                             //\r
64718   FControl := AOwner;                                                           //\r
64719   fNext := PImageList( AOwner.fImageList );                                     //\r
64720   if AOwner.fImageList <> nil then                                              //\r
64721      PImageList( AOwner.fImageList ).fPrev := @Self;                            //\r
64722   AOwner.fImageList := @Self;                                                   //\r
64723 end;                                                                            //\r
64724                                                                                 //\r
64725 //[constructor TThread.ThreadCreate]\r
64726 constructor TThread.ThreadCreate;                                               //\r
64727 begin                                                                           //\r
64728   IsMultiThread := True;                                                        //\r
64729   Create;                                                                       //\r
64730   FSuspended := True;                                                           //\r
64731   FHandle := CreateThread( nil, // no security                                  //\r
64732                           0,   // the same stack size                           //\r
64733                           @ThreadFunc, // thread entry point                    //\r
64734                           @Self,      // parameter to pass to ThreadFunc        //\r
64735                           CREATE_SUSPENDED,   // always SUSPENDED               //\r
64736                           FThreadID ); // receive thread ID                     //\r
64737 end;                                                                            //\r
64738                                                                                 //\r
64739 //[constructor TThread.ThreadCreateEx]\r
64740 constructor TThread.ThreadCreateEx( const Proc: TOnThreadExecute );             //\r
64741 begin                                                                           //\r
64742   ThreadCreate;                                                                 //\r
64743   OnExecute := Proc;                                                            //\r
64744   Resume;                                                                       //\r
64745 end;                                                                            //\r
64746                                                                                 //\r
64747 {$ENDIF USE_CONSTRUCTORS} //****************************************************//\r
64748 {+}\r
64750 { TCABFile }\r
64752 //[function OpenCABFile]\r
64753 function OpenCABFile( const APaths: array of String ): PCABFile;\r
64754 var I: Integer;\r
64755 begin\r
64756   {-}\r
64757   New( Result, Create );\r
64758   {+}{++}(*Result := PCABFile.Create;*){--}\r
64759   Result.FSetupapi := LoadLibrary( 'setupapi.dll' );\r
64760   Result.FNames := NewStrList;\r
64761   Result.FPaths := NewStrList;\r
64762   for I := 0 to High( APaths ) do\r
64763     Result.FPaths.Add( APaths[ I ] );\r
64764 end;\r
64766 //[destructor TCABFile.Destroy]\r
64767 destructor TCABFile.Destroy;\r
64768 begin\r
64769   FNames.Free;\r
64770   FPaths.Free;\r
64771   FTargetPath := '';\r
64772   if FSetupapi <> 0 then\r
64773     FreeLibrary( FSetupapi );\r
64774   inherited;\r
64775 end;\r
64777 const\r
64778   SPFILENOTIFY_FILEINCABINET  = $11;\r
64779   SPFILENOTIFY_NEEDNEWCABINET = $12;\r
64781 type\r
64782   PSP_FILE_CALLBACK = function( Context: Pointer; Notification, Param1, Param2: DWORD ): DWORD;\r
64783   stdcall;\r
64785   TSetupIterateCabinet = function ( CabinetFile: PChar; Reserved: DWORD;\r
64786          MsgHandler: PSP_FILE_CALLBACK; Context: Pointer ): Boolean; stdcall;\r
64787          //external 'setupapi.dll' name 'SetupIterateCabinetA';\r
64789   TSetupPromptDisk = function (\r
64790     hwndParent: HWND;   // parent window of the dialog box\r
64791     DialogTitle: PChar; // optional, title of the dialog box\r
64792     DiskName: PChar;    // optional, name of disk to insert\r
64793     PathToSource: PChar;// optional, expected source path\r
64794     FileSought: PChar;  // name of file needed\r
64795     TagFile: PChar;     // optional, source media tag file\r
64796     DiskPromptStyle: DWORD;     // specifies dialog box behavior\r
64797     PathBuffer: PChar;  // receives the source location\r
64798     PathBufferSize: DWORD;      // size of the supplied buffer\r
64799     PathRequiredSize: PDWORD    // optional, buffer size needed\r
64800    ): DWORD; stdcall;\r
64801    //external 'setupapi.dll' name 'SetupPromptForDiskA';\r
64803 type\r
64804   TCabinetInfo = packed record\r
64805     CabinetPath: PChar;\r
64806     CabinetFile: PChar;\r
64807     DiskName: PChar;\r
64808     SetId: WORD;\r
64809     CabinetNumber: WORD;\r
64810   end;\r
64811   PCabinetInfo = ^TCabinetInfo;\r
64813   TFileInCabinetInfo = packed record\r
64814     NameInCabinet: PChar;\r
64815     FileSize: DWORD;\r
64816     Win32Error: DWORD;\r
64817     DosDate: WORD;\r
64818     DosTime: WORD;\r
64819     DosAttribs: WORD;\r
64820     FullTargetName: array[0..MAX_PATH-1] of Char;\r
64821   end;\r
64822   PFileInCabinetInfo = ^TFileInCabinetInfo;\r
64824 //[function CABCallback]\r
64825 function CABCallback( Context: Pointer; Notification, Param1, Param2: DWORD ): DWORD;\r
64826 stdcall;\r
64827 var CAB: PCABFile;\r
64828     CABPath, OldPath: String;\r
64829     CABInfo: PCabinetInfo;\r
64830     CABFileInfo: PFileInCabinetInfo;\r
64831     hr: Integer;\r
64832     SetupPromptProc: TSetupPromptDisk;\r
64833 begin\r
64834   Result := 0;\r
64835   CAB := Context;\r
64836   case Notification of\r
64837   SPFILENOTIFY_NEEDNEWCABINET:\r
64838     begin\r
64839       OldPath := CAB.FPaths.Items[ CAB.FCurCAB ];\r
64840       Inc( CAB.FCurCAB );\r
64841       if CAB.FCurCAB = CAB.FPaths.Count then\r
64842         CAB.FPaths.Add( '?' );\r
64843       CABPath := CAB.FPaths.Items[ CAB.FCurCAB ];\r
64844       if CABPath = '?' then\r
64845       begin\r
64846         if Assigned( CAB.FOnNextCAB ) then\r
64847           CAB.FPaths.Items[CAB.FCurCAB ] := CAB.FOnNextCAB( CAB );\r
64848         CABPath := CAB.FPaths.Items[ CAB.FCurCAB ];\r
64849         if CABPath = '?' then\r
64850         begin\r
64851           SetLength( CABPath, MAX_PATH );\r
64852           CABInfo := Pointer( Param1 );\r
64853           if CAB.FSetupapi <> 0 then\r
64854             SetupPromptProc := GetProcAddress( CAB.FSetupapi, 'SetupPromptForDiskA' )\r
64855           else\r
64856             SetupPromptProc := nil;\r
64857           if Assigned( SetupPromptProc ) then\r
64858           begin\r
64859             hr := SetupPromptProc( 0, nil, nil, PChar( ExtractFilePath( OldPath ) ),\r
64860                  CABInfo.CabinetFile, nil, 2 {IDF_NOSKIP}, @CabPath[ 1 ], MAX_PATH, nil );\r
64861             case hr of\r
64862             0: // success\r
64863               begin\r
64864                 StrCopy( PChar( Param2 ), PChar( CABPath ) );\r
64865                 Result := 0;\r
64866               end;\r
64867             2: // skip file\r
64868               Result := 0;\r
64869             else // cancel\r
64870               Result := ERROR_FILE_NOT_FOUND;\r
64871             end;\r
64872           end;\r
64873         end\r
64874           else\r
64875         begin\r
64876           StrCopy( PChar( Param2 ), PChar( CABPath ) );\r
64877           Result := 0;\r
64878         end;\r
64879       end;\r
64880     end;\r
64881   SPFILENOTIFY_FILEINCABINET:\r
64882     begin\r
64883       CABFileInfo := Pointer( Param1 );\r
64884       if CAB.FGettingNames then\r
64885       begin\r
64886         CAB.FNames.Add( CABFileInfo.NameInCabinet );\r
64887         Result := 2; // FILEOP_SKIP\r
64888       end\r
64889         else\r
64890       begin\r
64891         CABPath := CABFileInfo.NameInCabinet;\r
64892         if Assigned( CAB.FOnFile ) then\r
64893         begin\r
64894           if CAB.FOnFile( CAB, CABPath ) then\r
64895           begin\r
64896             if ExtractFilePath( CABPath ) = '' then\r
64897             if CAB.FTargetPath <> '' then\r
64898               CABPath := CAB.TargetPath + CABPath;\r
64899             StrCopy( @CABFileInfo.FullTargetName[ 0 ], PChar( CABPath ) );\r
64900             Result := 1; // FILEOP_DOIT\r
64901           end\r
64902           else\r
64903             Result := 2\r
64904         end\r
64905         else\r
64906         begin\r
64907           if CAB.FTargetPath <> '' then\r
64908             StrCopy( @CABFileInfo.FullTargetName[ 0 ], PChar( CAB.TargetPath + CABPath ) );\r
64909           Result := 1;\r
64910         end;\r
64911       end;\r
64912     end;\r
64913   end;\r
64914 end;\r
64916 //[function TCABFile.Execute]\r
64917 function TCABFile.Execute: Boolean;\r
64918 var SetupIterateProc: TSetupIterateCabinet;\r
64919 begin\r
64920   FCurCAB := 0;\r
64921   Result := FALSE;\r
64922   if FSetupapi = 0 then Exit;\r
64923   SetupIterateProc := GetProcAddress( FSetupapi, 'SetupIterateCabinetA' );\r
64924   if not Assigned( SetupIterateProc ) then Exit;\r
64925   Result := SetupIterateProc( PChar( FPaths.Items[ 0 ] ), 0, CABCallback, @Self );\r
64926 end;\r
64928 //[function TCABFile.GetCount]\r
64929 function TCABFile.GetCount: Integer;\r
64930 begin\r
64931   GetNames( 0 );\r
64932   Result := FNames.Count;\r
64933 end;\r
64935 //[function TCABFile.GetNames]\r
64936 function TCABFile.GetNames(Idx: Integer): String;\r
64937 begin\r
64938   if FNames.Count = 0 then\r
64939   begin\r
64940     FGettingNames := TRUE;\r
64941     Execute;\r
64942     FGettingNames := FALSE;\r
64943   end;\r
64944   Result := '';\r
64945   if Idx < FNames.Count then\r
64946     Result := FNames.Items[ Idx ];\r
64947 end;\r
64949 //[function TCABFile.GetPaths]\r
64950 function TCABFile.GetPaths(Idx: Integer): String;\r
64951 begin\r
64952   Result := FPaths.Items[ Idx ];\r
64953 end;\r
64955 //[function TCABFile.GetTargetPath]\r
64956 function TCABFile.GetTargetPath: String;\r
64957 begin\r
64958   Result := FTargetPath;\r
64959   if Result <> '' then\r
64960   if Result[ Length( Result ) ] <> '\' then\r
64961     Result := Result + '\';\r
64962 end;\r
64964 //[procedure InvalidateExW]\r
64965 procedure InvalidateExW( Wnd: HWnd );\r
64966 begin\r
64967   InvalidateRect( Wnd, nil, TRUE );\r
64968   Wnd := GetWindow( Wnd, GW_CHILD );\r
64969   while Wnd <> 0 do\r
64970   begin\r
64971     InvalidateExW( Wnd );\r
64972     Wnd := GetWindow( Wnd, GW_HWNDNEXT );\r
64973   end;\r
64974 end;\r
64976 //[procedure TControl.InvalidateEx]\r
64977 procedure TControl.InvalidateEx;\r
64978 begin\r
64979   if fHandle = 0 then Exit;\r
64980   InvalidateExW( fHandle );\r
64981 end;\r
64983 //[procedure InvalidateNCW]\r
64984 procedure InvalidateNCW( Wnd: HWnd; Recursive: Boolean );\r
64985 begin\r
64986   SendMessage( Wnd, WM_NCPAINT, 1, 0 );\r
64987   if not Recursive then Exit;\r
64988   Wnd := GetWindow( Wnd, GW_CHILD );\r
64989   while Wnd <> 0 do\r
64990   begin\r
64991     InvalidateNCW( Wnd, Recursive );\r
64992     Wnd := GetWindow( Wnd, GW_HWNDNEXT );\r
64993   end;\r
64994 end;\r
64996 //[procedure TControl.InvalidateNC]\r
64997 procedure TControl.InvalidateNC(Recursive: Boolean);\r
64998 begin\r
64999   if fHandle = 0 then Exit;\r
65000   InvalidateNCW( fHandle, Recursive );\r
65001 end;\r
65003 //[procedure TControl.SetClientMargin]\r
65004 procedure TControl.SetClientMargin(const Index, Value: Integer);\r
65005 begin\r
65006   case Index of\r
65007   1: fClientTop := Value;\r
65008   2: fClientBottom := Value;\r
65009   3: fClientLeft := Value;\r
65010   4: fClientRight := Value;\r
65011   end;\r
65012   Global_Align( @Self );\r
65013 end;\r
65015 {$IFDEF F_P}\r
65016 //[function TControl.GetClientMargin]\r
65017 function TControl.GetClientMargin(const Index: Integer): Integer;\r
65018 begin\r
65019   CASE Index OF\r
65020   1: Result := fClientTop;\r
65021   2: Result := fClientBottom;\r
65022   3: Result := fClientLeft;\r
65023   4: Result := fClientRight;\r
65024   END;\r
65025 end;\r
65026 {$ENDIF F_P}\r
65028 { TBits }\r
65030 //[function NewBits]\r
65031 function NewBits: PBits;\r
65032 begin\r
65033   {-}\r
65034   new( Result, Create );\r
65035   {+}{++}(*Result := PBits.Create;*){--}\r
65036   Result.fList := NewList;\r
65037   //Result.fList.fAddBy := 1;\r
65038 end;\r
65040 //[procedure TBits.AssignBits]\r
65041 procedure TBits.AssignBits(ToIdx: Integer; FromBits: PBits; FromIdx,\r
65042   N: Integer);\r
65043 var i: Integer;\r
65044     NewCount: Integer;\r
65045 begin\r
65046   if FromIdx >= FromBits.Count then Exit;\r
65047   if FromIdx + N > FromBits.Count then\r
65048     N := FromBits.Count - FromIdx;\r
65049   Capacity := (ToIdx + N + 8) div 8;\r
65050   NewCount := Max( Count, ToIdx + N - 1 );\r
65051   fCount := Max( NewCount, fCount );\r
65052   fList.fCount := (Capacity + 3) div 4;\r
65053   while ToIdx and $1F <> 0 do\r
65054   begin\r
65055     Bits[ ToIdx ] := FromBits.Bits[ FromIdx ];\r
65056     Inc( ToIdx );\r
65057     Inc( FromIdx );\r
65058     Dec( N );\r
65059     if N = 0 then Exit;\r
65060   end;\r
65061   Move( PByte( Integer( FromBits.fList.fItems ) + (FromIdx + 31) div 32 )^,\r
65062         PByte( Integer( fList.fItems ) + ToIdx div 32 )^, (N + 31) div 32 );\r
65063   FromIdx := FromIdx and $1F;\r
65064   if FromIdx <> 0 then\r
65065   begin // shift data by (Idx and $1F) bits right\r
65066     for i := ToIdx div 32 to fList.Count-2 do\r
65067       fList.Items[ i ] := Pointer(\r
65068         (DWORD( fList.Items[ i ] ) shr FromIdx) or\r
65069         (DWORD( fList.Items[ i+1 ] ) shl (32 - FromIdx))\r
65070         );\r
65071     fList.Items[ fList.Count-1 ] := Pointer(\r
65072       DWORD( fList.Items[ fList.Count-1 ] ) shr FromIdx\r
65073       );\r
65074   end;\r
65075 end;\r
65077 //[function TBits.Copy]\r
65078 procedure TBits.Clear;\r
65079 begin\r
65080   fList.Clear;\r
65081 end;\r
65083 function TBits.Copy(From, BitsCount: Integer): PBits;\r
65084 var Shift, N: Integer;\r
65085     FirstItemPtr: Pointer;\r
65086 begin\r
65087   Result := NewBits;\r
65088   if BitsCount = 0 then Exit;\r
65089   Result.Capacity := BitsCount + 32;\r
65090   Result.fCount := BitsCount;\r
65091   Move( fList.fItems[ From shr 5 ], Result.fList.fItems[ 0 ], (Count + 31) div 32 );\r
65092   Shift := From and $1F;\r
65093   if Shift <> 1 then\r
65094   begin\r
65095     N := (BitsCount + 31) div 32;\r
65096     FirstItemPtr := @ Result.fList.fItems[ N - 1 ];\r
65097     asm\r
65098           PUSH  ESI\r
65099           PUSH  EDI\r
65100           MOV   ESI, FirstItemPtr\r
65101           MOV   EDI, ESI\r
65102           STD\r
65103           MOV   ECX, N\r
65104           XOR   EAX, EAX\r
65105           CDQ\r
65106     @@1:\r
65107           PUSH  ECX\r
65108           LODSD\r
65109           MOV   ECX, Shift\r
65110           SHRD  EAX, EDX, CL\r
65111           STOSD\r
65112           SUB   ECX, 32\r
65113           NEG   ECX\r
65114           SHR   EDX, CL\r
65115           POP   ECX\r
65117           LOOP  @@1\r
65119           CLD\r
65120           POP   EDI\r
65121           POP   ESI\r
65122     end {$IFDEF F_P} ['EAX','EDX','ECX'] {$ENDIF};\r
65123   end;\r
65124 end;\r
65126 //[destructor TBits.Destroy]\r
65127 destructor TBits.Destroy;\r
65128 begin\r
65129   fList.Free;\r
65130   inherited;\r
65131 end;\r
65133 //[function TBits.GetBit]\r
65134 function TBits.GetBit(Idx: Integer): Boolean;\r
65135 begin\r
65136   if Idx >= Count then Result := FALSE else\r
65137   Result := ( ( DWORD( fList.fItems[ Idx shr 5 ] ) shr (Idx and $1F)) and 1 ) <> 0;\r
65138 end;\r
65140 //[function TBits.GetCapacity]\r
65141 function TBits.GetCapacity: Integer;\r
65142 begin\r
65143   Result := fList.Capacity * 32;\r
65144 end;\r
65146 //[function TBits.GetSize]\r
65147 function TBits.GetSize: Integer;\r
65148 begin\r
65149   Result := (fList.fCount + 3) div 4;\r
65150 end;\r
65152 {$IFDEF ASM_noVERSION}\r
65153 //[function TBits.IndexOf]\r
65154 function TBits.IndexOf(Value: Boolean): Integer;\r
65155 asm     //cmd    //opd\r
65156         PUSH     EDI\r
65157         MOV      EDI, [EAX].fList\r
65158         MOV      ECX, [EDI].TList.fCount\r
65159 @@ret_1:\r
65160         OR       EAX, -1\r
65161         JECXZ    @@ret_EAX\r
65162         MOV      EDI, [EDI].TList.fItems\r
65163         TEST     DL, DL\r
65164         MOV      EDX, EDI\r
65165         JE       @@of_false\r
65166         INC      EAX\r
65167         REPZ     SCASD\r
65168         JE       @@ret_1\r
65169         MOV      EAX, [EDI-4]\r
65170         NOT      EAX\r
65171         JMP      @@calc_offset\r
65172         BSF      EAX, EAX\r
65173         SUB      EDI, EDX\r
65174         SHR      EDI, 2\r
65175         ADD      EAX, EDI\r
65176         JMP      @@ret_EAX\r
65177 @@of_false:\r
65178         REPE     SCASD\r
65179         JE       @@ret_1\r
65180         MOV      EAX, [EDI-4]\r
65181 @@calc_offset:\r
65182         BSF      EAX, EAX\r
65183         DEC      EAX\r
65184         SUB      EDI, 4\r
65185         SUB      EDI, EDX\r
65186         SHL      EDI, 3\r
65187         ADD      EAX, EDI\r
65188 @@ret_EAX:\r
65189         POP      EDI\r
65190 end;\r
65191 {$ELSE ASM_VERSION} //Pascal\r
65192 function TBits.IndexOf(Value: Boolean): Integer;\r
65193 var I: Integer;\r
65194     D: DWORD;\r
65195 begin\r
65196   Result := -1;\r
65197   if Value then\r
65198   begin\r
65199     for I := 0 to fList.Count-1 do\r
65200     begin\r
65201       D := DWORD( fList.fItems[ I ] );\r
65202       if D <> 0 then\r
65203       begin\r
65204         asm\r
65205           MOV  EAX, D\r
65206           BSF  EAX, EAX\r
65207           MOV  D, EAX\r
65208         end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};\r
65209         Result := I * 32 + Integer( D );\r
65210         break;\r
65211       end;\r
65212     end;\r
65213   end\r
65214     else\r
65215   begin\r
65216     for I := 0 to fList.fCount-1 do\r
65217     begin\r
65218       D := DWORD( fList.fItems[ I ] );\r
65219       if D <> $FFFFFFFF then\r
65220       begin\r
65221         asm\r
65222           MOV  EAX, D\r
65223           NOT  EAX\r
65224           BSF  EAX, EAX\r
65225           MOV  D, EAX\r
65226         end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};\r
65227         Result := I * 32 + Integer( D );\r
65228         break;\r
65229       end;\r
65230     end;\r
65231   end;\r
65232 end;\r
65233 {$ENDIF ASM_VERSION}\r
65235 //[function TBits.LoadFromStream]\r
65236 function TBits.LoadFromStream(strm: PStream): Integer;\r
65237 var\r
65238  i: Integer;\r
65239 begin\r
65240  Result := strm.Read( i, 4 );\r
65241  if Result < 4 then Exit;\r
65242  \r
65243  bits[ i]:= false; //by miek\r
65244  fcount:= i;\r
65246  i := (i + 7) div 8;\r
65247  Inc( Result, strm.Read( fList.fItems^, i ) );\r
65248 end;\r
65250 //[function TBits.OpenBit]\r
65251 function TBits.OpenBit: Integer;\r
65252 begin\r
65253   Result := IndexOf( FALSE );\r
65254   if Result < 0 then Result := Count;\r
65255 end;\r
65257 //[function TBits.Range]\r
65258 function TBits.Range(Idx, N: Integer): PBits;\r
65259 begin\r
65260   Result := NewBits;\r
65261   Result.AssignBits( 0, @ Self, Idx, N );\r
65262 end;\r
65264 //[function TBits.SaveToStream]\r
65265 function TBits.SaveToStream(strm: PStream): Integer;\r
65266 begin\r
65267   Result := strm.Write( fCount, 4 );\r
65268   if fCount = 0 then Exit;\r
65269   Inc( Result, strm.Write( fList.fItems^, (fCount + 7) div 8 ) );\r
65270 end;\r
65272 //[procedure TBits.SetBit]\r
65273 procedure TBits.SetBit(Idx: Integer; const Value: Boolean);\r
65274 var Msk: DWORD;\r
65275 begin\r
65276   if Idx >= Capacity then\r
65277     Capacity := Idx + 1;\r
65278   Msk := 1 shl (Idx and $1F);\r
65279   if Value then\r
65280     fList.fItems[ Idx shr 5 ] := Pointer(\r
65281                   DWORD(fList.fItems[ Idx shr 5 ]) or Msk)\r
65282   else\r
65283     fList.fItems[ Idx shr 5 ] := Pointer(\r
65284                   DWORD(fList.fItems[ Idx shr 5 ]) and not Msk);\r
65285   if Idx >= fCount then\r
65286     fCount := Idx + 1;\r
65287 end;\r
65289 //[procedure TBits.SetCapacity]\r
65290 procedure TBits.SetCapacity(const Value: Integer);\r
65291 var OldCap: Integer;\r
65292 begin\r
65293   OldCap := fList.Capacity;\r
65294   fList.Capacity := (Value + 31) div 32;\r
65295   if OldCap < fList.Capacity then\r
65296     FillChar( PChar( Integer( fList.fItems ) + OldCap * Sizeof( Pointer ) )^,\r
65297               (fList.Capacity - OldCap) * sizeof( Pointer ), 0 );\r
65298 end;\r
65300 { ----------------------------------------------------------------------\r
65302                 TAction and TActionList\r
65304 ----------------------------------------------------------------------- }\r
65305 //[function NewActionList]\r
65306 function NewActionList(AOwner: PControl): PActionList;\r
65307 begin\r
65308   {-}\r
65309   New( Result, Create );\r
65310   {+} {++}(* Result := PActionList.Create; *){--}\r
65311   with Result{-}^{+} do begin\r
65312     FActions:=NewList;\r
65313     FOwner:=AOwner;\r
65314     RegisterIdleHandler(DoUpdateActions);\r
65315   end;\r
65316 end;\r
65317 //[END NewActionList]\r
65319 //[function NewAction]\r
65320 function NewAction(const ACaption, AHint: string; AOnExecute: TOnEvent): PAction;\r
65321 begin\r
65322   {-}\r
65323   New( Result, Create );\r
65324   {+} {++}(* Result := PAction.Create; *){--}\r
65325   with Result{-}^{+} do begin\r
65326     FControls:=NewList;\r
65327     Enabled:=True;\r
65328     Visible:=True;\r
65329     Caption:=ACaption;\r
65330     Hint:=AHint;\r
65331     OnExecute:=AOnExecute;\r
65332   end;\r
65333 end;\r
65334 //[END NewAction]\r
65336 { TAction }\r
65338 //[procedure TAction.LinkCtrl]\r
65339 procedure TAction.LinkCtrl(ACtrl: PObj; ACtrlKind: TCtrlKind; AItemID: integer; AUpdateProc: TOnUpdateCtrlEvent);\r
65340 var\r
65341   cr: PControlRec;\r
65342 begin\r
65343   New(cr);\r
65344   with cr^ do begin\r
65345     Ctrl:=ACtrl;\r
65346     CtrlKind:=ACtrlKind;\r
65347     ItemID:=AItemID;\r
65348     UpdateProc:=AUpdateProc;\r
65349   end;\r
65350   FControls.Add(cr);\r
65351   AUpdateProc(cr);\r
65352 end;\r
65354 //[procedure TAction.LinkControl]\r
65355 procedure TAction.LinkControl(Ctrl: PControl);\r
65356 begin\r
65357   LinkCtrl(Ctrl, ckControl, 0, UpdateCtrl);\r
65358   Ctrl.OnClick:=DoOnControlClick;\r
65359 end;\r
65361 //[procedure TAction.LinkMenuItem]\r
65362 procedure TAction.LinkMenuItem(Menu: PMenu; MenuItemIdx: integer);\r
65363 {$IFDEF _FPC}\r
65364 var\r
65365   arr1_DoOnMenuItem: array[ 0..0 ] of TOnMenuItem;\r
65366 {$ENDIF _FPC}\r
65367 begin\r
65368   LinkCtrl(Menu, ckMenu, MenuItemIdx, UpdateMenu);\r
65369   {$IFDEF _FPC}\r
65370   arr1_DoOnMenuItem[ 0 ] := DoOnMenuItem;\r
65371   Menu.AssignEvents(MenuItemIdx, arr1_DoOnMenuItem);\r
65372   {$ELSE}\r
65373   Menu.AssignEvents(MenuItemIdx, [ DoOnMenuItem ]);\r
65374   {$ENDIF}\r
65375 end;\r
65377 //[procedure TAction.LinkToolbarButton]\r
65378 procedure TAction.LinkToolbarButton(Toolbar: PControl; ButtonIdx: integer);\r
65379 {$IFDEF _FPC}\r
65380 var\r
65381   arr1_DoOnToolbarButtonClick: array[ 0..0 ] of TOnToolbarButtonClick;\r
65382 {$ENDIF _FPC}\r
65383 begin\r
65384   LinkCtrl(Toolbar, ckToolbar, ButtonIdx, UpdateToolbar);\r
65385   {$IFDEF _FPC}\r
65386   arr1_DoOnToolbarButtonClick[ 0 ] := DoOnToolbarButtonClick;\r
65387   Toolbar.TBAssignEvents(ButtonIdx, arr1_DoOnToolbarButtonClick);\r
65388   {$ELSE}\r
65389   Toolbar.TBAssignEvents(ButtonIdx, [DoOnToolbarButtonClick]);\r
65390   {$ENDIF}\r
65391 end;\r
65393 //[destructor TAction.Destroy]\r
65394 destructor TAction.Destroy;\r
65395 begin\r
65396   FControls.Release;\r
65397   FCaption:='';\r
65398   FShortCut:='';\r
65399   FHint:='';\r
65400   inherited;\r
65401 end;\r
65403 //[procedure TAction.DoOnControlClick]\r
65404 procedure TAction.DoOnControlClick(Sender: PObj);\r
65405 begin\r
65406   Execute;\r
65407 end;\r
65409 //[procedure TAction.DoOnMenuItem]\r
65410 procedure TAction.DoOnMenuItem(Sender: PMenu; Item: Integer);\r
65411 begin\r
65412   Execute;\r
65413 end;\r
65415 //[procedure TAction.DoOnToolbarButtonClick]\r
65416 procedure TAction.DoOnToolbarButtonClick(Sender: PControl; BtnID: Integer);\r
65417 begin\r
65418   Execute;\r
65419 end;\r
65421 //[procedure TAction.Execute]\r
65422 procedure TAction.Execute;\r
65423 begin\r
65424   if Assigned(FOnExecute) and FEnabled then\r
65425     FOnExecute(PObj( @Self ));\r
65426 end;\r
65428 //[procedure TAction.SetCaption]\r
65429 procedure TAction.SetCaption(const Value: string);\r
65430 var\r
65431   i: integer;\r
65432   c, ss: string;\r
65434 begin\r
65435   i:=Pos(#9, Value);\r
65436   if i <> 0 then begin\r
65437     c:=Copy(Value, 1, i - 1);\r
65438     ss:=Copy(Value, i + 1, MaxInt);\r
65439   end\r
65440   else begin\r
65441     c:=Value;\r
65442     ss:='';\r
65443   end;\r
65444   if (FCaption = c) and (FShortCut = ss) then exit;\r
65445   FCaption:=c;\r
65446   FShortCut:=ss;\r
65447   UpdateControls;\r
65448 end;\r
65450 //[procedure TAction.SetChecked]\r
65451 procedure TAction.SetChecked(const Value: boolean);\r
65452 begin\r
65453   if FChecked = Value then exit;\r
65454   FChecked := Value;\r
65455   UpdateControls;\r
65456 end;\r
65458 //[procedure TAction.SetEnabled]\r
65459 procedure TAction.SetEnabled(const Value: boolean);\r
65460 begin\r
65461   if FEnabled = Value then exit;\r
65462   FEnabled := Value;\r
65463   UpdateControls;\r
65464 end;\r
65466 //[procedure TAction.SetHelpContext]\r
65467 procedure TAction.SetHelpContext(const Value: integer);\r
65468 begin\r
65469   if FHelpContext = Value then exit;\r
65470   FHelpContext := Value;\r
65471   UpdateControls;\r
65472 end;\r
65474 //[procedure TAction.SetHint]\r
65475 procedure TAction.SetHint(const Value: string);\r
65476 begin\r
65477   if FHint = Value then exit;\r
65478   FHint := Value;\r
65479   UpdateControls;\r
65480 end;\r
65482 //[procedure TAction.SetOnExecute]\r
65483 procedure TAction.SetOnExecute(const Value: TOnEvent);\r
65484 begin\r
65485   if @FOnExecute = @Value then exit;\r
65486   FOnExecute:=Value;\r
65487   UpdateControls;\r
65488 end;\r
65490 //[procedure TAction.SetVisible]\r
65491 procedure TAction.SetVisible(const Value: boolean);\r
65492 begin\r
65493   if FVisible = Value then exit;\r
65494   FVisible := Value;\r
65495   UpdateControls;\r
65496 end;\r
65498 //[procedure TAction.UpdateControls]\r
65499 procedure TAction.UpdateControls;\r
65500 var\r
65501   i: integer;\r
65502 begin\r
65503   with FControls{-}^{+} do\r
65504     for i:=0 to Count - 1 do\r
65505       PControlRec(Items[i]).UpdateProc(Items[i]);\r
65506 end;\r
65508 //[procedure TAction.UpdateCtrl]\r
65509 procedure TAction.UpdateCtrl(Sender: PControlRec);\r
65510 begin\r
65511   with Sender^, PControl(Ctrl){-}^{+} do begin\r
65512     if Caption <> Self.FCaption then\r
65513       Caption:=Self.FCaption;\r
65514     if Enabled <> Self.FEnabled then\r
65515       Enabled:=Self.FEnabled;\r
65516     if Checked <> Self.FChecked then\r
65517       Checked:=Self.FChecked;\r
65518     if Visible <> Self.FVisible then\r
65519       Visible:=Self.FVisible;\r
65520   end;\r
65521 end;\r
65523 //[procedure TAction.UpdateMenu]\r
65524 procedure TAction.UpdateMenu(Sender: PControlRec);\r
65525 var\r
65526   s: string;\r
65527 begin\r
65528   with Sender^, PMenu(Ctrl).Items[ItemID]{-}^{+} do begin\r
65529     s:=Self.FCaption;\r
65530     if Self.FShortCut <> '' then\r
65531       s:=s + #9 + Self.FShortCut;\r
65532     if Caption <> s then\r
65533       Caption:=s;\r
65534     if Enabled <> Self.FEnabled then\r
65535       Enabled:=Self.FEnabled;\r
65536     if Checked <> Self.FChecked then\r
65537       Checked:=Self.FChecked;\r
65538     if Visible <> Self.FVisible then\r
65539       Visible:=Self.FVisible;\r
65540     if HelpContext <> Self.FHelpContext then\r
65541       HelpContext:=Self.FHelpContext;\r
65542     if Self.FAccelerator.Key <> 0 then {YS}  // Äîáàâèòü\r
65543       Accelerator:=Self.FAccelerator;\r
65544   end;\r
65545 end;\r
65547 //[procedure TAction.UpdateToolbar]\r
65548 procedure TAction.UpdateToolbar(Sender: PControlRec);\r
65549 var\r
65550   i: integer;\r
65551   s: string;\r
65552 begin\r
65553   with Sender^, PControl(Ctrl){-}^{+} do begin\r
65554     i:=TBIndex2Item(ItemID);\r
65555     s:=TBButtonText[i];\r
65556     if (s <> '') and (s <> Self.FCaption) then\r
65557       TBButtonText[i]:=Self.FCaption;\r
65558     TBSetTooltips(i, [PChar(Self.FHint)]);\r
65559     if TBButtonEnabled[ItemID] <> Self.FEnabled then\r
65560       TBButtonEnabled[ItemID]:=Self.FEnabled;\r
65561     if TBButtonVisible[ItemID] <> Self.FVisible then\r
65562       TBButtonVisible[ItemID]:=Self.FVisible;\r
65563     if TBButtonChecked[ItemID] <> Self.FChecked then\r
65564       TBButtonChecked[ItemID]:=Self.FChecked;\r
65565   end;\r
65566 end;\r
65568 //[procedure TAction.SetAccelerator]\r
65569 procedure TAction.SetAccelerator(const Value: TMenuAccelerator);\r
65570 begin\r
65571   if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then exit;\r
65572   FAccelerator := Value;\r
65573   FShortCut:=GetAcceleratorText(FAccelerator);  // {YS}\r
65574   UpdateControls;\r
65575 end;\r
65577 { TActionList }\r
65579 //[function TActionList.Add]\r
65580 function TActionList.Add(const ACaption, AHint: string; OnExecute: TOnEvent): PAction;\r
65581 begin\r
65582   Result:=NewAction(ACaption, AHint, OnExecute);\r
65583   FActions.Add(Result);\r
65584 end;\r
65586 //[procedure TActionList.Clear]\r
65587 procedure TActionList.Clear;\r
65588 begin\r
65589   while FActions.Count > 0 do\r
65590     Delete(0);\r
65591   FActions.Clear;  \r
65592 end;\r
65594 //[procedure TActionList.Delete]\r
65595 procedure TActionList.Delete(Idx: integer);\r
65596 begin\r
65597   Actions[Idx].Free;\r
65598   FActions.Delete(Idx);\r
65599 end;\r
65601 //[destructor TActionList.Destroy]\r
65602 destructor TActionList.Destroy;\r
65603 begin\r
65604   UnRegisterIdleHandler(DoUpdateActions);\r
65605   Clear;\r
65606   FActions.Free;\r
65607   inherited;\r
65608 end;\r
65610 //[procedure TActionList.DoUpdateActions]\r
65611 procedure TActionList.DoUpdateActions(Sender: PObj);\r
65612 begin\r
65613   if Assigned(FOnUpdateActions) and (GetActiveWindow = FOwner.Handle) then\r
65614     FOnUpdateActions(PObj( @Self ));\r
65615 end;\r
65617 //[function TActionList.GetActions]\r
65618 function TActionList.GetActions(Idx: integer): PAction;\r
65619 begin\r
65620   Result:=FActions.Items[Idx];\r
65621 end;\r
65623 //[function TActionList.GetCount]\r
65624 function TActionList.GetCount: integer;\r
65625 begin\r
65626   Result:=FActions.Count;\r
65627 end;\r
65629 {$IFDEF USE_CUSTOMEXTENSIONS}\r
65630   {$I CUSTOM_CODE_EXTENSION.inc} // See comments in TControl\r
65631 {$ENDIF USE_CUSTOMEXTENSIONS}\r
65633 //[initialization]\r
65634 initialization\r
65635 //[finalization]\r
65636 finalization\r
65637 {$IFDEF UNLOAD_RICHEDITLIB}\r
65638   if FRichEditModule <> 0 then\r
65639     FreeLibrary( FRichEditModule );\r
65640 {$ENDIF UNLOAD_RICHEDITLIB}\r
65642 //[END OF KOL.pas]\r
65643 end.\r